Custom Code Experiment •
Chromatophores 1
Source Code View HTML / CSS / JavaScript
<!DOCTYPE html>
<html>
<head>
<style>
html, body {
overflow: hidden;
background: #000;
padding: 0px;
margin: 0px;
width: 100%;
height: 100%;
}
canvas {
display: block;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
// Initialize canvas and context
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// Set initial dimensions
var w = canvas.width = window.innerWidth;
var h = canvas.height = window.innerHeight;
// Handle window resize
window.onresize = function() {
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
};
// Configuration - same as your original code
var pixels = [];
var emitterCount = 3;
var pixelSize = 6;
var gap = 2;
var lineWidth = 1;
var maxLifetime = 3000;
var minLifetime = 1000;
var spawnRate = 500;
var shape = "rect"; // rect/arc
var style = "stroke"; // fill/stroke
var opacity = 0.2;
var hue = 0; // Starting Hue (0-360)
var hueRange = 50; // Hue +/-
// Create new pixels - EXACTLY as in your original code
function emit() {
for(var i = 0; i < emitterCount; i++) {
pixels.push({
x: Math.ceil((Math.random() * w) / (pixelSize + gap)) * (pixelSize + gap),
y: Math.ceil((Math.random() * h) / (pixelSize + gap)) * (pixelSize + gap),
t: Math.random() * (maxLifetime - minLifetime) + minLifetime,
s: Date.now(),
h: Math.random() * ((hue + hueRange) - (hue - hueRange)) + (hue - hueRange)
});
}
}
// Adjust gap for stroke style - exactly as in your code
if(style == "stroke") {
gap *= 2;
}
// Draw all pixels - exactly as in your code
function draw() {
for(var i = 0; i < pixels.length; i++) {
ctx.beginPath();
ctx.globalAlpha = opacity;
ctx.lineWidth = lineWidth;
var diff = (Date.now() - pixels[i].s) / pixels[i].t;
var perc = Math.round(diff * 100);
ctx.strokeStyle = "hsl(" + pixels[i].h + "," + perc + "%,50%)";
ctx.fillStyle = "hsl(" + pixels[i].h + "," + perc + "%,50%)";
if(shape == "rect") {
ctx.rect(pixels[i].x, pixels[i].y, pixelSize, pixelSize);
} else if(shape == "arc") {
ctx.arc(pixels[i].x, pixels[i].y, pixelSize, 0, 2 * Math.PI);
}
if(style == "stroke") {
ctx.stroke();
} else if(style == "fill") {
ctx.fill();
}
ctx.closePath();
}
}
// Animate pixels (move them) - exactly as in your code
function animate() {
for(var i = 0; i < pixels.length; i++) {
if(pixels[i].s + pixels[i].t < Date.now()) {
pixels.splice(i, 1);
} else {
var dir = Math.round(Math.random() * 8) % 8;
switch(dir) {
case 0: // N
pixels[i].y -= gap + pixelSize;
break;
case 1: // NE
pixels[i].x += gap + pixelSize;
pixels[i].y -= gap + pixelSize;
break;
case 2: // E
pixels[i].x += gap + pixelSize;
break;
case 3: // SE
pixels[i].x += gap + pixelSize;
pixels[i].y += gap + pixelSize;
break;
case 4: // S
pixels[i].y += gap + pixelSize;
break;
case 5: // SW
pixels[i].x -= gap + pixelSize;
pixels[i].y += gap + pixelSize;
break;
case 6: // W
pixels[i].x -= gap + pixelSize;
break;
case 7: // NW
pixels[i].x -= gap + pixelSize;
pixels[i].y -= gap + pixelSize;
break;
}
}
}
}
// Main render loop
function render() {
// DO NOT clear the canvas - let pixels accumulate (as in your original code)
draw();
animate();
requestAnimationFrame(render);
}
// Start immediately - no need to wait for window.onload
emit();
setInterval(emit, spawnRate);
requestAnimationFrame(render);
// Remove the click handler that clears the canvas
// canvas.onclick = function() {
// ctx.clearRect(0, 0, w, h);
// }
</script>
</body>
</html>