修改完善了一个可互动的动态背景-几何粒子星空连线
本帖最后由 TRIM 于 2024-3-8 12:04 编辑 <br /><br /><h1 style="color: #ffffff; font-size: 1.5em"><b>使用效果</b></h1><p style="color: #ffffff"><b>这个帖子就是其中一个最好的效果!</b></p>
<p style="color: #ffffff"><b>如果你想看浅色主题下的效果,请移步至</b></p>
<a href="http://trim.wyylkjs.top" style="color: #e67e22">浅色主题应用效果</a>
<p style="color: #ffffff"><br>(对不起啦,有些板块发帖不允许使用html代码,我只好在这发帖了)</p>
<br></br>
<h3 style="color: #ffffff">这个背景起初是我在CSDN上看到的:</h3>
<a href="https://blog.csdn.net/lc_2014c/article/details/132028857" style="color: #e67e22">javascript实现几何粒子星空连线背景效果</a>
<p style="color: #ffffff">但是,在使用过程中,发现了以下问题:<br></p>
<h3 style="color: #ffffff; font-size: 1.1em">1.在原代码中,粒子在鼠标一定范围内会被吸引,但当鼠标悬停过长时间,粒子会聚集在鼠标周围“鬼畜”</h3>
<p style="color: #ffffff">想出了一个办法:在drawLine函数中传入粒子运动的dx和dy(xy方向位移变化量),计算出角度,若粒子与鼠标连线和这个角度的夹角大于90度,则不吸引(修改后代码第111~123行)</p>
<p style="color: #ffffff">这样一来,粒子在飞向鼠标时会与鼠标互动,飞出鼠标方向后便不会被一直“拽着”,互动的效果更好了</p>
<br></br>
<h3 style="color: #ffffff; font-size: 1.1em">2.作者设置粒子碰到边缘反弹,我认为不反弹,将粒子显现出飞入飞出的效果会更好</h3>
<p style="color: #ffffff">但发现如果碰到边缘后粒子马上消失,连线也会瞬间断掉,更加生硬了......</p>
<p style="color: #ffffff">只好“扩展”了画布,大小往两边100。并且在y轴的出现消失位移上做了优化,同时也方便了对第3点的改进(修改后代码第77~93行)</p>
<p style="color: #ffffff">这样,粒子可以自由飞出屏幕,移动至另一边相对位置再飞入,“广阔”的感觉就出来了</p>
<br></br>
<h3 style="color: #ffffff; font-size: 1.1em">3.在滚动页面时背景不会动,略显单调</h3>
<p style="color: #ffffff">添加了页面滚动时粒子在y方向的位移,移动距离为页面滚动距离的1/5,凸显层次感</p>
<br></br>
<p style="color: #ffffff">另外,还修了一些原有的小bug,随机粒子大小等......</p>
<p style="color: #ffffff; font-size: 1.3em"><b>不管怎么说,这东西在修改后可以直接拿去用啦!效果超级棒!</b></p>
<p style="color: #55ffff; font-size: 1.15em"><b>↓ 在下面下载修改后的文件和代码 ↓</b></p>
<style>
div.nthread_postbox {
background-color: transparent;
backdrop-filter: blur(2px);
border: 2px solid #ccc;
border-radius: 20px;
}
#f_pst.pl.bm.bmw {
background-color: transparent;
backdrop-filter: blur(2px);
border: 2px solid #ccc;
border-radius: 20px;
}
td.t_f {
color: #ffffff;
}
div.nthread_postinfo {
background-color: transparent;
}
div.pi.bbs_detail_title {
background-color: transparent;
}
td.plc {
background-color: transparent;
}
div.pct.zhanzhuai_v_p15 {
background-color: transparent;
}
</style>
<canvas id="canvas"></canvas>
<script>
class Point {
constructor(canvas, options) {
this.canvas = canvas;
this.ctx = canvas.getContext("2d");
options = options || {};
this.options = {
pointColor: options.pointColor || "rgba(255,255,255,1)",
};
this.x = this.randomFloat(0, this.canvas.width);
this.y = this.randomFloat(0, this.canvas.height);
var speed = this.randomFloat(0.3, 1.4);
var angle = this.randomFloat(0, 2*Math.PI);
this.dx = Math.sin(angle) * speed;
this.dy = Math.cos(angle) * speed;
this.r = this.randomFloat(1, 1.6);
this.color = this.options.pointColor;
this.dpageScrollDistance = 0;
this.pageScrollDistance = 0;
this.pageScrollDistanceOld = 0;
document.addEventListener("scroll", (event) => {
this.pageScrollDistance = window.scrollY;
});
}
move() {
this.x += this.dx;
if (this.x < -100) {
this.x = this.canvas.width;
} else if (this.x > this.canvas.width+100) {
this.x = 0;
}
this.y += this.dy;
this.dpageScrollDistance = this.pageScrollDistance - this.pageScrollDistanceOld;
this.pageScrollDistanceOld = this.pageScrollDistance;
this.y -= this.dpageScrollDistance/5;
if (this.y < -100) {
this.y = this.y + this.canvas.height + 200;
} else if (this.y > this.canvas.height + 100) {
this.y = this.y - this.canvas.height - 200;
}
}
draw() {
this.ctx.fillStyle = this.color;
this.ctx.beginPath();
this.ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
this.ctx.closePath();
this.ctx.fill();
}
randomInt(min, max) {
return Math.floor((max - min + 1) * Math.random() + min);
}
randomFloat(min, max) {
return (max - min) * Math.random() + min;
}
}
class ParticleBackground {
constructor(options) {
options = options || {};
this.canvas = document.createElement("canvas");
this.ctx = this.canvas.getContext("2d");
this.points = [];
this.degree = 2.5;
this.startTime = new Date().getTime();
this.options = {
backgroundColor: options.backgroundColor || "rgba(0, 0, 0,1)",
pointNum: options.pointNum || 170,
pointColor: options.pointColor || "rgba(255,255,255,1)",
lineLength: options.lineLength || 10000,
};
this.p0 = new Point(this.canvas, this.options);
this.p0.dx = this.p0.dy = 0;
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.canvas.style.cssText = `
position: fixed;
top: 0px;
left: 0px;
z-index: -1;
opacity: 1.0;
`;
document.body.appendChild(this.canvas, this.options);
}
initPoints(num) {
if (!num) num = this.options.pointNum;
for (var i = 0; i < num; ++i) {
this.points.push(new Point(this.canvas));
}
this.initListner();
}
drawLine(p1, p2, deg, p2dx, p2dy) {
var dx = p1.x - p2.x;
var dy = p1.y - p2.y;
var dis2 = dx * dx + dy * dy;
var P2Angel = Math.atan2(p2dy, p2dx);
var LineAngel = Math.atan2(dy, dx);
var angle = Math.abs(P2Angel - LineAngel);
if (angle > Math.PI) {
angle = 2 * Math.PI - angle;
}
if (dis2 < 2 * this.options.lineLength) {
if (dis2 > this.options.lineLength/5 && angle < Math.PI / 2) {
if (p1 === this.p0) {
p2.x += dx * 0.025;
p2.y += dy * 0.025;
} else return;
}
var t = (1.05 - dis2 / this.options.lineLength) * 0.2 * deg;
this.ctx.strokeStyle = "rgba(255,255,255," + t + ")";
this.ctx.beginPath();
this.ctx.lineWidth = 1.5;
this.ctx.moveTo(p1.x, p1.y);
this.ctx.lineTo(p2.x, p2.y);
this.ctx.closePath();
this.ctx.stroke();
}
return;
}
drawFrame() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx.fillStyle = this.options.backgroundColor;
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
var arr = this.p0.x == null ? this.points : .concat(this.points);
for (var i = 0; i < arr.length; ++i) {
for (var j = i + 1; j < arr.length; ++j) {
this.drawLine(arr, arr, 1.0, arr.dx, arr.dy);
}
arr.draw();
arr.move();
}
window.requestAnimationFrame(this.drawFrame.bind(this));
}
initListner() {
const _this = this;
document.onmousemove = function (ev) {
_this.p0.x = ev.clientX;
_this.p0.y = ev.clientY;
};
document.onmousedown = function (ev) {
_this.degree = 5.0;
_this.p0.x = ev.clientX;
_this.p0.y = ev.clientY;
};
document.onmouseup = function (ev) {
_this.degree = 2.5;
_this.p0.x = ev.clientX;
_this.p0.y = ev.clientY;
};
window.onmouseout = function () {
_this.p0.x = null;
_this.p0.y = null;
};
}
}
const particleBackgroundInstance = new ParticleBackground();
particleBackgroundInstance.initPoints();
particleBackgroundInstance.drawFrame();
</script> WOW!!!梦幻,好玩!
页:
[1]