使用canvas实现简单的下雪特效

效果图

引子:年近圣诞和元旦,公司运营活动需要搞一个下雪特效的活动页,需要用到canvas来写,由于之前实际项目中接触canvas甚少,这次也是一次学习和记录使用canvas的基本语法。

参考链接:MDN-Canvas的基本用法

先看看canvas的一些基本方法

矩形:
fillRect(x, y, width, height)
strokeRect(x, y, width, height)
clearRect(x, y, width, height)

路径:
步骤 => 创建起点 -> 绘制路径 -> 封闭 -> 描边填充等渲染 
beginPath()  开始
moveTo(x, y) 移动
lineTo(x, y) 绘制直线
arc(x, y, radius, startAngle, endAngle, anticlockwise)   x,y圆心 radius半径 startAngle到endAngle anticlockwise方向(默认为顺时针)
arcTo(x1, y1, x2, y2, radius)  // 
quadraticCurveTo(cp1x, cp1y, x, y)  // 二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)  // 三次贝塞尔曲线
closePath()  闭合路径
stroke()     通过线条绘制轮廓
fill()       填充绘制

颜色和样式:
fillStyle = color // 填充颜色
strokeStyle = color  // 轮廓颜色

透明度:
globalAlpha = 0到1  // 影响整canvas

线型样式:
lineWidth = value
lineCap = type  (butt、round、square)
lineJoin = type  (miter、round、bevel)
miterLimit = value
getLineDash()
setLineDash([4, 2])
lineDashOffset = value

渐变:
createLinearGradient(x1, y1, x2, y2)  // 线性渐变形状位置
createRadialGradient(x1, y1, radius1, x2, y2, radius2)  // 圆形渐变形状位置
gradient.addColorStop(position, color)  // 上色 position 0-1 颜色所在的相对位置

图片引用:
createPattern(image, type) Image: 图像的引用或canvas type: 重复属性(repeat,no-repeat,repeat-x,repeat-y)

阴影: shadow(x, y, value, color)
shadowOffsetX = float
shadowOffsetY = float
shadowBlur = float
shadowColor = color

绘制文本:
fillText(text, x, y [, maxWidth])  // maxWidth会压缩字体
strokeText(text, x, y [, maxWidth])
font = value (10px sans-serif)
textAlign = value  (start, end, left, right or center)
textBaseline = value (top, hanging, middle, alphabetic, ideographic, bottom)
direction = value (ltr, rtl)

绘制图片:
drawImage(image, x, y, width, height)  // 缩放(图片,起始位置,图片大小)
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) // 切片(图片、切割起始点、切割的大小、切完目标的位置、缩放大小)前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小

实现canvas下雪特效

基本思路:

  • 首先在画布上随机生成一些雪花

  • 设置雪花的起始位置(x,y)

  • 定义每片雪花的行动轨迹(toX, toY),即下一次渲染的目标位置

  • 随机设置雪花的大小形态,为了美观雪花使用图片合成

  • 使用requestAnimationFrame()方法渲染动效

第一步:先使用canvas定义一个画布

初始化样式和定义好画布的样式

html:


css:

第二步:使用JavaScript获取画布上下文

注意这里设置画布大小原因是由于canvas标签使用css设置会导致绘制的元素变形,必须使用canvas标签中的width和height属性设置画布大小

const canvas = document.querySelector("#snow")
const W = canvas.clientWidth
const H = canvas.clientHeight

// 设置canvas画布大小
canvas.setAttribute("width", W)
canvas.setAttribute("height", H)

const ctx = canvas.getContext("2d")

第三步:随机生成的每一片雪花数据

const config = {
    number: 200,  // 生成的雪花数量
    snowArr: [],
    pic: "https://www.deanhan.cn/wp-content/uploads/2017/12/snow.png"  // 雪花图片
}
let snowImg = new Image()
snowImg.src = config.pic

for (let i = 0; i < config.number; i++) {
    config.snowArr.push({
        x: Math.random() * W,  // 定义每片雪花的X轴
        y: Math.random() * H,  // Y轴
        toX: Math.random(),  // 雪花每一次渲染的X距离
        toY: Math.random() * 1 + 1,
        size: Math.random() * 20 + 5  // 雪花的大小
    })
}

第四步:雪花下落动画

const dropAnimation = () => {
    ctx.clearRect(0, 0, W, H)  // 清除画布重新渲染
    for (let i = 0; i < config.snowArr.length; i++) {
        let snow = config.snowArr[i]
        // ctx.beginPath()  绘制圆形雪花 后面直接图片代替
        // ctx.arc(snow.x, snow.y, snow.size, 0, Math.PI * 2, true)
        // ctx.fillStyle = "#666"
        // ctx.fill()
        ctx.drawImage(snowImg, snow.x, snow.y, snow.size, snow.size)

        snow.x = snow.x > W ? 0 : snow.x + snow.toX  // 每调一次函数向右移动一点
        snow.y = snow.y > H ? 0 : snow.y + snow.toY   // 向下移动
    }
    requestAnimationFrame(dropAnimation)
}
requestAnimationFrame(dropAnimation)

通过上述就可以实现一个简单的雪花动效,实现的关键思路还是第四步如何实现雪花的下掉动画,这样一个简易的下雪动效就这样实现了,想看源码请移步我的Github

你可能感兴趣的:(使用canvas实现简单的下雪特效)