JavaScript
语言:
JaveScriptBabelCoffeeScript
确定
var NUM_PARTICLES = ((ROWS = 5) * (COLS = 11)),
LIMIT_MAX = Math.pow(400, 2),
LIMIT_MIN = Math.pow(50, 2),
CL_1 = 8 / LIMIT_MAX,
CL_2 = 10 / LIMIT_MAX,
CL_3 = 12 / LIMIT_MAX,
SL = 5 / LIMIT_MAX,
MARGIN = 150,
SPACING = 150,
COLOR = 220,
color,
PUSH = 0.95,
POP = 0.15,
tog = true,
container, ctx,
particle,
canvas,
p, list,
a, offset,
count = 0,
w, h,
mx, my,
dx, dy,
d, l, ds,
s,
newiterations, i, j, k,
ClearnData, Clearn;
c = [0, 0, 0]
bg = [13, 27, 34];
pt1 = {
x: 0,
y: 0
};
pt2 = {
x: 0,
y: 0
};
half = {
x: 0,
y: 0
};
ho = {
x: 0,
y: 0
};
iterations = [pt1, pt2];
particle = {
vx: 0,
vy: 0,
x: 0,
y: 0
};
function init() {
container = document.getElementById('container');
canvas = document.createElement('canvas');
ctx = canvas.getContext('2d');
list = [];
l = [];
ds = [];
w = canvas.width = (COLS - 1) * SPACING + MARGIN * 2;
h = canvas.height = (ROWS - 1) * SPACING + MARGIN * 2;
container.style.marginLeft = Math.round(w * -0.5) + 'px';
container.style.marginTop = Math.round(h * -0.5) + 'px';
ClearnData = (Clearn = ctx.createImageData(w, h)).data;
for (i = 0; i < NUM_PARTICLES; i++) {
p = Object.create(particle);
if (i % 2 == 0) {
p = Object.create(particle);
p.x = p.ox = MARGIN + SPACING * (i % COLS);
p.y = p.oy = MARGIN + SPACING * Math.floor(i / COLS);
}
list[i] = p;
l[i] = false;
ds[i] = 0;
if ((i + 1) % 4 == 0) {
ClearnData[i] = 255;
} else {
ClearnData[i] = 11;
}
}
container.addEventListener('mousemove', function(e) {
bounds = container.getBoundingClientRect();
mx = pt2.x = e.clientX - bounds.left;
my = pt2.y = e.clientY - bounds.top;
});
container.appendChild(canvas);
}
function step() {
if (tog = !tog) {
for (i = 0; i < NUM_PARTICLES; i = i + 2) {
p = list[i];
d = (dx = mx - p.x) * dx + (dy = my - p.y) * dy;
f = ((LIMIT_MAX + LIMIT_MIN) / 2) / d;
if (d < LIMIT_MAX && d > LIMIT_MIN) { //只针对半径小于限制的粒子
t = Math.atan2(dy, dx);
p.vx += f * Math.cos(t);
p.vy += f * Math.sin(t);
l[i] = true;
ds[i] = LIMIT_MAX - d;
}
p.x += p.vx + (p.ox - p.x) * POP; //PUSH向外步长,POP还原步长
p.y += p.vy + (p.oy - p.y) * POP;
p.vx = 0;
p.vy = 0;
}
} else { //显示粒子
ctx.putImageData(Clearn, 0, 0);
for (i = 0; i < NUM_PARTICLES; i = i + 2) {
p = list[i];
color = "#ffffff";
if (l[i] == true) {
pt1 = {
x: p.x,
y: p.y
};
c = [7 + ~~(ds[i] * CL_1), 12 - ~~(ds[i] * CL_2), 15 - ~~(ds[i] * CL_3)];
color = '#' + c[0].toString(16) + '0' + c[1].toString(16) + '0' + c[2].toString(16) + '0';
s = Math.max(1, ~~(ds[i] * SL));
lightning();
l[i] = false;
}
ctx.strokeStyle = '#000000';
ctx.lineWidth = 5;
ctx.beginPath();
ctx.arc(~~p.x, ~~p.y, 20, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = color;
ctx.fill();
ctx.stroke();
}
}
requestAnimationFrame(step);
}
function lightning() {
iterations = [pt1, pt2];
for (k = 0; k < 8; k++) { //二分法取点
newiterations = [iterations[0]]
for (j = 1; j < iterations.length; j++) {
newiterations.push(getRandMidpoint(iterations[j - 1], iterations[j], 100 / (k * k + 1)))
newiterations.push(iterations[j])
}
iterations = newiterations.concat([])
}
ctx.beginPath();
ctx.moveTo(iterations[0].x, iterations[0].y);
ctx.lineWidth = s;
ctx.strokeStyle = color;
for (k = 1; k < iterations.length; k++) {
ctx.lineTo(iterations[k].x, iterations[k].y);
}
ctx.stroke()
ctx.closePath()
}
function getRandMidpoint(pa, pb, range) {
a = Math.atan2(pb.y - pa.y, pb.x - pa.x) + Math.PI / 2;
half = {
y: (pb.y - pa.y) / 2 + pa.y,
x: (pb.x - pa.x) / 2 + pa.x
};
offset = Math.random() * range - range / 2;
ho = {
x: Math.cos(a) * offset + half.x,
y: Math.sin(a) * offset + half.y
}
return ho;
}
init();
step();