技术就餐

导航

canvas水波上涨进度动画

 

 
 
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>水波上涨进度动画</title>
    <style>
      body {
        display: flex;
        flex-flow: column wrap;
        justify-content: center;
        align-items: center;
      }
    </style>
  </head>
  <body>
    <canvas id="c">当前浏览器不支持canvas 请升级!</canvas>
  </body>
  <script>
    function draw(data, color) {
      let canvas = document.getElementById("c");
      let ctx = canvas.getContext("2d");
      let oRange = document.getElementsByName("range")[0];
      let M = Math;
      let Sin = M.sin;
      let Cos = M.cos;
      let Sqrt = M.sqrt;
      let Pow = M.pow;
      let PI = M.PI;
      let Round = M.round;
      let oW = (canvas.width = 250);
      let oH = (canvas.height = 250);
      // 线宽
      let lineWidth = 2;
      // 大半径
      let r = oW / 2;
      let cR = r - 10 * lineWidth;
      ctx.beginPath();
      ctx.lineWidth = lineWidth;
      // 水波动画初始参数
      let axisLength = 2 * r - 16 * lineWidth; // Sin 图形长度
      let unit = axisLength / 9; // 波浪宽
      let range = 0.4; // 浪幅
      let nowrange = range;
      let xoffset = 8 * lineWidth; // x 轴偏移量
      data = ~~data / 100; // 数据量
      let sp = 0; // 周期偏移量
      let nowdata = 0;
      let waveupsp = 0.006; // 水波上涨速度
      // 圆动画初始参数
      let arcStack = []; // 圆栈
      let bR = r - 8 * lineWidth;
      let soffset = -(PI / 2); // 圆动画起始位置
      let circleLock = true; // 起始动画锁
      // 获取圆动画轨迹点集
      for (var i = soffset; i < soffset + 2 * PI; i += 1 / (8 * PI)) {
        arcStack.push([r + bR * Cos(i), r + bR * Sin(i)]);
      }
      // 圆起始点
      cStartPoint = arcStack.shift();
      ctx.strokeStyle = "#1c86d1";
      ctx.moveTo(cStartPoint[0], cStartPoint[1]);
      // 开始渲染
      render();

      function drawSine() {
        ctx.beginPath();
        ctx.save();
        var Stack = []; // 记录起始点和终点坐标
        for (var i = xoffset; i <= xoffset + axisLength; i += 20 / axisLength) {
          var x = sp + (xoffset + i) / unit;
          var y = Sin(x) * nowrange;
          var dx = i;
          var dy = 2 * cR * (1 - nowdata) + (r - cR) - unit * y;
          ctx.lineTo(dx, dy);
          Stack.push([dx, dy]);
        }
        // 获取初始点和结束点
        var startP = Stack[0];
        var endP = Stack[Stack.length - 1];
        ctx.lineTo(xoffset + axisLength, oW);
        ctx.lineTo(xoffset, oW);
        ctx.lineTo(startP[0], startP[1]);
        ctx.fillStyle = color;
        ctx.fill();
        ctx.restore();
      }

      function drawText() {
        ctx.globalCompositeOperation = "source-over";
        var size = 0.4 * cR;
        txt = (nowdata.toFixed(2) * 100).toFixed(0) + "%";
        var fonty = r + size / 2;
        var fontx = r - size * 0.8;
        ctx.fillStyle = "black";
        ctx.textAlign = "center";
        ctx.fillText(txt, r + 5, r - 50);
      }
      //最外面淡黄色圈
      function drawCircle() {
        ctx.beginPath();
        ctx.lineWidth = 1;
        ctx.strokeStyle = color;
        ctx.arc(r, r, cR + 1, 0, 2 * Math.PI);
        ctx.stroke();
        ctx.restore();
      }

      //裁剪中间水圈
      function clipCircle() {
        ctx.beginPath();
        ctx.arc(r, r, cR, 0, 2 * Math.PI, false);
        ctx.clip();
      }
      //渲染canvas
      function render() {
        ctx.clearRect(0, 0, oW, oH);
        //最外面淡黄色圈
        drawCircle();
        //裁剪中间水圈
        clipCircle();
        if (data >= 0.85) {
          if (nowrange > range / 4) {
            var t = range * 0.01;
            nowrange -= t;
          }
        } else if (data <= 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 (data - nowdata > 0) {
          nowdata += waveupsp;
        }
        if (data - nowdata < 0) {
          nowdata -= waveupsp;
        }
        sp += 0.07;
        // 开始水波动画
        drawSine();
        // 写字
        drawText();
        requestAnimationFrame(render);
      }
    }

    draw(50, "skyblue");
  </script>
</html>

posted on 2021-12-17 21:29  技术就餐  阅读(88)  评论(0编辑  收藏  举报