JavaScript利用Canvas实现粒子动画倒计时

JavaScript/前端
308
0
0
2023-07-02
目录
  • canvas 粒子动画介绍
  • 何为canvas
  • 粒子动画是啥
  • canvas
  • 定义初始变量
  • 初始化canvas和数字文本
  • 创建一定数量的点
  • 倒计时
  • 倒计时文本绘画
  • 循环绘制
  • 点动画
  • 效果图

canvas 粒子动画介绍

何为canvas

canvas是HTML5中新增的一个标签,主要是用于网页实时生成图像并可操作图像,它是用JavaScript操作的bitmap。

粒子动画是啥

粒子动画就是页面上通过发射许多微小粒子来表示不规则模糊物体,比如:用小圆点来模拟下雪、下雨的效果,用模糊线条模拟黑客帝国背景效果等。

canvas

新建一个HTML文件,写入canvas标签用于后续展示倒计时

<canvas id="canvas-number"></canvas>
<canvas id="canvas-dots"></canvas>
  • canvas-number 是用于倒计时数字展示
  • canvas-dots 是用于全屏粒子动画展示

加点样式效果看看吧

body {
  background-color: #f;
  margin:;
  padding:;
}

canvas {
  position: absolute;
  top:;
  left:;
}

#canvas-number {
  width:px;
  height:px;
}

主要是定义了 canvas-number 画布大小,canvas-dots 画布大小会在JavaScript中定义

定义初始变量

在JavaScript中定义所需的变量

var numberStage,
  numberStageCtx,
  numberStageWidth =,
  numberStageHeight =,
  numberOffsetX,
  numberOffsetY,

  stage,
  stageCtx,
  stageWidth = window.innerWidth,
  stageHeight = window.innerHeight,
  stageCenterX = stageWidth /,
  stageCenterY = stageHeight /,

  countdownFrom =,
  countdownTimer =,
  countdownRunning = true,

  number,
  dots = [],
  numberPixelCoordinates,
  circleRadius =,
  colors = [', 207, 236', '255, 244, 174', '255, 211, 218', '151, 211, 226'];
  • numberStage - stageCenterY 这一块主要是定义画布宽高和坐标
  • countdownFrom 从 10 开始倒计时
  • countdownTimer 数字显示的时长
  • countdownRunning 动起来
  • colors 页面上所有粒子颜色
  • 其他的可以自己理解一下哦~

初始化canvas和数字文本

创建一个init函数,里面会包裹初始化内容

function init() {

  // 初始化canvas-number
  numberStage = document.getElementById("canvas-number");
  numberStageCtx = numberStage.getContext('d');
  
  // 设置文字文本的窗口大小
  numberStage.width = numberStageWidth;
  numberStage.height = numberStageHeight;

  // 初始化canvas-dots和窗口大小
  stage = document.getElementById("canvas-dots");
  stageCtx = stage.getContext('d');
  stage.width = stageWidth;
  stage.height = stageHeight;

  // 设置一定的偏移量,让文字居中
  numberOffsetX = (stageWidth - numberStageWidth) /;
  numberOffsetY = (stageHeight - numberStageHeight) /;
}

根据代码中的注释可以了解初始化的内容哦~

初始化完成之后,我们需要直接运行方法

init();

在init函数结束之后,马上就需要运行该函数了

创建一定数量的点

for (var i =; i < 2240; i++) {
    var dot = new Dot(randomNumber(, stageWidth), randomNumber(0, stageHeight), colors[randomNumber(1, colors.length)], .3);
    dots.push(dot);
    tweenDots(dot, '', 'space');
}
  • 循环创建点,这里循环给的是个固定数据
  • new Dot 是创建点对象的方法
  • tweenDots 是让点动起来的第三方js
function Dot(x, y, color, alpha) {

  var _this = this;

  _this.x = x;
  _this.y = y;
  _this.color = color;
  _this.alpha = alpha;

  this.draw = function () {
    stageCtx.beginPath();
    stageCtx.arc(_this.x, _this.y, circleRadius,, 2 * Math.PI, false);
    stageCtx.fillStyle = 'rgba(' + _this.color + ', ' + _this.alpha + ')';
    stageCtx.fill();
  }

}
  • 通过 x、y坐标定位点
  • 通过随机颜色,让点样式更丰富
  • draw 里面的内容都是canvas画图的方法,具体可参考canvas文档

倒计时

function countdown() {

  // 发送倒计时数字
  drawNumber(countdownFrom.toString());

  // 倒计时为 时停止
  if (countdownFrom ===) {
    countdownRunning = false;
    drawNumber('蜡笔小心');
  }

  countdownFrom--;
}

倒计时结束之后,就可以想干啥干啥了,这里我重新输出了额外的文字

countdownFrom 需要做递减的操作

countdown();

我们需要在页面进入时,直接触发倒计时函数

倒计时文本绘画

每一个倒计时都需要用不同的点去绘制

这里通过循环 让每个文本都有四种颜色绘制

function drawNumber(num) {
  numberStageCtx.clearRect(, 0, numberStageWidth, numberStageHeight);
  numberStageCtx.fillStyle = "#f";
  numberStageCtx.textAlign = 'center';
  numberStageCtx.font = "boldpx Lato";
  numberStageCtx.fillText(num,, 300);

  var ctx = document.getElementById('canvas-number').getContext('d');
  var imageData = ctx.getImageData(, 0, numberStageWidth, numberStageHeight).data;
  numberPixelCoordinates = [];
  for (var i = imageData.length; i >=; i -= 4) {
    if (imageData[i] !==) {
      var x = (i /) % numberStageWidth;
      var y = Math.floor(Math.floor(i / numberStageWidth) /);
      if ((x && x % (circleRadius * + 3) == 0) && (y && y % (circleRadius * 2 + 3) == 0)) {
        numberPixelCoordinates.push({
          x: x,
          y: y
        });
      }
    }
  }
  formNumber();
}

function formNumber() {
  for (var i =; i < numberPixelCoordinates.length; i++) {
    tweenDots(dots[i], numberPixelCoordinates[i], '');
  }

  if (countdownRunning && countdownFrom >) {
    setTimeout(function () {
      breakNumber();
    }, countdownTimer);
  }
}

function breakNumber() {
  for (var i =; i < numberPixelCoordinates.length; i++) {
    tweenDots(dots[i], '', 'space');
  }

  if (countdownRunning) {
    setTimeout(function () {
      countdown();
    }, countdownTimer);
  }

}

循环绘制

function loop() {
  stageCtx.clearRect(, 0, stageWidth, stageHeight);
  for (var i =; i < dots.length; i++) {
    dots[i].draw(stageCtx);
  }
  requestAnimationFrame(loop);
}
loop();

循环绘制,需要进入页面即执行,所以在方法之后马上执行该函数

点动画

在倒计时文本中,我们一直会调用tweenDots方法,就是用于点动画效果的绘制

function tweenDots(dot, pos, type) {
  if (type === 'space') {
    TweenMax.to(dot, ( + Math.round(Math.random() * 100) / 100), {
      x: randomNumber(, stageWidth),
      y: randomNumber(, stageHeight),
      alpha:.3,
      ease: Cubic.easeInOut,
      onComplete: function () {
        tweenDots(dot, '', 'space');
      }
    });
  } else {
    TweenMax.to(dot, (.5 + Math.round(Math.random() * 100) / 100), {
      x: (pos.x + numberOffsetX),
      y: (pos.y + numberOffsetY),
      delay:,
      alpha:,
      ease: Cubic.easeInOut,
      onComplete: function () {}
    });
  }
}

function randomNumber(min, max) {
  return Math.floor(Math.random() * (max - min) + min);
}
  • 随机移动画布周围的点
  • 让点和文本内容协调展示

效果图