一、实现效果
二、代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>canvas--again</title>
<style>
* {
margin: 0;
padding: 0;
overflow: hidden;
}
html,body {
width: 100%;
height: 100%;
background: no-repeat linear-gradient(to bottom, #011a39 0%, #009d7f 100%);
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
<script>
(function(win, doc) {
const maxW = win.innerWidth;
const maxH = win.innerHeight;
const maxSize = 5;
const minSize = 1;
let isMoving = false;
let timer = null;
let canvas = doc.getElementById('canvas');
canvas.width = maxW;
canvas.height = maxH;
let ctx = canvas.getContext('2d');
let stars = [];
let move_stars = [];
function CanvasStar(num) {
this.num = num;
};
CanvasStar.prototype = {
render() {
for (let i = 0; i < this.num; i++) {
let alpha = Math.random() + 0.1;
stars[i] = new Star(i, getOneRandom(maxW), getOneRandom(maxH), getOneRandom(maxSize, minSize), true, alpha);
}
animate();
}
};
function Star(id, x, y, r, isCache, dot_alpha) {
this.id = id;
this.x = x;
this.y = y;
this.r = r;
this.dot_alpha = dot_alpha;
this.show = .5;
this.direct = getOneRandom(180) + 180;
this.isCache = isCache;
this.cacheCanvas = doc.createElement('canvas');
this.ctx_cache = this.cacheCanvas.getContext('2d');
if(isCache) {
this.cache();
}
};
Star.prototype = {
draw() {
if(!this.isCache) {
let alpha = Math.random() + 0.1;
ctx.save();
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
ctx.closePath();
ctx.shadowColor = '#fff';
ctx.shadowBlur = 2 * this.r;
ctx.fillStyle = `rgba(255, 255, 255, ${ this.dot_alpha })`;
ctx.fill();
ctx.restore();
}else {
ctx.drawImage(this.cacheCanvas, this.x - 3 * this.r, this.y - 3 * this.r)
}
},
move() {
this.y -= 0.25;
if(this.y < -10) {
this.y = maxH + 10;
}
this.draw();
},
shake(arr) {
this.show -= 0.01;
if(this.show < 0) {
return;
}
let speed = .5;
this.x += Math.cos(this.direct * Math.PI / 180) * speed;
this.y += Math.sin(this.direct * Math.PI / 180) * speed;
this.draw();
this.link();
},
link() {
if(!this.id) return;
let len = move_stars.length;
let arr = move_stars.slice(this.id - 3, this.id);
let endIdx = arr.length - 1;
ctx.save();
for(let i = endIdx; i >= 0; i--) {
if(i == endIdx && !!arr[endIdx]) {
ctx.moveTo(arr[endIdx].x, arr[endIdx].y);
ctx.beginPath();
ctx.lineTo(this.x, this.y);
}
if(i != endIdx && !!arr[i] && arr[i].show > 0) ctx.lineTo(arr[i].x, arr[i].y);
}
ctx.closePath();
ctx.strokeStyle = 'rgba(255, 255, 255, 0.125)';
ctx.stroke();
ctx.restore();
},
cache() {
this.cacheCanvas.width = 6 * this.r;
this.cacheCanvas.height = 6 * this.r;
this.ctx_cache.save();
this.ctx_cache.beginPath();
this.ctx_cache.arc(this.r * 3, this.r * 3, this.r, 0, 2 * Math.PI, false);
this.ctx_cache.closePath();
this.ctx_cache.shadowColor = '#fff';
this.ctx_cache.shadowBlur = 2 * this.r;
this.ctx_cache.fillStyle = `rgba(255, 255, 255, ${this.dot_alpha})`;
this.ctx_cache.fill();
this.ctx_cache.restore();
}
};
function animate() {
ctx.clearRect(0, 0, maxW, maxH);
let len = stars.length;
for(let i = 0; i < len; i++) {
stars[i].move();
}
let len2 = move_stars.length;
if(isMoving) {
for(let i = 0; i < len2; i++) {
if(move_stars[i]) move_stars[i].shake(move_stars);
}
}else {
move_stars = []
}
requestAnimationFrame(animate);
};
function getOneRandom(max, min = 0) {
return Math.floor(Math.random() * (max - min) + min);
};
function getSign() {
return Math.random() > .5 ? -1 : 1;
};
doc.addEventListener('mousemove', function(e) {
let x = e.clientX, y = e.clientY;
let len = move_stars.length;
let dis_x, dis_y;
if(!len) {
move_stars.push( new Star(len, x, y, getOneRandom(maxSize, 3), true, 1) );
}
if(move_stars[len - 1]) {
let pre_star = move_stars[len - 1];
if(pre_star) {
dis_x = Math.abs(x - pre_star.x);
dis_y = Math.abs(y - pre_star.y);
}
x = x + getSign() * getOneRandom(50);
y = y + getSign() * getOneRandom(50);
if(dis_x > 5 && dis_y > 5) move_stars.push( new Star(len, x, y, getOneRandom(maxSize, minSize), true, 1) );
}
isMoving = true;
clearInterval(timer);
timer = setInterval(function() {
isMoving = false;
clearInterval(timer);
}, 500)
}, false);
window.CanvasStar = CanvasStar;
})(window, document);
let canvasStar = new CanvasStar(200);
canvasStar.render();
</script>
<script>
</script>
</html>