canvas拖尾效果演示
本帖最后由 马黑黑 于 2024-5-4 18:40 编辑 <br /><br /><style>#papa { margin: 20px auto; width: 760px; height: 560px; background: linear-gradient(lightblue, tan); }
#canv { display: block; position: absolute; background: #000; mix-blend-mode: screen; }
</style>
<div id="papa"><canvas id="canv"></canvas></div>
<script>
var ctx = canv.getContext('2d');
let total = 50, r = 2, particles = [];
let ww = canv.width = papa.offsetWidth, hh = canv.height = papa.offsetHeight;
for (var i = 0; i < total; i ++) {
let x = Math.random() * ww,
y = Math.random() * hh,
v = Math.random() * 0.5 + 0.5,
color = 'rgba(255,255,255,.5)';
particles.push({x: x, y: y, r: r, v: v, color: color});
}
var draw = (x,y,r,color) => {
ctx.save();
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI);
ctx.fill();
ctx.restore();
};
var move = () => {
ctx.fillStyle = 'rgba(0, 0, 0, .1)';
ctx.fillRect(0, 0, ww, hh);
particles.forEach(p => {
draw(p.x, p.y, p.r, p.color);
p.x += p.v;
p.y += p.v;
if (p.x > ww) p.x = 0;
if (p.y > ww) p.y = 0;
});
requestAnimationFrame(move);
};
move();
</script>
本帖最后由 马黑黑 于 2024-5-4 18:39 编辑
代码
<style>
#papa { margin: 20px auto; width: 760px; height: 560px; background: linear-gradient(lightblue, tan); }
#canv { display: block; position: absolute; background: #000; mix-blend-mode: screen; }
</style>
<div id="papa"><canvas id="canv"></canvas></div>
<script>
var ctx = canv.getContext('2d');
let total = 50, r = 2, particles = [];
let ww = canv.width = papa.offsetWidth, hh = canv.height = papa.offsetHeight;
for (var i = 0; i < total; i ++) {
let x = Math.random() * ww,
y = Math.random() * hh,
v = Math.random() * 0.5 + 0.5,
color = 'rgba(255,255,255,.5)';
particles.push({x: x, y: y, r: r, v: v, color: color});
}
var draw = (x,y,r,color) => {
ctx.save();
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI);
ctx.fill();
ctx.restore();
};
var move = () => {
ctx.fillStyle = 'rgba(0, 0, 0, .1)';
ctx.fillRect(0, 0, ww, hh);
particles.forEach(p => {
draw(p.x, p.y, p.r, p.color);
p.x += p.v;
p.y += p.v;
if (p.x > ww) p.x = 0;
if (p.y > ww) p.y = 0;
});
requestAnimationFrame(move);
};
move();
</script>
本帖最后由 马黑黑 于 2024-5-4 20:45 编辑
代码说明:
第11行:三个全局变量,total 粒子总数,r 粒子半径,particles 存储粒子对象数组——
let total = 50, r = 2, particles = [];
第14~20行:通过 for循环创建粒子对象数组,对象用 {} 表示,里面是四个键值对,xyr 记录圆形粒子的圆心坐标和半径,v 记录行进速度,color 记录填充颜色——
for (var i = 0; i < total; i ++) {
let x = Math.random() * ww,
y = Math.random() * hh,
v = Math.random() * 0.5 + 0.5,
color = 'rgba(255,255,255,.5)';
particles.push({x: x, y: y, r: r, v: v, color: color});
}
其中,particles.push(...) 是数组追加数据的方法,这里把粒子各个键值对一一存储到前面声明的空数组 particles 中。
第22~29行:绘制原型图像函数,需要四个参数,圆心xy坐标、圆半径以及圆填充色。这是标准的canvas画圆方法的封装,不多说——
var draw = (x,y,r,color) => {
ctx.save();
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI);
ctx.fill();
ctx.restore();
};
第31~42行:粒子行进函数,说明在下面代码的注释里——
var move = () => {
// 将画布绘制为0.1透明度的黑色矩形,这是粒子拖尾的关键
ctx.fillStyle = 'rgba(0, 0, 0, .1)';
ctx.fillRect(0, 0, ww, hh);
// 遍历粒子,令粒子不断改变自己的圆心坐标
particles.forEach(p => {
draw(p.x, p.y, p.r, p.color);
p.x += p.v;
p.y += p.v;
if (p.x > ww) p.x = 0;
if (p.y > ww) p.y = 0;
});
requestAnimationFrame(move); // 通过显示刷新率递归调用函数自身以达到永动动画的目的
};
此法实现了拖尾效果,也是canvas画布中最常使用的实现方式。运行性能极高,只是拖尾有残留。
CSS代码中,代码第03行,设计了纯黑背景色和融合滤镜属性。纯黑色背景配套 screen 融合滤镜,但即便不设置 background 纯黑背景,画布也会逐渐变黑,因为拖尾效果的实现就是将画布填充为一定透明度的黑色(可以是其他颜色,那就背景变成该颜色),反复渲染后呈现出来的背景会是黑色的。融合滤镜的使用是为了适应帖子容器的实际背景,虽然不完美。
另一种实现拖尾的方式和这个大同小异,它也会用到一定透明度的颜色填充画布,不同的是还用上全局透明属性+混合属性,效果会和本法一样。
还有第三种实现拖尾的方法,很复杂:记录粒子的前几个轨迹,将其渐次透明化。这回营造出更为逼真且没有残留的拖尾效果,但开销极大,运行性能会降低很多。
画布画出来的流星雨效果。。
有得飞得快一些,有的飞的慢一些。。 canvas也能画流星雨,这流星雨好漂亮啊{:4_199:} 红影 发表于 2024-5-4 20:05
canvas也能画流星雨,这流星雨好漂亮啊
之前我们不是做过烟花吗?拖尾的原理和这个虽然不尽一样,道理是相同的 南无月 发表于 2024-5-4 19:03
画布画出来的流星雨效果。。
有得飞得快一些,有的飞的慢一些。。
这是机制问题,可以随意的 马黑黑 发表于 2024-5-4 20:06
这是机制问题,可以随意的
随意飞的效果更好{:4_170:} 马黑黑 发表于 2024-5-4 20:06
之前我们不是做过烟花吗?拖尾的原理和这个虽然不尽一样,道理是相同的
是的,之前有过烟花,但是用画布做还是有点不一样呢{:4_187:} 红影 发表于 2024-5-4 20:25
是的,之前有过烟花,但是用画布做还是有点不一样呢
道理差不多 南无月 发表于 2024-5-4 20:23
随意飞的效果更好
那要看场景的,比如有些场景,敬酒的话,只能是下属对上司敬酒 马黑黑 发表于 2024-5-4 20:46
那要看场景的,比如有些场景,敬酒的话,只能是下属对上司敬酒
这个也是实用的技巧。。老师好细心。{:4_170:}
{:4_191:}再给老师敬一杯
马黑黑 发表于 2024-5-4 20:45
道理差不多
这个很漂亮呢{:4_187:} 红影 发表于 2024-5-4 21:16
这个很漂亮呢
不算特难看 南无月 发表于 2024-5-4 21:16
这个也是实用的技巧。。老师好细心。
再给老师敬一杯
{:4_191:} 流星雨粒子来了{:4_199:} 小辣椒 发表于 2024-5-4 21:56
流星雨粒子来了
{:4_190:} 马黑黑 发表于 2024-5-4 21:48
不算特难看
其实在特定情况下,淡淡的拖尾效果也不错的{:4_173:} 红影 发表于 2024-5-4 22:47
其实在特定情况下,淡淡的拖尾效果也不错的
只能如此 马黑黑 发表于 2024-5-5 08:15
只能如此
很多东西会有意想不到的效果呢。