js+canvas下雨效果二
七娃博客389人阅读
css代码:
*,body,html{ margin: 0; padding: 0; overflow: hidden; height: 100%; background: black; } *{ box-sizing: border-box; } body{ margin: 0; padding: 0; } canvas{ position: absolute; z-index: 2; width: 100vw; height: 100vh; } svg{ position: absolute; z-index: 1; width: 100vw; height: 100vh; background: linear-gradient(45deg, rgb(30,30,40), rgb(50,50,60) ); } .cloud{ transform: translate(0,0); animation-name: cloudSlide; animation-duration: 5s; animation-direction: alternate; animation-iteration-count: infinite; animation-delay: 0s; animation-fill-mode: both; animation-timing-function: linear; } @keyframes cloudSlide{ from{ transform: translate(0px, 0px) } to{ transform: translate(30px, 0px); } }
html代码:
<canvas id="rain-canvas"></canvas>
js代码:
const {innerWidth, innerHeight} = window; const {random, abs, PI, floor} = Math; let ctx, particles, particleNum, particleR, particleSpeed, particleLife; function rand(min, max = 0, neg = false){ if(!max) max = min, min = 0 if(neg) return ( (random() - 0.5) * (max-min) + min ) else return ( random() * (max-min) + min ) } function Particle(x,y,r,dx,dy,l){ this.x = x; this.y = y; this.r = r; this.dx = dx; this.dy = dy; this.l = l; this.init = function(lastPoint){ this.r = rand(particleR.min, particleR.max); this.x = rand(0 + this.r, ctx.canvas.width - this.r); this.y = rand(10, 300); lastPoint.x = this.x; lastPoint.y = this.y; this.dx = 0; this.dy = rand(particleSpeed.min, particleSpeed.max); this.l = rand(particleLife.min, particleLife.max); this.draw(lastPoint); } this.draw = function(lastPoint){ ctx.beginPath(); ctx.strokeStyle = "rgba(80,80,"+rand(80,130)+","+this.l+")"; ctx.lineWidth = this.r; ctx.moveTo(lastPoint.x, lastPoint.y); ctx.lineTo(this.x + this.dx, this.y + this.dy); ctx.stroke(); ctx.closePath(); } this.checkBounds = function(lastPoint){ if(this.y > ctx.canvas.height || this.l <= 0){ this.init(lastPoint) }else this.draw(lastPoint) } this.update = function(){ let lastPoint = { x: this.x, y: this.y}; this.x += this.dx; this.y += this.dy; // this.l -= 1 * (1/60); this.checkBounds(lastPoint); } } window.onload = function(){ let clouds = document.querySelectorAll('g'); let duration = 15 * clouds.length + 10; clouds.forEach(cloud => { duration -= 10; cloud.style.animationDuration = duration + 's'; }); let canvas = document.getElementById('rain-canvas'); ctx = canvas.getContext("2d"); resize(); } function initCanvas(){ initParticles(); animate(); } function initParticles(){ particles = []; particleNum = 600; particleR = {min: 1, max: 2}; particleSpeed = {min: 5, max: 10}; particleLife = {min: 0.1, max: 1}; for(let i = 0; i < particleNum; i++){ let r = rand(particleR.min, particleR.max); let x = rand(0 + r, ctx.canvas.width - r); let y = rand(0, ctx.canvas.height); let dx = 0; let dy = rand(particleSpeed.min, particleSpeed.max); let l = rand(particleLife.min, particleLife.max); particles.push( new Particle(x,y,r,dx,dy,l) ) } } function resize(){ ctx.canvas.width = innerWidth; ctx.canvas.height = innerHeight; initCanvas() } function animate(){ ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); // ctx.fillStyle = "rgba(255,255,255,0.01)"; // ctx.fillRect(0,0, ctx.canvas.width, ctx.canvas.height); particles.forEach(particle => { particle.update(); }); requestAnimationFrame(animate); } addEventListener('resize', resize);