粒子网格特效

在这里插入图片描述

css

@charset "utf-8";
.particle-network-animation {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  background-color: #171717;
}
.particle-network-animation::before {
  z-index: -2;
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-size: cover;
  opacity: 0.2;
}

.glow {
  z-index: -1;
  position: fixed;
  top: 50%;
  left: 50%;
  background-image: radial-gradient(circle closest-side, rgba(255, 255, 255, 0.025), transparent);
}

.glow-1 {
  width: 150vw;
  height: 150vh;
  margin-top: -75vh;
  margin-left: -75vw;
  animation: glow-1-move 25s linear infinite both;
}

@keyframes glow-1-move {
  from {
    transform: translate(-100%, 100%);
  }
  to {
    transform: translate(100%, -100%);
  }
}
.glow-2 {
  width: 100vw;
  height: 100vh;
  margin-top: -50vh;
  margin-left: -50vw;
  animation: glow-2-move 25s linear 8.3333333333s infinite both;
}

@keyframes glow-2-move {
  from {
    transform: translate(-100%, 0%);
  }
  to {
    transform: translate(100%, 100%);
  }
}
.glow-3 {
  width: 120vw;
  height: 120vh;
  margin-top: -60vh;
  margin-left: -60vw;
  animation: glow-3-move 25s linear 16.6666666667s infinite both;
}

@keyframes glow-3-move {
  from {
    transform: translate(100%, 100%);
  }
  to {
    transform: translate(0%, -100%);
  }
}

js

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
(function() {

	var ParticleNetworkAnimation, PNA;
	ParticleNetworkAnimation = PNA = function() {};

	PNA.prototype.init = function(element) {
		this.$el = $(element);

		this.container = element;
		this.canvas = document.createElement('canvas');
		this.sizeCanvas();
		this.container.appendChild(this.canvas);
		this.ctx = this.canvas.getContext('2d');
		this.particleNetwork = new ParticleNetwork(this);

		this.bindUiActions();

		return this;
	};

	PNA.prototype.bindUiActions = function() {
		$(window).on('resize', function() {
			// this.sizeContainer();
			this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
			this.sizeCanvas();
			this.particleNetwork.createParticles();
		}.bind(this));
	};

	PNA.prototype.sizeCanvas = function() {
		this.canvas.width = this.container.offsetWidth;
		this.canvas.height = this.container.offsetHeight;
	};

	var Particle = function(parent, x, y) {
		this.network = parent;
		this.canvas = parent.canvas;
		this.ctx = parent.ctx;
		this.particleColor = returnRandomArrayitem(this.network.options.particleColors);
		this.radius = getLimitedRandom(1.5, 2.5);
		this.opacity = 0;
		this.x = x || Math.random() * this.canvas.width;
		this.y = y || Math.random() * this.canvas.height;
		this.velocity = {
			x: (Math.random() - 0.5) * parent.options.velocity,
			y: (Math.random() - 0.5) * parent.options.velocity
		};
	};

	Particle.prototype.update = function() {
		if (this.opacity < 1) {
			this.opacity += 0.01;
		} else {
			this.opacity = 1;
		}
		// Change dir if outside map
		if (this.x > this.canvas.width + 100 || this.x < -100) {
			this.velocity.x = -this.velocity.x;
		}
		if (this.y > this.canvas.height + 100 || this.y < -100) {
			this.velocity.y = -this.velocity.y;
		}

		// Update position
		this.x += this.velocity.x;
		this.y += this.velocity.y;
	};

	Particle.prototype.draw = function() {
		// Draw particle
		this.ctx.beginPath();
		this.ctx.fillStyle = this.particleColor;
		this.ctx.globalAlpha = this.opacity;
		this.ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
		this.ctx.fill();
	};

	var ParticleNetwork = function(parent) {
		this.options = {
			velocity: 1, // the higher the faster
			density: 15000, // the lower the denser
			netLineDistance: 200,
			netLineColor: '#929292',
			particleColors: ['#aaa'] // ['#6D4E5C', '#aaa', '#FFC458' ]
		};
		this.canvas = parent.canvas;
		this.ctx = parent.ctx;

		this.init();
	};

	ParticleNetwork.prototype.init = function() {
		// Create particle objects
		this.createParticles(true);

		// Update canvas
		this.animationFrame = requestAnimationFrame(this.update.bind(this));

		this.bindUiActions();
	};

	ParticleNetwork.prototype.createParticles = function(isInitial) {
		// Initialise / reset particles
		var me = this;
		this.particles = [];
		var quantity = this.canvas.width * this.canvas.height / this.options.density;

		if (isInitial) {
			var counter = 0;
			clearInterval(this.createIntervalId);
			this.createIntervalId = setInterval(function() {
				if (counter < quantity - 1) {
					// Create particle object
					this.particles.push(new Particle(this));
				}
				else {
					clearInterval(me.createIntervalId);
				}
				counter++;
			}.bind(this), 250);
		}
		else {
			// Create particle objects
			for (var i = 0; i < quantity; i++) {
				this.particles.push(new Particle(this));
			}
		}
	};

	ParticleNetwork.prototype.createInteractionParticle = function() {
		// Add interaction particle
		this.interactionParticle = new Particle(this);
		this.interactionParticle.velocity = {
			x: 0,
			y: 0
		};
		this.particles.push(this.interactionParticle);
		return this.interactionParticle;
	};

	ParticleNetwork.prototype.removeInteractionParticle = function() {
		// Find it
		var index = this.particles.indexOf(this.interactionParticle);
		if (index > -1) {
			// Remove it
			this.interactionParticle = undefined;
			this.particles.splice(index, 1);
		}
	};

	ParticleNetwork.prototype.update = function() {
		if (this.canvas) {

			this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
			this.ctx.globalAlpha = 1;

			// Draw connections
			for (var i = 0; i < this.particles.length; i++) {
				for (var j = this.particles.length - 1; j > i; j--) {
					var distance, p1 = this.particles[i], p2 = this.particles[j];

					// check very simply if the two points are even a candidate for further measurements
					distance = Math.min(Math.abs(p1.x - p2.x), Math.abs(p1.y - p2.y));
					if (distance > this.options.netLineDistance) {
						continue;
					}

					// the two points seem close enough, now let's measure precisely
					distance = Math.sqrt(
						Math.pow(p1.x - p2.x, 2) +
						Math.pow(p1.y - p2.y, 2)
					);
					if (distance > this.options.netLineDistance) {
						continue;
					}

					this.ctx.beginPath();
					this.ctx.strokeStyle = this.options.netLineColor;
					this.ctx.globalAlpha = (this.options.netLineDistance - distance) / this.options.netLineDistance * p1.opacity * p2.opacity;
					this.ctx.lineWidth = 0.7;
					this.ctx.moveTo(p1.x, p1.y);
					this.ctx.lineTo(p2.x, p2.y);
					this.ctx.stroke();
				}
			}

			// Draw particles
			for (var i = 0; i < this.particles.length; i++) {
				this.particles[i].update();
				this.particles[i].draw();
			}

			if (this.options.velocity !== 0) {
				this.animationFrame = requestAnimationFrame(this.update.bind(this));
			}

		}
		else {
			cancelAnimationFrame(this.animationFrame);
		}
	};

	ParticleNetwork.prototype.bindUiActions = function() {
		// Mouse / touch event handling
		this.spawnQuantity = 3;
		this.mouseIsDown = false;
		this.touchIsMoving = false;

		this.onMouseMove = function(e) {
			if (!this.interactionParticle) {
				this.createInteractionParticle();
			}
			this.interactionParticle.x = e.offsetX;
			this.interactionParticle.y = e.offsetY;
		}.bind(this);

		this.onTouchMove = function(e) {
			e.preventDefault();
			this.touchIsMoving = true;
			if (!this.interactionParticle) {
				this.createInteractionParticle();
			}
			this.interactionParticle.x = e.changedTouches[0].clientX;
			this.interactionParticle.y = e.changedTouches[0].clientY;
		}.bind(this);

		this.onMouseDown = function(e) {
			this.mouseIsDown = true;
			var counter = 0;
			var quantity = this.spawnQuantity;
			var intervalId = setInterval(function() {
				if (this.mouseIsDown) {
					if (counter === 1) {
						quantity = 1;
					}
					for (var i = 0; i < quantity; i++) {
						if (this.interactionParticle) {
							this.particles.push(new Particle(this, this.interactionParticle.x, this.interactionParticle.y));
						}
					}
				}
				else {
					clearInterval(intervalId);
				}
				counter++;
			}.bind(this), 50);
		}.bind(this);

		this.onTouchStart = function(e) {
			e.preventDefault();
			setTimeout(function() {
				if (!this.touchIsMoving) {
					for (var i = 0; i < this.spawnQuantity; i++) {
						this.particles.push(new Particle(this, e.changedTouches[0].clientX, e.changedTouches[0].clientY));
					}
				}
			}.bind(this), 200);
		}.bind(this);

		this.onMouseUp = function(e) {
			this.mouseIsDown = false;
		}.bind(this);

		this.onMouseOut = function(e) {
			this.removeInteractionParticle();
		}.bind(this);

		this.onTouchEnd = function(e) {
			e.preventDefault();
			this.touchIsMoving = false;
			this.removeInteractionParticle();
		}.bind(this);

		this.canvas.addEventListener('mousemove', this.onMouseMove);
		this.canvas.addEventListener('touchmove', this.onTouchMove);
		this.canvas.addEventListener('mousedown', this.onMouseDown);
		this.canvas.addEventListener('touchstart', this.onTouchStart);
		this.canvas.addEventListener('mouseup', this.onMouseUp);
		this.canvas.addEventListener('mouseout', this.onMouseOut);
		this.canvas.addEventListener('touchend', this.onTouchEnd);
	};

	ParticleNetwork.prototype.unbindUiActions = function() {
		if (this.canvas) {
			this.canvas.removeEventListener('mousemove', this.onMouseMove);
			this.canvas.removeEventListener('touchmove', this.onTouchMove);
			this.canvas.removeEventListener('mousedown', this.onMouseDown);
			this.canvas.removeEventListener('touchstart', this.onTouchStart);
			this.canvas.removeEventListener('mouseup', this.onMouseUp);
			this.canvas.removeEventListener('mouseout', this.onMouseOut);
			this.canvas.removeEventListener('touchend', this.onTouchEnd);
		}
	};

	var getLimitedRandom = function(min, max, roundToInteger) {
		var number = Math.random() * (max - min) + min;
		if (roundToInteger) {
			number = Math.round(number);
		}
		return number;
	};

	var returnRandomArrayitem = function(array) {
		return array[Math.floor(Math.random()*array.length)];
	};

pna = new ParticleNetworkAnimation();	pna.init($('.particle-network-animation')[0]);

}());

html代码

<div class='particle-network-animation'></div>

完整html代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
  @charset "utf-8";
.particle-network-animation {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  background-color: #171717;
}
.particle-network-animation::before {
  z-index: -2;
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-size: cover;
  opacity: 0.2;
}

.glow {
  z-index: -1;
  position: fixed;
  top: 50%;
  left: 50%;
  background-image: radial-gradient(circle closest-side, rgba(255, 255, 255, 0.025), transparent);
}

.glow-1 {
  width: 150vw;
  height: 150vh;
  margin-top: -75vh;
  margin-left: -75vw;
  animation: glow-1-move 25s linear infinite both;
}

@keyframes glow-1-move {
  from {
    transform: translate(-100%, 100%);
  }
  to {
    transform: translate(100%, -100%);
  }
}
.glow-2 {
  width: 100vw;
  height: 100vh;
  margin-top: -50vh;
  margin-left: -50vw;
  animation: glow-2-move 25s linear 8.3333333333s infinite both;
}

@keyframes glow-2-move {
  from {
    transform: translate(-100%, 0%);
  }
  to {
    transform: translate(100%, 100%);
  }
}
.glow-3 {
  width: 120vw;
  height: 120vh;
  margin-top: -60vh;
  margin-left: -60vw;
  animation: glow-3-move 25s linear 16.6666666667s infinite both;
}

@keyframes glow-3-move {
  from {
    transform: translate(100%, 100%);
  }
  to {
    transform: translate(0%, -100%);
  }
}

  </style>
</head>

<body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class='particle-network-animation'></div>

  <script>
    (function() {

	var ParticleNetworkAnimation, PNA;
	ParticleNetworkAnimation = PNA = function() {};

	PNA.prototype.init = function(element) {
		this.$el = $(element);

		this.container = element;
		this.canvas = document.createElement('canvas');
		this.sizeCanvas();
		this.container.appendChild(this.canvas);
		this.ctx = this.canvas.getContext('2d');
		this.particleNetwork = new ParticleNetwork(this);

		this.bindUiActions();

		return this;
	};

	PNA.prototype.bindUiActions = function() {
		$(window).on('resize', function() {
			// this.sizeContainer();
			this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
			this.sizeCanvas();
			this.particleNetwork.createParticles();
		}.bind(this));
	};

	PNA.prototype.sizeCanvas = function() {
		this.canvas.width = this.container.offsetWidth;
		this.canvas.height = this.container.offsetHeight;
	};

	var Particle = function(parent, x, y) {
		this.network = parent;
		this.canvas = parent.canvas;
		this.ctx = parent.ctx;
		this.particleColor = returnRandomArrayitem(this.network.options.particleColors);
		this.radius = getLimitedRandom(1.5, 2.5);
		this.opacity = 0;
		this.x = x || Math.random() * this.canvas.width;
		this.y = y || Math.random() * this.canvas.height;
		this.velocity = {
			x: (Math.random() - 0.5) * parent.options.velocity,
			y: (Math.random() - 0.5) * parent.options.velocity
		};
	};

	Particle.prototype.update = function() {
		if (this.opacity < 1) {
			this.opacity += 0.01;
		} else {
			this.opacity = 1;
		}
		// Change dir if outside map
		if (this.x > this.canvas.width + 100 || this.x < -100) {
			this.velocity.x = -this.velocity.x;
		}
		if (this.y > this.canvas.height + 100 || this.y < -100) {
			this.velocity.y = -this.velocity.y;
		}

		// Update position
		this.x += this.velocity.x;
		this.y += this.velocity.y;
	};

	Particle.prototype.draw = function() {
		// Draw particle
		this.ctx.beginPath();
		this.ctx.fillStyle = this.particleColor;
		this.ctx.globalAlpha = this.opacity;
		this.ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
		this.ctx.fill();
	};

	var ParticleNetwork = function(parent) {
		this.options = {
			velocity: 1, // the higher the faster
			density: 15000, // the lower the denser
			netLineDistance: 200,
			netLineColor: '#929292',
			particleColors: ['#aaa'] // ['#6D4E5C', '#aaa', '#FFC458' ]
		};
		this.canvas = parent.canvas;
		this.ctx = parent.ctx;

		this.init();
	};

	ParticleNetwork.prototype.init = function() {
		// Create particle objects
		this.createParticles(true);

		// Update canvas
		this.animationFrame = requestAnimationFrame(this.update.bind(this));

		this.bindUiActions();
	};

	ParticleNetwork.prototype.createParticles = function(isInitial) {
		// Initialise / reset particles
		var me = this;
		this.particles = [];
		var quantity = this.canvas.width * this.canvas.height / this.options.density;

		if (isInitial) {
			var counter = 0;
			clearInterval(this.createIntervalId);
			this.createIntervalId = setInterval(function() {
				if (counter < quantity - 1) {
					// Create particle object
					this.particles.push(new Particle(this));
				}
				else {
					clearInterval(me.createIntervalId);
				}
				counter++;
			}.bind(this), 250);
		}
		else {
			// Create particle objects
			for (var i = 0; i < quantity; i++) {
				this.particles.push(new Particle(this));
			}
		}
	};

	ParticleNetwork.prototype.createInteractionParticle = function() {
		// Add interaction particle
		this.interactionParticle = new Particle(this);
		this.interactionParticle.velocity = {
			x: 0,
			y: 0
		};
		this.particles.push(this.interactionParticle);
		return this.interactionParticle;
	};

	ParticleNetwork.prototype.removeInteractionParticle = function() {
		// Find it
		var index = this.particles.indexOf(this.interactionParticle);
		if (index > -1) {
			// Remove it
			this.interactionParticle = undefined;
			this.particles.splice(index, 1);
		}
	};

	ParticleNetwork.prototype.update = function() {
		if (this.canvas) {

			this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
			this.ctx.globalAlpha = 1;

			// Draw connections
			for (var i = 0; i < this.particles.length; i++) {
				for (var j = this.particles.length - 1; j > i; j--) {
					var distance, p1 = this.particles[i], p2 = this.particles[j];

					// check very simply if the two points are even a candidate for further measurements
					distance = Math.min(Math.abs(p1.x - p2.x), Math.abs(p1.y - p2.y));
					if (distance > this.options.netLineDistance) {
						continue;
					}

					// the two points seem close enough, now let's measure precisely
					distance = Math.sqrt(
						Math.pow(p1.x - p2.x, 2) +
						Math.pow(p1.y - p2.y, 2)
					);
					if (distance > this.options.netLineDistance) {
						continue;
					}

					this.ctx.beginPath();
					this.ctx.strokeStyle = this.options.netLineColor;
					this.ctx.globalAlpha = (this.options.netLineDistance - distance) / this.options.netLineDistance * p1.opacity * p2.opacity;
					this.ctx.lineWidth = 0.7;
					this.ctx.moveTo(p1.x, p1.y);
					this.ctx.lineTo(p2.x, p2.y);
					this.ctx.stroke();
				}
			}

			// Draw particles
			for (var i = 0; i < this.particles.length; i++) {
				this.particles[i].update();
				this.particles[i].draw();
			}

			if (this.options.velocity !== 0) {
				this.animationFrame = requestAnimationFrame(this.update.bind(this));
			}

		}
		else {
			cancelAnimationFrame(this.animationFrame);
		}
	};

	ParticleNetwork.prototype.bindUiActions = function() {
		// Mouse / touch event handling
		this.spawnQuantity = 3;
		this.mouseIsDown = false;
		this.touchIsMoving = false;

		this.onMouseMove = function(e) {
			if (!this.interactionParticle) {
				this.createInteractionParticle();
			}
			this.interactionParticle.x = e.offsetX;
			this.interactionParticle.y = e.offsetY;
		}.bind(this);

		this.onTouchMove = function(e) {
			e.preventDefault();
			this.touchIsMoving = true;
			if (!this.interactionParticle) {
				this.createInteractionParticle();
			}
			this.interactionParticle.x = e.changedTouches[0].clientX;
			this.interactionParticle.y = e.changedTouches[0].clientY;
		}.bind(this);

		this.onMouseDown = function(e) {
			this.mouseIsDown = true;
			var counter = 0;
			var quantity = this.spawnQuantity;
			var intervalId = setInterval(function() {
				if (this.mouseIsDown) {
					if (counter === 1) {
						quantity = 1;
					}
					for (var i = 0; i < quantity; i++) {
						if (this.interactionParticle) {
							this.particles.push(new Particle(this, this.interactionParticle.x, this.interactionParticle.y));
						}
					}
				}
				else {
					clearInterval(intervalId);
				}
				counter++;
			}.bind(this), 50);
		}.bind(this);

		this.onTouchStart = function(e) {
			e.preventDefault();
			setTimeout(function() {
				if (!this.touchIsMoving) {
					for (var i = 0; i < this.spawnQuantity; i++) {
						this.particles.push(new Particle(this, e.changedTouches[0].clientX, e.changedTouches[0].clientY));
					}
				}
			}.bind(this), 200);
		}.bind(this);

		this.onMouseUp = function(e) {
			this.mouseIsDown = false;
		}.bind(this);

		this.onMouseOut = function(e) {
			this.removeInteractionParticle();
		}.bind(this);

		this.onTouchEnd = function(e) {
			e.preventDefault();
			this.touchIsMoving = false;
			this.removeInteractionParticle();
		}.bind(this);

		this.canvas.addEventListener('mousemove', this.onMouseMove);
		this.canvas.addEventListener('touchmove', this.onTouchMove);
		this.canvas.addEventListener('mousedown', this.onMouseDown);
		this.canvas.addEventListener('touchstart', this.onTouchStart);
		this.canvas.addEventListener('mouseup', this.onMouseUp);
		this.canvas.addEventListener('mouseout', this.onMouseOut);
		this.canvas.addEventListener('touchend', this.onTouchEnd);
	};

	ParticleNetwork.prototype.unbindUiActions = function() {
		if (this.canvas) {
			this.canvas.removeEventListener('mousemove', this.onMouseMove);
			this.canvas.removeEventListener('touchmove', this.onTouchMove);
			this.canvas.removeEventListener('mousedown', this.onMouseDown);
			this.canvas.removeEventListener('touchstart', this.onTouchStart);
			this.canvas.removeEventListener('mouseup', this.onMouseUp);
			this.canvas.removeEventListener('mouseout', this.onMouseOut);
			this.canvas.removeEventListener('touchend', this.onTouchEnd);
		}
	};

	var getLimitedRandom = function(min, max, roundToInteger) {
		var number = Math.random() * (max - min) + min;
		if (roundToInteger) {
			number = Math.round(number);
		}
		return number;
	};

	var returnRandomArrayitem = function(array) {
		return array[Math.floor(Math.random()*array.length)];
	};

pna = new ParticleNetworkAnimation();	pna.init($('.particle-network-animation')[0]);

}());

  </script>
</body>
</html>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诗水人间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值