如何在HTML5 Canvas中为上下文填充不透明度设置动画

时间:2017-12-28 17:26:28

标签: javascript html5-canvas

是否可以告诉我如何在HTML Canvas中为上下文的fill不透明度添加动画效果(或添加淡入淡出效果)?

例如,在以下示例中,ctx.fillStyle填充不透明度设置为0,如何将其设置为1



var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

ctx.beginPath(); 
ctx.fillStyle = 'rgba(255, 165, 0, 0)';
ctx.rect(20, 20, 150, 100);
ctx.fill();

<canvas id="myCanvas" width="300" height="300" style="border:1px solid #d3d3d3;">
   Your browser does not support the HTML5 canvas tag.
</canvas>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

您可以使用window.requestAnimationFrame

实现此目的

var
  /* Save the canvas' context. */
  ctx = document.getElementById("myCanvas").getContext("2d"),
  
  /* The starting opacity. */
  opacity = 0,
  
  /* The duration of the animation in milliseconds. */
  duration = 500,
  
  /* Cache the starting time in milliseconds since page load. */
  past = performance.now();

/* The animation function. */
function animate(present) {
  /* Find the difference between the previous and current times. */
  var step = present - past;
  
  /* Set the present time to past. */
  past = present;
  
  /* Increment the opacity by a linear step. */
  opacity += step / duration;

  /* Create the shape. */
  ctx.beginPath();
  ctx.fillStyle = "rgba(255, 165, 0, " + opacity + ")";
  ctx.clearRect(20, 20, 150, 100);
  ctx.rect(20, 20, 150, 100);
  ctx.fill();

  /* Continue the animation until the opacity is 1. */
  if (opacity < 1) window.requestAnimationFrame(animate);
}

/* Start the animation. */
window.requestAnimationFrame(animate);
<canvas id="myCanvas" width="300" height="300" style="border:1px solid #d3d3d3;">
  Your browser does not support the HTML5 canvas tag.
</canvas>

备注:

  1. 您可以通过将持续时间更改为最适合您的时间来调整动画的速度。该值以毫秒为单位。

  2. animate的每次调用中,我们使用clearRect清除画布,以避免在另一个上面创建一个形状,以便不透明度按预期增加。

  3. 不同的浏览器以不同的方式处理requestAnimationFrame,因此要实现一致的跨浏览器结果,您必须使用一个解决浏览器之间差异的polyfill。我在下面提供了一个。

  4. 继续动画的另一种方法是使用setInterval,但我相信这已成为过去。有关详情,请参阅this article

  5. <强>填充工具:

    (此polyfill是this one的修改版本,由Paul Irish创建)

    ;(function (prefices, lastTime) {       
        /* Iterate over every browser-engine-specific prefix. */
        for (var i = 0; i < prefices.length && !window.requestAnimationFrame; i++) {
            /* Normalise requestAnimationFrame and cancelAnimationFrame. */
            window.requestAnimationFrame = window[prefices[i] + "RequestAnimationFrame"];
            window.cancelAnimationFrame =
                window[prefices[i] + "CancelAnimationFrame"] ||
                window[prefices[i] + "CancelRequestAnimationFrame"];
        }
    
        /* If requestAnimationFrame is not defined use a custom function. */
        window.requestAnimationFrame = window.requestAnimationFrame
            || function (callback, element) {
            var
                /* Save the present time and the time between it and the last time. */
                now = Date.now() || new Date().getTime(),
                timeToCall = Math.max(0, 16 - (now - lastTime)),
    
                /* Save the id of the timeout. */
                id = window.setTimeout(function () {
                    /* Call the callback function passing the time passed & the element. */
                    callback(now + timeToCall, element);
                }, timeToCall);
    
            /* Update the last time with the present time plus the time in between. */
            lastTime = now + timeToCall;
    
            /* Return the id of the timeout. */
            return id;
        };
    
        /* If cancelAnimationFrame is not defined set it to clear the timeout. */
        window.cancelAnimationFrame = window.cancelAnimationFrame || function (id) {
            clearTimeout(id);
        }
    })(["webkit", "moz", "ms", "o"], 0);
    

答案 1 :(得分:1)

你不能像使用CSS一样“动画”。使用画布,你会画出灵感,所以你必须自己做数学和计时。

这是从一个值到另一个值的简单线性过程。

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

const duration = 1000; // ms
const step = 10; // ms
let opacity = 0;

function draw() {
  if (opacity == 1) return;

  opacity += (step / duration);
  ctx.clearRect(20, 20, 150, 100);
  ctx.beginPath(); 
  ctx.fillStyle = `rgba(255, 165, 0, ${opacity})`;
  ctx.rect(20, 20, 150, 100);
  ctx.fill();
  setTimeout(draw, step);
}

draw();
<canvas id="myCanvas" width="300" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

基本上,您可以跟踪当前的不透明度,您希望它的持续时间以及您希望它触发的频率。然后,按照stepduration的百分比增加不透明度并重新绘制。

另外,既然你正在处理不透明度,你必须记住每一步都要清除它,否则它会很快变暗。

你也可以使用window.requestAnimationFrame,但是(如果你想控制速度),你需要跟踪时间而不是步骤:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

const duration = 1000; // ms
let lastTime = performance.now();
let opacity = 0;

function draw(now) {
  if (opacity >= 1) return;
  
  opacity += ((now - lastTime) / duration);
  lastTime = now;
  
  ctx.clearRect(20, 20, 150, 100);
  ctx.beginPath(); 
  ctx.fillStyle = `rgba(255, 165, 0, ${opacity})`;
  ctx.rect(20, 20, 150, 100);
  ctx.fill();
  
  window.requestAnimationFrame(draw);
}

draw(lastTime);
<canvas id="myCanvas" width="300" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

现在注意而不是opacity += step / duration,我们使用自上次更新opacity += (now - lastTime) / duration以来的毫秒数。

如果你想进行不同的过渡(如步入式输出),你需要调整不透明度增加量作为时间因素。