如何在 HTML5 中动画和擦除弧线

Posted

技术标签:

【中文标题】如何在 HTML5 中动画和擦除弧线【英文标题】:How to animate and erase an arc in HTML5 【发布时间】:2012-08-12 02:08:10 【问题描述】:

这是我的问题:我有一个动画,构建是圆形的。见:http://jsfiddle.net/2TUnE/

JavaScript:

var currentEndAngle = 0
var currentStartAngle = 0;
var currentColor = 'black';

setInterval(draw, 50);


function draw()  /***************/

    var can = document.getElementById('canvas1'); // GET LE CANVAS
    var canvas = document.getElementById("canvas1");
    var context = canvas.getContext("2d");
    var x = canvas.width / 2;
    var y = canvas.height / 2;
    var radius = 75;

    var startAngle = currentStartAngle * Math.PI;
    var endAngle = (currentEndAngle) * Math.PI;

    currentEndAngle = currentEndAngle + 0.01;

    var counterClockwise = false;

    context.beginPath();
    context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
    context.lineWidth = 15;
    // line color
    context.strokeStyle = currentColor;
    context.stroke();

    /************************************************/

当圆圈完全绘制好后,我希望它开始擦除,就像它被创建的方式一样(所以慢慢地去除黑色)。一旦整个圆圈被擦除,我会再次创建黑色圆圈,创建某种“等待/加载”效果。

我尝试做的是检查 currentEndAngle 是否为 2(所以圆圈是完整的),然后移动 startAngle,但它不起作用。

有什么想法吗?

谢谢!

编辑:忘了说,动画将覆盖图像,所以它必须是“透明的”而不是白色的

【问题讨论】:

您是否考虑过编写动画 SVG 并将其嵌入为图像? 我不知道它是什么。这是我第一次接触 html5。我会调查一下。 SVG 是一种原生支持动画的矢量图形图像格式。有关规范,请参阅 w3.org/TR/SVG/animate.html 和一些示例,请参阅 developer.mozilla.org/en-US/docs/SVG/SVG_animation_with_SMIL。 SVG 是 HTML5 规范的一部分。 【参考方案1】:

查看这个 JSFiddle 中的内容:http://jsfiddle.net/fNTsA/

这个方法基本上就是你的代码,只是我们使用模数来控制状态。检查半径是否为 2 只对了一半,要切换绘制白色或绘制黑色,您应该将半径取模 2 的一半。第一次有 floor(0..2/2) % 2 == 0 时,第二个你有 floor(2..4/2) % 2 == 1,依此类推。

另外,因为线条是抗锯齿的,它有助于让起始角度覆盖已经绘制的内容,否则您可能会得到额外的白线,您可能不想要。同理,在画白色圆圈的时候,应该画一条稍粗的线(半径越小,线越粗)。否则,抗锯齿会留下一些 schmutz - 已擦除圆圈的微弱轮廓。

我将半径和宽度放入您放在顶部的全局变量中:

var lineRadius = 75;
var lineWidth = 15;

同样这是我的模数,非常标准:

currentStartAngle = currentEndAngle - 0.01;
currentEndAngle = currentEndAngle + 0.01;

if (Math.floor(currentStartAngle / 2) % 2) 
  currentColor = "white";
  radius = lineRadius - 1;
  width = lineWidth + 3;
 else 
  currentColor = "black";
  radius = lineRadius;
  width = lineWidth;

【讨论】:

你好!感谢您的代码!有什么方法可以在不使用白色的情况下完成,因为这个动画将在非纯色背景上? 兄弟,这完全有可能现在挖掘你想做的事情.. 如果你想用透明度绘制,必须将上下文的 globalCompositeOperation 设置为“destination-out”。 +1 比我更好的答案。 1. 你理解了这个问题。 2. 关于调整起始角度以覆盖前一个循环上绘制的线的一小部分的好技巧。这是你的小提琴的一个分支,有一些改进jsfiddle.net/3E2V9【参考方案2】:

有趣的挑战!尝试以下(更新小提琴here)。我试图包含大量的 cmets 来展示我的想法。

    // Moved these to global scope as you don't want to re-declare 
    // them in your draw method each time your animation loop runs
    var canvas = document.getElementById("canvas1");
    var context = canvas.getContext("2d");
    var x = canvas.width / 2;
    var y = canvas.height / 2;
    var radius = 75;

    // Use objects to hold our draw and erase props
    var drawProps = 
      startAngle: 0,
      speed: 2,
      color: 'black',
      counterClockwise: false,
      globalCompositeOperation: context.globalCompositeOperation,
      lineWidth: 15            
    ;

    var eraseProps = 
      startAngle: 360,
      speed: -2,
      color: 'white',
      counterClockwise: true,
      globalCompositeOperation: "destination-out",
      lineWidth: 17 // artefacts appear unless we increase lineWidth for erase
    ;

    // Let's work in degrees as they're easier for humans to understand
    var degrees = 0; 
    var props = drawProps;

    // start the animation loop
    setInterval(draw, 50);

    function draw()  /***************/

        degrees += props.speed;

        context.beginPath();
        context.arc(
            x, 
            y, 
            radius, 
            getRadians(props.startAngle), 
            getRadians(degrees), 
            props.counterClockwise
        );
        context.lineWidth = props.lineWidth;
        context.strokeStyle = props.color;
        context.stroke();

        // Start erasing when we hit 360 degrees
        if (degrees >= 360) 
            context.closePath();
            props = eraseProps;
            context.globalCompositeOperation = props.globalCompositeOperation;
        

        // Start drawing again when we get back to 0 degrees
        if (degrees <= 0) 
            canvas.width = canvas.width; // Clear the canvas for better performance (I think)
            context.closePath();
            props = drawProps;
            context.globalCompositeOperation = props.globalCompositeOperation;
        
        /************************************************/
      

    // Helper method to convert degrees to radians
    function getRadians(degrees) 
        return degrees * (Math.PI / 180);
    

【讨论】:

非常感谢! cmets帮了大忙!你知道在不使用白色的情况下是否可以做类似的事情。我将在图像上使用动画 您希望在擦除时将 context.globalCompositeOperation 设置为“destination-out”。我已经更新了答案和小提琴jsfiddle.net/GCvQ5/2

以上是关于如何在 HTML5 中动画和擦除弧线的主要内容,如果未能解决你的问题,请参考以下文章

如何沿弧线为图像设置动画

基于STM32的Flash擦除方式

矢量排序和擦除不起作用

获得平均值和擦除数字有很大差异[关闭]

如何将插入符号形状动画化为平滑的弧线?

svg path 画弧线