canvas繪製多邊形進度展現圖,水波浪效果

參考:
多邊形函數:https://www.cnblogs.com/anxia...
canvas畫波浪進度球:https://www.cnblogs.com/pagod...html

最近項目中須要一個六邊形的水波紋進度,在網上只找到了一個進度球的繪製方法,而後結合了一下多邊形的繪製方法,代碼以下
案例1:
代碼:canvas

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    body{
        position: relative;
        width:100vw;
        height: 100vh;
        margin: 0;
    }
    canvas{
        position: absolute;
        left: 50%;
        top: 50%;
        margin-left: -150px;
        margin-top: -150px;
        border: 1px dashed rgba(0,0,0,0.1)
    }
</style>
<body>
<canvas id="c"></canvas>
<input type="range" id="r" min="0" max="100" step="1">
</body>
<script>
    var canvas = document.getElementById('c');
    var ctx = canvas.getContext('2d');
    var range = document.getElementById('r');

    //range控件信息
    var rangeValue = range.value;
    var nowRange = 40;   //用於作一個臨時的range

    //畫布屬性
    var mW = canvas.width = 350;
    var mH = canvas.height = 350;
    var lineWidth = 1;

    //圓屬性
    var r = mH / 2; //圓心
    var cR = r - 32 * lineWidth; //圓半徑

    //Sin 曲線屬性
    var sX = 0;
    var axisLength = mW; //軸長
    var waveWidth = 0.008 ;   //波浪寬度,數越小越寬
    var waveHeight = 6; //波浪高度,數越大越高
    var speed = 0.09; //波浪速度,數越大速度越快
    var xOffset = 0; //波浪x偏移量

    ctx.lineWidth = lineWidth;

    //畫圈函數
    var IsdrawCircled = false;
    var drawCircle = function(){
        // 畫多邊形函數
        function drawPath(x, y, n, r)
        {
            var i,ang;
            ang = Math.PI*2/n //旋轉的角度
            ctx.save();//保存狀態
            ctx.fillStyle ='rgba(255,0,0,.3)';//填充紅色,半透明
            ctx.strokeStyle ='#000)';//填充綠色
            ctx.lineWidth = 2;//設置線寬
            ctx.translate(x, y);//原點移到x,y處,即要畫的多邊形中心
            ctx.moveTo(0, -r);//據中心r距離處畫點
            ctx.beginPath();
            for(i = 0;i < n; i ++)
            {
                ctx.rotate(ang)//旋轉
                ctx.lineTo(0, -r);//據中心r距離處連線
            }
            ctx.closePath();
            ctx.stroke();
            ctx.fill();
            ctx.restore();//返回原始狀態
        }
        drawPath(r, r, 6, cR+1)
        drawPath(r, r, 6, cR)
        ctx.clip();
        IsdrawCircled = true;
    }

    //畫sin 曲線函數
    var drawSin = function(xOffset, color, waveHeight){
        ctx.save();

        var points=[];  //用於存放繪製Sin曲線的點

        ctx.beginPath();
        //在整個軸長上取點
        for(var x = sX; x < sX + axisLength; x += 20 / axisLength){
            //此處座標(x,y)的取點,依靠公式 「振幅高*sin(x*振幅寬 + 振幅偏移量)」
            var y = Math.sin((-sX - x) * waveWidth + xOffset) * 0.8 + 0.1;

            var dY = mH * (1 - nowRange / 100 );

            points.push([x, dY + y * waveHeight]);
            ctx.lineTo(x, dY + y * waveHeight);
        }

        //封閉路徑
        ctx.lineTo(axisLength, mH);
        ctx.lineTo(sX, mH);
        ctx.lineTo(points[0][0],points[0][1]);
        ctx.fillStyle = color;
        ctx.fill();

        ctx.restore();
    };

    var render = function(){
        ctx.clearRect(0, 0, mW, mH);

        rangeValue = range.value;
        console.log(rangeValue);
        if(IsdrawCircled == false){
            drawCircle();
        }

        if(nowRange <= rangeValue){
            var tmp = 1;
            nowRange += tmp;
        }

        if(nowRange > rangeValue){
            var tmp = 1;
            nowRange -= tmp;
        }

        drawSin(xOffset+Math.PI*0.7, 'rgba(28, 134, 209, 0.5)', 18);
        drawSin(xOffset, '#1c86d1', 18);
        drawText();

        xOffset += speed;
        requestAnimationFrame(render);
    }
    //寫百分比文本函數
    var drawText = function(){
        ctx.save();

        var size = 0.4*cR;
        ctx.font = size + 'px Microsoft Yahei';
        ctx.textAlign = 'center';
        ctx.fillStyle = "rgba(06, 85, 128, 0.5)";
        ctx.fillText(~~nowRange + '%', r, r + size / 2);

        ctx.restore();
    };

    render();


</script>
</html>

clipboard.png
效果圖函數


案例2:
代碼:this

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    body{
        position: relative;
        width:100vw;
        height: 100vh;
        margin: 0;
    }
    canvas{
        position: absolute;
        left: 50%;
        top: 50%;
        margin-left: -150px;
        margin-top: -150px;
        border: 1px dashed rgba(0,0,0,0.1)
    }
</style>
<body>
<canvas id="c"></canvas>
</body>
<script>

    var canvas = document.getElementById('c');
    var ctx = canvas.getContext('2d');

    // 初始化參數
    let oW = 236,
        oH = 267,
        lineWidth = 1,
        bOffset = 2,
        border = 3, //X軸偏移量
        r,
        cR,
        axisLength,
        unit, // 浪寬
        range = .3, // 浪高
        nowrange = .3,
        sp = 0,     // 週期偏移量
        nowdata = 0,
        value = 0.5, // 百分比
        waveupsp = 0.002; // 水波上漲速度

    canvas.width = oW;
    canvas.height = oH;
    ctx.lineWidth = lineWidth;
    var triangleH = Math.ceil(oH/4);
    // 外六邊形
    var arcStack = [
        [oW/2, 0],
        [oW-bOffset, triangleH],
        [oW-bOffset,oH-triangleH],
        [oW/2, oH],
        [bOffset, oH-triangleH],
        [bOffset, triangleH]
    ];
    var cStartPoint = arcStack.shift();
    // 內六邊形
    var arcStackInner = [
      [oW/2, border],
      [oW-border, triangleH + border/2],
      [oW-border, oH-triangleH-border/2],
      [oW/2, oH-border],
      [border, oH - triangleH - border/2],
      [border,triangleH + border/2]
    ];
    var cStartPointInner = arcStackInner.shift();
    r = oW / 2;
    cR = oH/2 - border - lineWidth;

    ctx.beginPath();
    axisLength = oW - 2*border;
    unit = axisLength / 20;
    ctx.beginPath();
    renderBorder();
    render();
    function renderBorder() {
        ctx.beginPath();
        ctx.strokeStyle = "#000000";
        ctx.fillStyle = "#000000";
        ctx.moveTo(cStartPoint[0], cStartPoint[1]);
        while (arcStack.length) {
            var temp = arcStack.shift();
            this.ctx.lineTo(temp[0], temp[1]);
            ctx.stroke();
        }
        ctx.lineTo(cStartPoint[0], cStartPoint[1]);
        ctx.stroke();
        ctx.fill();
        ctx.globalCompositeOperation = 'source-over';

        ctx.beginPath();
        ctx.fillStyle = '#fff'
        ctx.strokeStyle = '#fff';
        ctx.moveTo(cStartPointInner[0], cStartPointInner[1]);
        while (arcStackInner.length) {
            var temp = arcStackInner.shift();
            this.ctx.lineTo(temp[0], temp[1]);
            ctx.stroke();
        }
        ctx.lineTo(cStartPointInner[0], cStartPointInner[1]);
        ctx.stroke();
        ctx.fill();
        ctx.restore();
        ctx.clip();
        ctx.save();
        ctx.globalCompositeOperation = 'source-over';
    }

    function render() {
        ctx.clearRect(0,0,oW,oH);
        if (value >= 0.85) {
            if (nowrange > range/4) {
                var t = range * 0.01;
                nowrange -= t;
            }
        } else if (value <= 0.1) {
            if (nowrange < range*1.5) {
                var t = range * 0.01;
                nowrange += t;
            }
        } else {
            if (nowrange <= range) {
                var t = range * 0.01;
                nowrange += t;
            }

            if (nowrange >= range) {
                var t = range * 0.01;
                nowrange -= t;
            }
        }

        if((value - nowdata) > 0) {
            nowdata += waveupsp;
        }

        if((value - nowdata) < 0){
            nowdata -= waveupsp
        }

        sp += 0.07;
        if(value){
            drawSine();
        }
        requestAnimationFrame(render)
    }

    function drawSine() {
        ctx.beginPath();
        ctx.save();
        var Stack = [];
        for (let i = border; i <= border+axisLength; i+=20/axisLength) {
            var x = sp + (border + i) / unit;
            var y = Math.sin(x) * nowrange;
            var dx = i;

            var dy = 2*cR*(1-nowdata) + border - (unit * y);
            ctx.lineTo(dx, dy);
            Stack.push([dx,dy]);
        }
        var startP = Stack[0]
        ctx.lineTo(border + axisLength,oH + border);
        ctx.lineTo(border,oH+border);
        ctx.lineTo(startP[0], startP[1])
        ctx.fillStyle = "#50bff7";
        ctx.fill();
        ctx.restore();
    }
     function drawText() {
        ctx.save();

        var size = 0.4*cR;
        ctx.font = size + 'px Microsoft Yahei';
        ctx.textAlign = 'center';
        ctx.fillStyle = "rgba(06, 85, 128, 0.5)";
        let txt = (nowdata.toFixed(2)*100).toFixed(0) + '%';
        ctx.fillText(txt, r, r + size / 2);

        ctx.restore();
    }
</script>
</html>

clipboard.png

效果圖spa

相關文章
相關標籤/搜索