canvas - 图片裁剪 - 花瓣散落动画
用drawImage 带你做一个花瓣散落的动画
之前我们阅读过canvas的基础api。 但是其中包括有很多较为复杂的api我们直接跳过了。
drawImage 就是其中之一。今天我们就一起来看看他。
drawImage 一个方法包括了两种使用方式:渲染 和 裁剪 。 我们重点看看裁剪。
渲染
在我们渲染图片之前我们需要对图片进行预加载。
function loadImg(url) { return new Promise((resolve, reject) => { let img = new Image() img.onload = function () { resolve(img) } img.src = url }) } 复制代码
在图片加载结束之后我们将整个img对象返回。在这个img对象中我们可以拿到对img的宽高和img的实例。 而这个img的实例就是 我们drawImage的第一个参数。
我们使用drawImage对img,在参数0,0坐标处进行渲染。 我们可以看到效果是,图形将按照元是的像素进行渲染。
let img = await loadImg(imgUrl); let sw = img.width let sh = img.height ctx.drawImage(img, 0, 0) 复制代码
我们可以设置一个缩放比例 将img的长宽高都进行缩放然后在进行渲染。
let ZC = 0.2 // 缩放比例我们将缩放比例设置成20% // 在0,0这个点 按照缩放比例 ZC对图片进行渲染 ctx.drawImage(img, 0, 0, sw * ZC, sh * ZC) 复制代码
裁剪
drawImage 还有一个形变的公式,那就是裁剪
下面这段代码表示:
在图片宽度的43.6%高度的58%处截取 宽度为宽度的12.7%高度的24%的图形,放在画布的0,shZC高度处 按5050的大小显示出来
ctx.drawImage(img,sw*0.236,sh*0.58,sw*0.127,sh*0.24,0,sh*ZC,50,50) 复制代码
花瓣飘落动画
动画原理:
花瓣裁剪 我们首先定义一个花的类文件
在这个文件中我们顶一个,Flows数组 讲生成花瓣之后的实例都存放在其中。
另外实例的重点就是play方法讲水平移动 垂直移动的数值计算之后,
使用我们的图片裁剪裁剪出一朵花瓣,最后在画布中运动。
好,好这个类就定义完成了。
看代码。
let Flows = [] // 飘动雪花数组 class Flow { constructor(x, y, w, img, sw, sh) { this.x = x this.y = y this.w = w this.img = img this.sw = sw this.sh = sh this.g = Math.random() * 3+1 // 重力加速度 this.v = - (Math.random() * 2) // 水平移动速度 Flows.push(this) } play() { let img = this.img let sw = this.sw let sh = this.sh this.x -= this.v this.y += this.g // 最初始值绘图 ctx.drawImage(img,sw*0.236,sh*0.58,sw*0.127,sh*0.24,this.x, this.y,100*this.w/10,100*this.w/10) // 达到零界点清除 if(this.y > canvas.height){ this.clear() } } clear() { let index = Flows.indexOf(this) Flows.splice(index,1) } } 复制代码
花瓣运动
因为我们封装的图片加载是promise,我想使用异步的方式,
我们顶一个了一个立即执行函数,在图片加载完成之后 ,我们开启生成花瓣的函数。
没什么东西可以说的,理解了就很简单。
看代码。
let canvas = document.getElementById('canvas') let ctx = canvas.getContext('2d') canvas.height = window.innerHeight canvas.width = window.innerWidth let imgUrl = 'https://bloggers-1304641141.cos.ap-beijing.myqcloud.com/img/1631072101978.png' function loadImg(url) { return new Promise((resolve, reject) => { let img = new Image() img.onload = function () { resolve(img) } img.src = url }) } ( async () => { let img = await loadImg(imgUrl); let sw = img.width let sh = img.height let ZC = 0.2 let index = 0 new Flow(Math.random() * canvas.width/2, 0, Math.random() * 8, img, sw, sh) new Flow(Math.random() * canvas.width/2, 0, Math.random() * 8, img, sw, sh) // 60帧每秒渲染 setInterval(() => { ctx.clearRect(0, 0, canvas.width, canvas.height) // // 生产花朵 if (index % 50 === 0) { new Flow(Math.random() * canvas.width, 0, Math.random() * 4+3,img,sw,sh) } for (let i = 0; i < Flows.length; i++) { let element = Flows[i] element.play() } index++ }, 1000 / 60) })()
作者:玩鲁班的哥哥
链接:https://juejin.cn/post/7018478056381628430