本文正在参加「金石计划 . 瓜分6万现金大奖」
之前在网上看到过一篇效果很好的Canvas波纹涟漪效果,我尝试了复刻制作一下,结果失败了。 只能做一个简化版本的波纹来搪塞自己了🥴
理想状态:canvas实现水波纹效果 - 悠悠 (uusama.com)
简洁版思路参考:波纹背景动画效果_哔哩哔哩_bilibili
实际效果:一块白色画布上,有黑色的波纹涟漪在不断出现并扩散开,鼠标点击画布,也会在点击处生成一个波纹
码上掘金
开始制作
在HTML
中创建一个canvas
元素,然后在script
中获取到该元素。
因为我的项目使用的是vue3
,所以可以使用ref
获取元素,正好一开始的canvas
没有设置大小,所以需要js
中获取父元素的大小,然后重新设置。
html
:
<div id="wave" ref="fatherDom">
<canvas id="wavecanvas" ref="wavecanvas"></canvas>
</div>
js
import { ref, reactive, onMounted } from "vue";
const wavecanvas = ref(null), fatherDom = ref(null);
// 绘制image图像到canvas上
const drawImage = ()=>{
const canvasDom = wavecanvas.value as unknown as HTMLCanvasElement;
const size = (fatherDom.value as unknown as HTMLElement).getBoundingClientRect();
let [swidth, sheight] = [canvasDom.width, canvasDom.height] = [size.width, size.height];
}
一道波纹,其实就是一个不断扩大的黑圈,并且在扩大的过程中,透明度不断降低,这样一想,使用canvas
就很容易绘制出来了,在canvas
的API当中,有一个arc
方法用于绘制圆弧,CanvasRenderingContext2D.arc() - Web API 接口参考 | MDN (mozilla.org)。
可以创建一个波纹涟漪的class
类,命名为ripple
。
在该类中可以设置x、y位置,size圆半径、transparency透明度、speed扩散速度,然后还有update
更新方法和drawRipple
绘制方法。
在drawRipple
方法中,可以通过设置strokeStyle
来修改圆弧的颜色,ctx.strokeStyle = rgba(0, 0, 0, ${this.transparency})
这样在update
方法中不断调整transparency透明度和size圆半径,就可以绘制一个不断扩散的圆,并且逐渐降低透明度。
根据上面绘制一个圆,可以创建波纹数组ripple_map
,用来存储当前画布上的波纹实例。并且每一个循环时,进行一次判断,如果数组中的波纹透明度已经小于等于0,就从数组中移除该波纹实例ripple_map.splice(i, 1)
。
波纹生成的位置可以使用
Math.random()
乘以宽高来随机决定位置
动画方法还是使用requestAnimationFrame
方法来进行绘制循环。
// 持续动画
function animation() {
requestAnimationFrame(animation);
draw();
}
可以在画布上绑定鼠标点击方法,在点击位置生成ripple
实例,并绑定到ripple_map
数组当中。
function getPointXY(e: MouseEvent) {
return { x: e.offsetX, y: e.offsetY };
}
canvasDom.onmousedown = (e) => {
let pos = getPointXY(e);
ripple_map.push(new ripple(pos.x, pos.y));
}
到此一个简单的波纹效果就出现了,不过其实好像没有地方可以作为实际应用场景...