让你的博客下个雪吧

568 阅读1分钟

前言

一直以来都不怎么敢玩canvas,前些日子看见有篇文章讲解了DOM实现雪花飘落的效果,今天我也用canvas试一试。

起步

第一步先画出一个雪花

量产雪花

通过循环生成随机大小,位置不一的雪花

let count = 100
let list = []
for (let i = 0; i < count; i++) {
  list.push({
    // 雪花的位置
    x: Math.round(Math.random() * width ),
    y: Math.round(Math.random() * height),
    // 雪花的半径
    r: Math.round(Math.random() * 10 + 1),
    // 雪花x、y轴的滑落速度
    speedX: Math.random() + 1,
    speedY: Math.random() + 1,
  })
}

通过上面的代码生成100个雪花的信息

绘制雪花

canvas 绘制和CSS不同,不能直接用样式处理

let Context = canvas.getContext('2d')
// 参数分别时 圆的位置x,y 半径 r 开始位置 结束位置
Context.arc(100, 100, 10, 0, Math.PI * 2, true)
// 辐射渐变,参数 对应着 位置x,y,内圈半径 位置x,y 外圈半径
let radialGradient = Context.createRadialGradient(100, 100, 0, 100, 100, 10)
radialGradient.addColorStop(0, '#fff')
radialGradient.addColorStop(0.7, 'rgba(255, 255, 255, 0)')
Context.fillStyle = radialGradient
Context.fill()

上面通过canvas绘制一个渐变圆

结合上面的雪花信息列表,循环绘制出所有的圆

让雪花飞舞

let width = window.innerWidth
let height = window.innerHeight
let Can = document.getElementsById('canvas')
Can.width = width
Can.height = height
let Context = Can.getContext('2d')
let nodeInfoList = []
let count = 100

init()
window.requestAnimationFrame(draw)

function init() {
  for (let i = 0; i < count; i++) {
    nodeInfoList.push({
      // 雪花的位置
      x: Math.round(Math.random() * width),
      y: Math.round(Math.random() * height),
      // 雪花的半径
      r: Math.round(Math.random() * 15 + 1),
      // 雪花x、y轴的滑落速度
      speedX: Math.random() + 1,
      speedY: Math.random() + 1,
    })
  }
}

function draw() {
  Context.clearRect(0, 0, width, height)
  Context.beginPath()
  for (let i = 0; i < count; i++) {
    const node = nodeInfoList[i]
    Context.arc(node.x, node.y, node.r, 0, Math.PI * 2, true)
    let radialGradient = Context.createRadialGradient(node.x, node.y, 0, node.x, node.y, node.r)
    radialGradient.addColorStop(0, '#fff')
    radialGradient.addColorStop(0.7, 'rgba(255, 255, 255, 0)')
    Context.fillStyle = radialGradient
    Context.fillRect(node.x - node.r, node.y - node.r, node.r * 2, node.r * 2)
  }
  calcNextInfo()
  window.requestAnimationFrame(draw)
}

function calcNextInfo() {
  for (let i = 0; i < count; i++) {
    const node = nodeInfoList[i]
    node.x += node.speedX
    node.y += node.speedY
    if (node.x > width || node.y > height) {
      nodeInfoList[i] = {
      // 雪花的位置
      x: Math.round(Math.random() * width),
      y: Math.round(Math.random() * height),
      // 雪花的半径
      r: Math.round(Math.random() * 15 + 1),
      // 雪花x、y轴的滑落速度
      speedX: Math.random() + 1,
      speedY: Math.random() + 1,
    }
    }
  }
}

运行代码将会看到满屏的雪花飞舞。