codepens/spiral-fractal-experiment-v2/dist/script.js

162 lines
5.5 KiB
JavaScript

window.addEventListener('load', function(){
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = 900;
canvas.height = 900;
// canvas settings
ctx.lineCap = 'round';
ctx.shadowColor = 'rgba(0,0,0,0.7)';
ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 5;
ctx.shadowBlur = 10;
const canvas2 = document.getElementById('canvas2');
const ctx2 = canvas2.getContext('2d');
canvas2.width = window.innerWidth;
canvas2.height = window.innerHeight;
class Fractal {
constructor(canvasWidth, canvasHeight){
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
this.size = this.canvasWidth < this.canvasHeight ? this.canvasHeight * 0.3 : this.canvasHeight * 0.3;
this.maxLevel = 5;
this.scale = 0.8;
this.branches = Math.random() * 3 + 1;
this.spread = Math.random() * 1 - 0.5;
this.color = 'hsl(' + Math.random() * 360 + ', 100%, 50%)';
this.lineWidth = 6;
this.sides = Math.floor(Math.random() * 4 + 3);
this.skew1 = 1;
this.skew2 = 1;
this.center = 0;
}
#drawBranch(level, context){
if (level > this.maxLevel) return;
context.beginPath();
context.moveTo(0,0);
context.lineTo(this.size, 0);
context.stroke();
context.save();
context.translate(this.size * 0.1, 0);
context.scale(this.scale, this.scale);
context.save();
context.rotate(this.spread * this.skew1);
this.#drawBranch(level + 1, context);
context.restore();
context.restore();
context.save();
context.translate(this.size * 0.5, 0);
context.scale(this.scale * 0.4, this.scale * 0.4);
context.save();
context.rotate(this.spread * this.skew1 * 1.5);
this.#drawBranch(level + 1, context);
context.restore();
context.restore();
context.save();
context.translate(this.size * 0.6, 0);
context.scale(this.scale * 0.3, this.scale * 0.3);
context.save();
context.rotate(this.spread * 0.5 * (this.skew1 * 2));
this.#drawBranch(level + 1, context);
context.restore();
context.restore();
context.beginPath();
context.arc(this.size * 1.1,0,this.size * 0.09, 0, Math.PI * 2);
context.fill();
}
draw(context){
context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
context.strokeStyle = this.color;
context.fillStyle = this.color;
context.lineWidth = this.lineWidth;
context.save();
context.translate(this.canvasWidth/2, this.canvasHeight/2);
for (let i = 0; i < this.sides; i++){
context.rotate((Math.PI * 2)/this.sides);
this.#drawBranch(0, context);
}
context.restore();
}
}
class Rain {
constructor(canvasWidth, canvasHeight, image, ctx){
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
this.numberOfParticles = 10;
this.particles = [];
this.image = image;
this.ctx = ctx;
this.initialize()
}
initialize(){
for (let i = 0; i < this.numberOfParticles; i++){
this.particles.push(new Particle(this.canvasWidth, this.canvasHeight, this.image))
}
}
run(){
this.particles.forEach(particle => {
particle.draw(this.ctx);
particle.update();
});
}
}
class Particle {
constructor(canvasWidth, canvasHeight, image){
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
this.image = image;
this.sizeModifier = Math.random() * 0.4 + 0.1;
this.width = this.image.width * this.sizeModifier;
this.height = this.image.height * this.sizeModifier;
this.x = Math.random() * this.canvasWidth;
this.y = Math.random() * this.canvasHeight;
this.speed = Math.random() * 1 + 1;
this.image = image;
this.angle = 0;
this.va = Math.random() * 0.05 - 0.025;
}
update(){
this.angle += this.va;
if (this.y < -this.height) {
this.y = this.canvasHeight + this.height;
this.x = Math.random() * (this.canvasWidth - this.width);
this.angle = 0;
} else this.y -= this.speed;
}
draw(context){
context.save();
context.translate(this.x, this.y );
context.rotate(this.angle);
context.drawImage(this.image, -this.width/2, -this.height/2, this.width, this.height)
context.restore();
}
}
const fractal = new Fractal(canvas.width, canvas.height);
fractal.draw(ctx);
const fractalImage = new Image();
fractalImage.src = canvas.toDataURL();
fractalImage.onload = function(){
const rain = new Rain(canvas2.width, canvas2.height, fractalImage, ctx2);
rain.initialize();
function animate(){
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
rain.run();
requestAnimationFrame(animate);
}
animate();
}
})