canvas实现由粒子过渡为图片的效果

canvas实现由粒子过渡为图片的效果

DansRoh Lv4

效果图

效果图

实现方法

  1. 中间临时的canvas来处理图像,然后保存图像的ImageData
  2. 根据ImageData生成随机的粒子集合。
  3. 开启粒子动画,使随机粒子集合向目标处移动

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import './App.css'
import {useEffect, useRef} from "react";
import {Button} from 'antd'

function App() {
const canvasRef = useRef<HTMLCanvasElement>(null);

useEffect(() => {

}, []);

// 生成随机坐标
function getRandomCoordinateAround(n: number, range: number) {
const min = n - range;
const max = n + range;
return Math.floor(Math.random() * (max - min + 1)) + min;
}

// 创建粒子
function createParticles(imageData:ImageData) {
const particles = [];
const data = imageData.data;
const width = imageData.width;
const height = imageData.height;

for (let y = 0; y < height; y += 1) {
for (let x = 0; x < width; x += 1) {
const index = (x + y * width) * 4;
const r = data[index];
const g = data[index + 1];
const b = data[index + 2];
const a = data[index + 3];

particles.push({
x: getRandomCoordinateAround(x, 200), // 初始随机位置
y: getRandomCoordinateAround(y, 200),
targetX: x,
targetY: y,
color: `rgba(${r},${g},${b},${a / 255})`
});
}
}
return particles;
}

// 动画粒子
function animateParticles(particles: any) {
const ctx = canvasRef?.current?.getContext('2d') as CanvasRenderingContext2D;

function updateAndDraw() {
ctx.clearRect(0, 0, 300, 300);

let allParticlesReachedTarget = true; // 设定标识

particles.forEach((p: any) => {
if (p.x < p.targetX) {
if (p.targetX - p.x > 5) {
p.x += 4;
}
p.x += 1
allParticlesReachedTarget = false; // 若有任一粒子未达到目标位置,则标识设为 false
}
if (p.y < p.targetY) {
if (p.targetY - p.y > 5) {
p.y += 4;
}
p.y += 1
allParticlesReachedTarget = false;
}
if (p.x > p.targetX) {
if (p.x - p.targetX > 5) {
p.x -= 4;
}
p.x -= 1
allParticlesReachedTarget = false;
}
if (p.y > p.targetY) {
if (p.y - p.targetY > 5) {
p.y -= 4;
}
p.y -= 1
allParticlesReachedTarget = false;
}

ctx.fillStyle = p.color;
ctx.fillRect(p.x, p.y, 2, 2); // 绘制粒子
});

if (allParticlesReachedTarget) {
console.log('动画完成')
} else {
requestAnimationFrame(updateAndDraw); // 继续动画帧循环
}
}
requestAnimationFrame(updateAndDraw);
}

const show = () => {
// 加载图片
const image = new Image()
image.src = 'src/assets/images/avatar.png'
image.onload = () => {
// 创建中间临时的canvas来处理图像
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
tempCanvas.width = 300;
tempCanvas.height = 300;
tempCtx?.drawImage(image, 0, 0, 300, 300);
const imgData = tempCtx?.getImageData(0, 0, 300, 300) as ImageData;

const particles = createParticles(imgData)
animateParticles(particles);
}
}
return (
<>
<div>
<canvas ref={canvasRef} id="canvas" width={300} height={300}></canvas>
<div>
<Button onClick={show}>显示</Button>
</div>
</div>
</>
)
}

export default App
  • 标题: canvas实现由粒子过渡为图片的效果
  • 作者: DansRoh
  • 创建于 : 2024-06-27 00:00:00
  • 更新于 : 2024-06-28 10:22:30
  • 链接: https://blog.shinri.me/2024/06/27/36_canvas实现由粒子过渡成图片的效果/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
此页目录
canvas实现由粒子过渡为图片的效果