【问题标题】:Animate the opacity of stars drawn via canvas动画通过画布绘制的星星的不透明度
【发布时间】:2019-12-28 03:14:26
【问题描述】:

如何为通过画布绘制的星星的不透明度设置动画?我试图在一座山后面画出多颗星星。到目前为止,我能想到 2 个选项。

  1. 我可以使用2层图像,将星星隐藏在山脉后面,并在星星的不透明度上使用css3关键帧动画。

  2. 通过画布绘制前景(山脉)和背景(星星)。这是我现在正在采取的方法。

我有 2 个问题。

  1. 星星的不透明度翻转/闪烁非常快,我可以在动画之间添加延迟吗?目前,我正在调用无限循环window.requestAnimationFrame(this.animate); 我尝试使用setInterval 但动画不如requestAnimationFrame 流畅

  2. 我最终可以停止这种闪烁效果吗?

这是写在 react 组件里面的

  // Animation Loop
  animate = () => {
    window.requestAnimationFrame(this.animate);
    this.c.clearRect(0, 0, this.canvas.width, this.canvas.height);

    // fill background
    this.c.fillStyle = this.backgroundGradient;
    this.c.fillRect(0, 0, this.canvas.width, this.canvas.height);

    // createmountainRange
    this.createMountainRange(1, this.canvas.height - 50, "#384551");
    this.createMountainRange(2, this.canvas.height - 150, "#2B3843");
    this.createMountainRange(3, this.canvas.height - 250, "#26333E");

    this.backgroundStars.forEach(backgroundStar => {
      this.draw(backgroundStar);
    });
  };

  //draw function
  draw = star => {

    const opacity = 1 / utils.randomIntFromRange(1, 10);
    this.c.save() // only affects code in between
    this.c.beginPath();
    this.c.arc(star.x, star.y, star.radius, 0, Math.PI * 2, false);
    this.c.fillStyle = `rgba(227, 234, 239, ${opacity})`
    this.c.shadowColor = '#e3eaef'
    this.c.shadowBlur = 20
    this.c.fill();
    this.c.closePath();
    this.c.restore()

    console.log('opacity', opacity)
  };

【问题讨论】:

    标签: css reactjs animation canvas


    【解决方案1】:
    1. 您可以为每颗星指定一个单独的属性,以指示它何时应该重新计算不透明度(这也将存储在一个属性中),并且只在这些点进行更改;您可以使用基本缓动(如source * (1 - factor) + target * factor,或查找公式)在原始不透明度和新不透明度之间逐渐过渡。
    2. 使用上述方法,您可以使用条件在不再需要时停止重新计算 alpha。

    可以使用单独的画布方法,但前提是您希望所有星星在任何给定点都具有完全相同的 alpha;

    您也许可以使用globalAlpha,而不是在每次绘制时都拼接一个新的fillStyle,这对于阴影可能也更好看。

    【讨论】:

      【解决方案2】:

      您的动画函数有一个帧参数,您可以使用 sin 函数来添加闪烁效果,我需要更多代码来检查精确的解决方案,但您可以尝试以下方法:

        // Animation Loop
        animate = (frame) => {
          window.requestAnimationFrame(this.animate);
          this.c.clearRect(0, 0, this.canvas.width, this.canvas.height);
      
          // fill background
          this.c.fillStyle = this.backgroundGradient;
          this.c.fillRect(0, 0, this.canvas.width, this.canvas.height);
      
          // createmountainRange
          this.createMountainRange(1, this.canvas.height - 50, "#384551");
          this.createMountainRange(2, this.canvas.height - 150, "#2B3843");
          this.createMountainRange(3, this.canvas.height - 250, "#26333E");
      
          this.backgroundStars.forEach((backgroundStar, i) => {
            this.draw(backgroundStar, i, frame || 0);
          });
        };
      
        //draw function
        draw = (star, index, frame) => {
      
          const opacity = Math.sin(index * frame * 0.01);
          this.c.save() // only affects code in between
          this.c.beginPath();
          this.c.arc(star.x, star.y, star.radius, 0, Math.PI * 2, false);
          this.c.fillStyle = `rgba(227, 234, 239, ${opacity})`
          this.c.shadowColor = '#e3eaef'
          this.c.shadowBlur = 20
          this.c.fill();
          this.c.closePath();
          this.c.restore()
      
          console.log('opacity', opacity)
        };
      

      【讨论】:

        猜你喜欢
        • 2012-05-07
        • 1970-01-01
        • 1970-01-01
        • 2010-09-25
        • 1970-01-01
        • 2011-10-01
        • 2017-01-04
        • 1970-01-01
        • 2013-06-14
        相关资源
        最近更新 更多