RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1361323
Accepted
Alexandr_TT
Alexandr_TT
Asked:2022-05-15 19:45:57 +0000 UTC2022-05-15 19:45:57 +0000 UTC 2022-05-15 19:45:57 +0000 UTC

如何使用 Canvas 制作圆形进度条?

  • 772

如何在<canvas>没有问题的情况下做一个圆圈

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

ctx.beginPath();
ctx.arc(100, 100, 90, 0, 2 * Math.PI);
ctx.strokeStyle = "#1CB3FE"
ctx.lineWidth = 10;
ctx.stroke();
<canvas width="400" height="400" </canvas>

问题 - 创建一个不断增长的进度条线的动画,即在canvasCSS 和 SVG 属性中找到类似物, stroke-dasharray以及stroke-dashoffset

问题:

如何重复canvas显示完成百分比的进度条动画:

在此处输入图像描述

svg {
  height: 90vh;
  margin: auto;
  display: block;
}

path {
  stroke-linecap: round;
  stroke-width: 6;
}

path.grey {
  stroke: #e7e7e8;
}

path.purple {
  stroke: url(#gradient);
  stroke-dasharray: 198;
  stroke-dashoffset: 198;
  animation: dash 3s ease-out forwards;
}

path.white {
  stroke: #ffffff;
  stroke-dasharray: 0px, 198px;
  stroke-dashoffset: 198;
  stroke-width: 3.5px;
  animation: dash 3s ease-out forwards;
}

@keyframes dash {
  to {
    stroke-dashoffset: 1; 
  }
}
<svg viewbox="0 0 100 100">
      <linearGradient id="gradient" x1="0" y1="0" x2="0" y2="100%">
           <stop offset="0%" stop-color="#56c4fb" />
           <stop offset="100%" stop-color="#0baeff" />
       </linearGradient>
       <path class="grey" d="M30,90 A40,40 0 1,1 80,90" fill='none' />
       <path id="purple" fill='none' class="purple" d="M30,90 A40,40 0 1,1 80,90" />
       <path id="white" fill='none' class="white" d="M30,90 A40,40 0 1,1 80,90" />
 </svg>

javascript
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. Krovorgen
    2022-05-15T20:23:42Z2022-05-15T20:23:42Z

    var flag = false;
    var time = 5000;
    var step = 1;
    document.addEventListener('DOMContentLoaded', function () {
        var percentage = document.querySelectorAll('.survey-results__percentage');
        var targetBox = document.querySelector('.survey-results__wrap');
        var current = document.documentElement.scrollTop;
        var target = targetBox.offsetTop - 200;
        var circles = document.querySelectorAll('.survey-results__circle');
    
        if (current >= target && !flag) {
            for (var i = 0; i < circles.length; i++) {
                circles[i].classList.add('active');
                outNum(parseFloat(percentage[i].dataset.percent), percentage[i]);
                flag = true;
            }
        }
    });
        
    function outNum(num, elem) {
      var e = elem;
      n = 0;
      var t = time / (num / step);
      var interval = setInterval(() => {
          n = n + step;
          if (n >= num) {
              clearInterval(interval);
              e.innerHTML = num.toString().replace('.', ',') + '%';
          } else {
              e.innerHTML = parseFloat(n).toFixed(2).toString().toString().replace('.', ',') + '%';
          }
      }, t);
    }
    .survey-results__wrap {
      display: flex;
    }
    
    .survey-results__block {
      max-width: 170px;
    }
    
    .survey-results__chart {
      margin-bottom: 10px;
      width: 170px;
      height: 170px;
    }
    
    .survey-results__circular {
      display: block;
      width: 100%;
      height: 100%;
    }
    
    .survey-results__circle {
      fill: none;
      stroke-width: 2.8;
      stroke: #58bdfc;
      animation: progress 2s ease-out forwards;
    }
    
    .survey-results__percentage {
      font-family: inherit;
      font-weight: 700;
      font-size: 8px;
      fill: #ec8d06;
      text-anchor: middle;
    }
    
    @keyframes progress {
      0% {
        stroke-dasharray: 0 100;
      }
    }
    <div class="survey-results__wrap">
        <div class="survey-results__block">
            <div class="survey-results__chart">
                <svg viewBox="0 0 36 36"
                     class="survey-results__circular survey-results__circular--accent">
                    <path class="survey-results__circle" stroke-dasharray="98.7, 100"
                          d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"/>
                    <text x="18" y="20.35" class="survey-results__percentage" data-percent="98.7">
                        98,7%
                    </text>
                </svg>
            </div>
        </div>
    </div>

    或者,您也可以在 stroke-dasharray 中将其更改为所需的百分比

    • 4
  2. Best Answer
    Grundy
    2022-05-15T21:21:29Z2022-05-15T21:21:29Z

    使用canvas动画时,您必须自己做。

    例如,使用requestAnimationFrame, 来调用每个渲染步骤。

    要画一个圆,您可以使用.arc. 此方法允许您指定圆的中心以及要绘制的弧度段

    为了方便计算,您可以将坐标系移动到圆心,使用.translate

    现在设置开始角度、结束角度和改变步长就足够了,每次改变当前角度时调用一次重绘。

    例如:

    const canvas = document.querySelector('canvas');
    const ctx = canvas.getContext('2d');
    const startAngle = Math.PI / 6;
    const endAngle = 2 * Math.PI - startAngle;
    
    const stepAngle = Math.PI / 108;
    let curAngle = startAngle;
    
    var grad = ctx.createLinearGradient(0, 0, 100, 0);
    grad.addColorStop(0, "#56c4fb");
    grad.addColorStop(1, "#0baeff");
    
    function drawArc(start, end, strokeStyle) {
      ctx.save()
      ctx.translate(120, 120);
      ctx.rotate(Math.PI / 2);
      ctx.strokeStyle = strokeStyle;
      ctx.beginPath();
      ctx.lineWidth = 20;
      ctx.lineCap = 'round';
      ctx.arc(0, 0, 100, start, end);
      ctx.stroke();
      ctx.restore();
    }
    
    function drawCircle(angle) {
      ctx.save();
      ctx.translate(120, 120);
      ctx.rotate(Math.PI / 2);
      ctx.fillStyle = 'white';
      ctx.translate(Math.cos(angle) * 100, Math.sin(angle) * 100)
      ctx.beginPath();
      ctx.arc(0, 0, 8, 0, 2 * Math.PI);
      ctx.fill();
      ctx.restore();
    }
    
    function drawText(length, cur) {
      const percent = (cur / length * 100).toFixed(0);
      ctx.save();
      ctx.translate(120, 120);
      ctx.font = 'bold 50px sans-serif';
      ctx.textBaseline = 'middle';
      ctx.textAlign = 'center';
      ctx.beginPath();
      ctx.fillText(percent + '%', 0, 0);
      ctx.stroke();
      ctx.restore();
    }
    
    function drawSpeed(start, end, cur) {
      drawArc(start, end, 'lightgrey');
      drawArc(start, cur, grad);
      drawText(end - start, cur - start);
      if (cur !== end) {
        drawCircle(cur);
      }
    }
    
    requestAnimationFrame(function draw(t) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      curAngle = Math.min(curAngle + stepAngle, endAngle);
      drawSpeed(startAngle, endAngle, curAngle);
      if (curAngle < endAngle) {
        requestAnimationFrame(draw);
      }
    })
    <canvas width="400" height="400"> </canvas>

    • 3
  3. Виктор Карев
    2022-05-15T21:06:44Z2022-05-15T21:06:44Z

    像这样的地方:

    const canvas = document.querySelector('canvas');
    const ctx = canvas.getContext('2d');
    const from = 0.75 * Math.PI;
    const to = 2.25 * Math.PI;
    var progress = 0.65;
    
    ctx.beginPath();
    ctx.arc(100, 100, 90, from, to);
    ctx.strokeStyle = "#ccc"
    ctx.lineWidth = 10;
    ctx.stroke();
    
    ctx.beginPath();
    ctx.arc(100, 100, 90, from, from + (to-from)*progress);
    ctx.strokeStyle = "#1CB3FE"
    ctx.lineWidth = 10;
    ctx.stroke();
    <canvas width="400" height="400" </canvas>

    更改进度值并重绘。

    • 2

相关问题

  • 第二个 Instagram 按钮的 CSS 属性

  • 由于模糊,内容不可见

  • 弹出队列。消息显示不正确

  • 是否可以在 for 循环中插入提示?

  • 如何将 JSON 请求中的信息输出到数据表 Vuetify vue.js?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5