Canvas 波纹涟漪

5,351 阅读2分钟

本文正在参加「金石计划 . 瓜分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)

p3.gif

可以创建一个波纹涟漪的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));
}

到此一个简单的波纹效果就出现了,不过其实好像没有地方可以作为实际应用场景...