console
var Init = function() {
var canvas = document.getElementById('canvas');
this.ctx = canvas.getContext('2d');
this.vw = canvas.width = window.innerWidth;
this.vh = canvas.height = window.innerHeight;
this.boxSize = 80;
this.maxLevel = 6;
this.color1 = { h: 70, s: 75, l: 51 };
this.color2 = { h: 310, s: 98, l: 17 };
this.mouse = {
x: this.vw / 2,
y: this.vh / 2
};
this.lean = 0;
this.scale = 0;
this.x = (this.vw - this.boxSize) / 2;
this.y = this.vh;
this.getColors(this.color1, this.color2, this.maxLevel + 1);
}
Init.prototype.getColors = function(c1, c2, steps) {
this.colors = [];
var lerp = this.methods.lerp;
for (let i = 0; i < steps; i++) {
const t = i / (steps - 1);
const h = Math.round(lerp(c1.h, c2.h, t));
const s = Math.round(lerp(c1.s, c2.s, t));
const l = Math.round(lerp(c1.l, c2.l, t));
this.colors.push('hsl('+h+','+s+'%,'+l+'%)');
}
}
Init.prototype.methods = {
lerp: function lerp(a, b, t) {
return a + (b - a) * t;
},
map:function map(x, a, b, c, d) {
return c + (d - c) * ((x - a) / (b - a)) || 0;
}
}
Init.prototype.calcBranches = (function() {
var cache = {};
var memoize = function(width, scale, lean) {
var memoKey = width+'-'+scale+'-'+lean;
if (!cache[memoKey]) {
var currentH = width * scale;
var result = {
leftSize: Math.sqrt(currentH ** 2 + (width * (0.5 - lean)) ** 2),
rightSize: Math.sqrt(currentH ** 2 + (width * (0.5 + lean)) ** 2),
leftAngle: Math.atan(currentH / ((0.5 - lean) * width)),
rightAngle: Math.atan(currentH / ((0.5 + lean) * width))
};
cache[memoKey] = result;
}
return cache[memoKey];
}
memoize.cache = cache;
return memoize;
})();
Init.prototype.drawTree = function(size, scale, lean, level) {
var ctx = this.ctx;
var constitute = this.calcBranches(size, scale, lean);
ctx.save();
ctx.fillRect(0, 0, size, -size);
ctx.fillStyle = this.colors[level];
ctx.translate(0, -size);
ctx.rotate(-constitute.leftAngle);
if (level) {
this.drawTree(constitute.leftSize, scale, lean, level - 1);
} else {
ctx.fillRect(0, 0, constitute.leftSize, -constitute.leftSize);
}
ctx.translate(constitute.leftSize, 0);
ctx.rotate(constitute.rightAngle + constitute.leftAngle);
if (level) {
this.drawTree(constitute.rightSize, scale, lean, level - 1);
} else {
ctx.fillRect(0, 0,constitute.rightSize, -constitute.rightSize);
}
ctx.restore();
}
Init.prototype.render = function(){
var map = this.methods.map,
ctx = this.ctx
var scale = map(this.mouse.y, this.vh, 0, 0, 0.8)
var lean = map(this.mouse.x, 0,this.vw, 0.5, -0.5)
ctx.clearRect(0,0,this.vw,this.vh)
ctx.save();
ctx.fillStyle = this.colors[this.maxLevel];
ctx.translate(this.x,this.y);
this.drawTree(this.boxSize, scale, lean,this.maxLevel);
ctx.restore();
requestAnimationFrame(this.render.bind(this));
}
var init = new Init();
init.render();
window.addEventListener("mousemove", function(event) {
init.mouse.x = event.clientX;
init.mouse.y = event.clientY;
});
<canvas id="canvas"></canvas>