Spaces:
Runtime error
Runtime error
// draw background; Note: this background is based on https://codepen.io/pawelqcm/pen/oxPYox by Pawel | |
// Note 2: Pawel, you're awesome. | |
(function() { | |
var content_element = document.getElementById("overlay"); | |
var canvas = document.querySelector('canvas'); | |
var title_elem = document.getElementsByClassName("faded title")[0]; | |
var title_text = document.getElementById("title_text"); | |
ctx = canvas.getContext('2d'); | |
if (!ctx) | |
console.warn("Your browser does not support canvas, content may be broken :'("); | |
var SENSITIVITY, SIBLINGS_LIMIT, DENSITY, TOTAL_NODES, ANCHOR_LENGTH, CURSOR_HEIGHT, CURSOR_WIDTH; | |
css_opts = getComputedStyle(document.documentElement); | |
SENSITIVITY = css_opts.getPropertyValue('--background-sensitivity') || 120; | |
SIBLINGS_LIMIT = css_opts.getPropertyValue('--background-siblings') || 7; | |
NODE_DENSITY = css_opts.getPropertyValue('--background-node-density') || 6; | |
CURSOR_WIDTH = css_opts.getPropertyValue('--background-cursor-width') || 250; | |
CURSOR_HEIGHT = css_opts.getPropertyValue('--background-cursor-height') || 250; | |
CURSOR_VERTICAL_SHRINK = css_opts.getPropertyValue('--background-cursor-vertical-shrink') || 0.1; | |
SPEED_COEF = css_opts.getPropertyValue('--background-speed') || 1; | |
ENERGY_DECAY = css_opts.getPropertyValue('--energy-decay') || 2; | |
SHOW_IF_WIDER_THAN = css_opts.getPropertyValue('--background-show-if-wider-than') || 500; | |
MOVE_ON_CURSOR = css_opts.getPropertyValue('--background-move-on-cursor').includes("true") || false; | |
var nodes = []; | |
choice = (choices => choices[Math.floor(Math.random() * choices.length)]) | |
sample_color = () => choice([[40, 40, 40], [133, 133, 133]]) | |
ANCHOR_LENGTH = 20; | |
var cursor = {x: 0, y: 0}; | |
function centralize_cursor() { | |
var rect = document.getElementById("bug-logo").getBoundingClientRect() | |
var window_left = window.pageXOffset || document.documentElement.scrollLeft; | |
var window_top = window.pageYOffset || document.documentElement.scrollTop; | |
cursor.x = window_left + rect.left + rect.width / 2; | |
cursor.y = window_top + rect.top + rect.height / 2; | |
} | |
function Node(x, y) { | |
this.anchorX = x; | |
this.anchorY = y; | |
this.x = Math.random() * (x - (x - ANCHOR_LENGTH)) + (x - ANCHOR_LENGTH); | |
this.y = Math.random() * (y - (y - ANCHOR_LENGTH)) + (y - ANCHOR_LENGTH); | |
this.vx = (Math.random() * 2 - 1) * SPEED_COEF; | |
this.vy = (Math.random() * 2 - 1) * SPEED_COEF; | |
this.energy = Math.random() * 100; | |
this.radius = Math.random(); | |
this.siblings = []; | |
[this.r, this.g, this.b] = sample_color() | |
this.brightness = 0; | |
} | |
Node.prototype.drawNode = function() { | |
var color = `rgba(${this.r}, ${this.g}, ${this.b}, ${this.brightness})`; | |
ctx.beginPath(); | |
ctx.arc(this.x, this.y, 2 * this.radius + 2 * this.siblings.length / SIBLINGS_LIMIT, 0, 2 * Math.PI); | |
ctx.fillStyle = color; | |
ctx.fill(); | |
}; | |
Node.prototype.drawConnections = function() { | |
for (var i = 0; i < this.siblings.length; i++) { | |
var color = `rgba(133, 133, 133, ${this.brightness})`; | |
ctx.beginPath(); | |
ctx.moveTo(this.x, this.y); | |
ctx.lineTo(this.siblings[i].x, this.siblings[i].y); | |
ctx.lineWidth = 1 - calcDistance(this, this.siblings[i]) / SENSITIVITY; | |
ctx.strokeStyle = color; | |
ctx.stroke(); | |
} | |
}; | |
Node.prototype.moveNode = function() { | |
this.energy -= ENERGY_DECAY; | |
if (this.energy < 1) { | |
this.energy = Math.random() * 100; | |
if (this.x - this.anchorX < -ANCHOR_LENGTH) { | |
this.vx = Math.random() * SPEED_COEF; | |
} else if (this.x - this.anchorX > ANCHOR_LENGTH) { | |
this.vx = Math.random() * -SPEED_COEF; | |
} else { | |
this.vx = Math.random() * SPEED_COEF * 2 - SPEED_COEF; | |
} | |
if (this.y - this.anchorY < -ANCHOR_LENGTH) { | |
this.vy = Math.random() * SPEED_COEF; | |
} else if (this.y - this.anchorY > ANCHOR_LENGTH) { | |
this.vy = Math.random() * -SPEED_COEF; | |
} else { | |
this.vy = Math.random() * SPEED_COEF * 2 - SPEED_COEF; | |
} | |
} | |
relative_speed_rate = Math.min(canvas.height / 100, 10.0) | |
this.x += this.vx * this.energy * relative_speed_rate; | |
this.y += this.vy * this.energy * relative_speed_rate; | |
}; | |
function initNodes() { | |
centralize_cursor(); | |
ctx.clearRect(0, 0, canvas.width, canvas.height); | |
if (canvas.width >= SHOW_IF_WIDER_THAN) | |
total_nodes = Math.round(NODE_DENSITY * (canvas.width / 100 * canvas.height / 100)); | |
else | |
total_nodes = 0; | |
nodes = []; | |
for (var i = 0; i < total_nodes; i++) | |
nodes.push(new Node(50 + Math.random() * (canvas.width - 100), | |
5 + Math.random() * (canvas.height - 10))); | |
} | |
function calcDistance(node1, node2) { | |
return Math.sqrt(Math.pow(node1.x - node2.x, 2) + (Math.pow(node1.y - node2.y, 2))); | |
} | |
function findSiblings() { | |
var node1, node2, distance; | |
for (var i = 0; i < nodes.length; i++) { | |
node1 = nodes[i]; | |
node1.siblings = []; | |
for (var j = 0; j < nodes.length; j++) { | |
node2 = nodes[j]; | |
if (node1 !== node2) { | |
distance = calcDistance(node1, node2); | |
if (distance < SENSITIVITY) { | |
if (node1.siblings.length < SIBLINGS_LIMIT) { | |
node1.siblings.push(node2); | |
} else { | |
var node_sibling_distance = 0; | |
var max_distance = 0; | |
var s; | |
for (var k = 0; k < SIBLINGS_LIMIT; k++) { | |
node_sibling_distance = calcDistance(node1, node1.siblings[k]); | |
if (node_sibling_distance > max_distance) { | |
max_distance = node_sibling_distance; | |
s = k; | |
} | |
} | |
if (distance < max_distance) { | |
node1.siblings.splice(s, 1); | |
node1.siblings.push(node2); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
function redrawScene() { | |
resizeWindow(); | |
ctx.clearRect(0, 0, canvas.width, canvas.height); | |
findSiblings(); | |
var i, node, distance; | |
for (i = 0; i < nodes.length; i++) { | |
node = nodes[i]; | |
scaled_distance = calcDistance({x: cursor.x / CURSOR_WIDTH, y: cursor.y / CURSOR_HEIGHT}, | |
{x: node.x / CURSOR_WIDTH, y: node.y / CURSOR_HEIGHT}); | |
node.brightness = Math.max(1 - scaled_distance, 0); | |
} | |
for (i = 0; i < nodes.length; i++) { | |
node = nodes[i]; | |
if (node.brightness) { | |
node.drawConnections(); | |
node.drawNode(); | |
} | |
node.moveNode(); | |
} | |
requestAnimationFrame(redrawScene); | |
} | |
function initHandlers() { | |
document.addEventListener('resize', resizeWindow); | |
document.addEventListener('orientationchange', resizeWindow); | |
if (MOVE_ON_CURSOR) { | |
document.addEventListener('mousemove', moveHandler); | |
document.addEventListener('touchmove', moveHandler); | |
} | |
} | |
function resizeWindow(evt) { | |
var new_width, new_height; | |
new_width = Math.round(Math.max(title_elem.getBoundingClientRect().right, window.innerWidth)) | |
if (screen.width < 640) | |
title_text.style.fontSize = "24px"; | |
else | |
title_text.style.fontSize = "32px"; | |
if (!MOVE_ON_CURSOR) | |
new_height = Math.round(title_elem.getBoundingClientRect().top - canvas.getBoundingClientRect().top); | |
else | |
new_height = Math.round(Math.max( | |
content_element.offsetHeight, content_element.scrollHeight, | |
content_element.clientHeight, window.innerHeight)); | |
if (canvas.width != new_width || canvas.height != new_height) { | |
canvas.width = new_width; | |
canvas.height = new_height; | |
initNodes(); | |
} | |
if (!MOVE_ON_CURSOR) | |
centralize_cursor(); | |
} | |
function moveHandler(evt) { | |
if (evt.type == "mousemove") { | |
cursor.x = window.pageXOffset + evt.clientX; | |
cursor.y = window.pageYOffset + evt.clientY; | |
} | |
else { // touch event | |
cursor.x = window.pageXOffset + evt.changedTouches[0].clientX; | |
cursor.y = window.pageYOffset + evt.changedTouches[0].clientY; | |
} | |
} | |
initHandlers(); | |
initNodes(); | |
redrawScene(); | |
})(); |