言成言成啊 | Kit Chen's Blog

动画与帧

发布于2024-06-22 20:46:37,更新于2024-07-21 15:58:04,标签:js  文章会持续修订,转载请注明来源地址:https://meethigher.top/blog

先看视频,同样的代码,左侧是240刷显示器,右侧是60刷显示器,但是动画中粒子的运动速度不同。

原因是机器的帧率导致了基于帧的动画显示效果不同。

动画的移动距离是相同的,但是在240刷的显示器上,每秒移动240次,在60刷的显示器上,每秒移动60次。这就导致了在高刷显示器上,动画移动的更快。

解决办法是更换基于时间的JS动画库即可。

下面给出复现示例,meethigher/animation-and-frames: animation and frames

frame-animation.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
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Frame Animation</title>
<style>
* {
margin: 0;
padding: 0;
}

#particles-js {
position: absolute;
width: 100%;
height: 100%;
background-color: #000;
}

#particles-js canvas {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
</style>
</head>
<body>
<div id="particles-js"></div>

<script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
<script>
let lastTime = performance.now();
particlesJS("particles-js", {
"particles": {
"number": {
"value": 180,
"density": {
"enable": true,
"value_area": 800
}
},
"color": {
"value": "#ffffff"
},
"shape": {
"type": "circle",
"stroke": {
"width": 0,
"color": "#000000"
},
"polygon": {
"nb_sides": 5
},
"image": {
"src": "img/github.svg",
"width": 100,
"height": 100
}
},
"opacity": {
"value": 0.5,
"random": false,
"anim": {
"enable": false,
"speed": 1,
"opacity_min": 0.1,
"sync": false
}
},
"size": {
"value": 2,
"random": true,
"anim": {
"enable": false,
"speed": 40,
"size_min": 0.1,
"sync": false
}
},
"line_linked": {
"enable": false,
"distance": 150,
"color": "#ffffff",
"opacity": 0.4,
"width": 1
},
"move": {
"enable": true,
"speed": 2,
"direction": "bottom-right",
"random": false,
"straight": false,
"out_mode": "out",
"attract": {
"enable": false,
"rotateX": 600,
"rotateY": 1200
}
}
},
"interactivity": {
"detect_on": "canvas",
"events": {
"onhover": {
"enable": false,
"mode": "repulse"
},
"onclick": {
"enable": true,
"mode": "push"
},
"resize": true
},
"modes": {
"grab": {
"distance": 400,
"line_linked": {
"opacity": 1
}
},
"bubble": {
"distance": 400,
"size": 40,
"duration": 2,
"opacity": 8,
"speed": 3
},
"repulse": {
"distance": 200
},
"push": {
"particles_nb": 4
},
"remove": {
"particles_nb": 2
}
}
},
"retina_detect": true,
"config_demo": {
"hide_card": false,
"background_color": "#b61924",
"background_image": "",
"background_position": "50% 50%",
"background_repeat": "no-repeat",
"background_size": "cover"
},
// 强制将基于帧的动画改成基于时间的动画,但是经过测试发现耗费资源过大,导致运行一会会将电脑卡死。改方案不妥。
// "callback": {
// onParticlesUpdate: function () {
// const currentTime = performance.now();
// const deltaTime = (currentTime - lastTime) / 1000; // Time in seconds
// lastTime = currentTime;
//
// const speedFactor = deltaTime * 60; // Normalize to 60 FPS
// pJSDom[0].pJS.particles.move.speed = 6 * speedFactor;
// }
// }
});

// 重写绘图函数以包含自定义更新逻
const originalDraw = pJSDom[0].pJS.fn.particlesDraw;
pJSDom[0].pJS.fn.particlesDraw = function () {
if (pJSDom[0].pJS.callback && pJSDom[0].pJS.callback.onParticlesUpdate) {
pJSDom[0].pJS.callback.onParticlesUpdate();
}
originalDraw.call(pJSDom[0].pJS);
};
</script>
</body>
</html>

time-animation.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
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Time Animation</title>
<style>

* {
margin: 0;
padding: 0;
}

#tsparticles {
position: absolute;
width: 100%;
height: 100%;
background-color: #000;
}
</style>
</head>
<body>
<div id="tsparticles"></div>

<!-- 引入 tsparticles 库 -->
<script src="https://cdn.jsdelivr.net/npm/tsparticles@2/tsparticles.bundle.min.js"></script>
<script>
// 初始化 tsparticles
tsParticles.load("tsparticles", {
"fpsLimit": 60, // 限制帧率到 60 FPS
"particles": {
"number": {
"value": 180,
"density": {
"enable": true,
"value_area": 800
}
},
"color": {
"value": "#ffffff"
},
"shape": {
"type": "circle",
"stroke": {
"width": 0,
"color": "#000000"
},
"polygon": {
"nb_sides": 5
},
"image": {
"src": "img/github.svg",
"width": 100,
"height": 100
}
},
"opacity": {
"value": 0.5,
"random": false,
"anim": {
"enable": false,
"speed": 1,
"opacity_min": 0.1,
"sync": false
}
},
"size": {
"value": 2,
"random": true,
"anim": {
"enable": false,
"speed": 40,
"size_min": 0.1,
"sync": false
}
},
"line_linked": {
"enable": false,
"distance": 150,
"color": "#ffffff",
"opacity": 0.4,
"width": 1
},
"move": {
"enable": true,
"speed": 2,
"direction": "bottom-right",
"random": false,
"straight": false,
"out_mode": "out",
"attract": {
"enable": false,
"rotateX": 600,
"rotateY": 1200
}
}
},
"interactivity": {
"detect_on": "canvas",
"events": {
"onhover": {
"enable": false,
"mode": "repulse"
},
"onclick": {
"enable": true,
"mode": "push"
},
"resize": true
},
"modes": {
"grab": {
"distance": 400,
"line_linked": {
"opacity": 1
}
},
"bubble": {
"distance": 400,
"size": 40,
"duration": 2,
"opacity": 8,
"speed": 3
},
"repulse": {
"distance": 200
},
"push": {
"particles_nb": 4
},
"remove": {
"particles_nb": 2
}
}
},
"retina_detect": true,
"config_demo": {
"hide_card": false,
"background_color": "#b61924",
"background_image": "",
"background_position": "50% 50%",
"background_repeat": "no-repeat",
"background_size": "cover"
}
});
</script>
</body>
</html>
发布:2024-06-22 20:46:37
修改:2024-07-21 15:58:04
链接:https://meethigher.top/blog/2024/animation-and-frames/
标签:js 
付款码 打赏 分享
Shift+Ctrl+1 可控制工具栏