-
Notifications
You must be signed in to change notification settings - Fork 14
/
079.Canvas 爆炸粒子效果.html
101 lines (93 loc) · 2.88 KB
/
079.Canvas 爆炸粒子效果.html
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./assets/global.css" />
<style>
#monster {
width: 400px;
height: 400px;
}
</style>
</head>
<body>
<canvas id="monster"></canvas>
<script type="module">
import { Animation } from "https://gcore.jsdelivr.net/npm/@3r/tool/lib/animation.js";
import { Randoms } from "https://gcore.jsdelivr.net/npm/@3r/tool/lib/randoms.js";
/** @type {HTMLCanvasElement} */
let canvas = document.querySelector("#monster");
let ctx = canvas.getContext("2d");
let width = canvas.clientWidth;
let height = canvas.clientHeight;
canvas.width = width;
canvas.height = height;
// 像素类
class Pixel {
constructor(x, y, data) {
this.x = x;
this.y = y;
this.tx = 0;
this.ty = 0;
this.data = data;
}
setAlpha(a) {
for (let i = 0; i < this.data.data.length; i += 4) {
this.data.data[i + 3] = ~~(a * 255);
}
}
}
let pixels = [];
let img = new Image();
img.src = "./assets/monster/golza.jpg";
img.onload = () => {
ctx.drawImage(img, 100, 100, 200, 200);
let h = 200;
let w = 200;
let s = 5; // 获取图片像素尺寸
for (let y = 0; y < h; y += s) {
for (let x = 0; x < w; x += s) {
let data = ctx.getImageData(100 + x, 100 + y, s, s);
let pixel = new Pixel(x, y, data);
pixels.push(pixel);
}
}
};
let timestemp = 0; // 时间戳
let duration = 0.5; // 破碎时间
// 点击
canvas.addEventListener("click", (ev) => {
timestemp = +new Date();
for (let i = 0; i < pixels.length; i++) {
const pixel = pixels[i];
// 方向归一化
let tx = (pixel.x - 100) / 200;
let ty = (pixel.y - 100) / 200;
// 随机需要移动的位置
pixel.tx = tx * Randoms.int(300, 800);
pixel.ty = ty * Randoms.int(300, 800);
}
requestAnimationFrame(render);
});
// 渲染
function render() {
let now = +new Date();
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (now - timestemp > 1000 * duration) return; // 超出时间移除
let timeProportion = (now - timestemp) / (1000 * duration); // 时间比例
let proportion = Animation.easeOut(timeProportion); // 完成比例
for (let i = 0; i < pixels.length; i++) {
const pixel = pixels[i];
let x = pixel.tx * proportion + 200;
let y = pixel.ty * proportion + 200;
pixel.setAlpha(1 - timeProportion);
if (x < 0 && y < 0) continue;
ctx.putImageData(pixel.data, x, y);
}
requestAnimationFrame(render);
}
</script>
</body>
</html>