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

·  阅读 1083
使用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 = 01  // 影响整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:
<canvas id="snow"></canvas>

css:
<style>
* {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}
#snow {
	width: 100%;
	height: 100vh;
	background: url("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1607430084485&di=f65b2a32979936da744874e318c37d1e&imgtype=0&src=http%3A%2F%2Fpic.51yuansu.com%2Fbackgd%2Fcover%2F00%2F25%2F46%2F5bac096e294e6.jpg%2521%2Ffw%2F780%2Fquality%2F90%2Funsharp%2Ftrue%2Fcompress%2Ftrue") no-repeat center / 100% 100%;
	display: block;
}
</style>
复制代码

第二步:使用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

分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改