window.init = function(elemid) {
let canvas = document.getElementById(elemid),
ctx = canvas.getContext("2d"),
w = (canvas.width = window.innerWidth),
h = (canvas.height = window.innerHeight);
ctx.fillStyle = "rgba(30,30,30,1)";
ctx.fillRect(0, 0, w, h);
return {ctx:ctx,canvas:canvas};
}
window.requestAnimFrame = function() {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback);
}
);
};
window.spaceworm = function () {
//functions definition
//class definition
class segment {
constructor(x, y, length) {
this.boundary = Math.random()*1.9+0.1;
this.x0 = x;
this.y0 = y;
this.angle = Math.random() * 2 * Math.PI;
this.x1 = this.x0 + length * Math.cos(this.angle);
this.y1 = this.y0 + length * Math.sin(this.angle);
this.length = length;
}
update(x, y) {
this.x0 = x;
this.y0 = y;
this.angle = Math.atan2(this.y1 - this.y0, this.x1 - this.x0);
this.x1 = this.x0 + this.length * Math.cos(this.angle);
this.y1 = this.y0 + this.length * Math.sin(this.angle);
}
}
class rope {
constructor(tx, ty, length, boundary, segmentsToLengthRatio, type) {
if(type == "l"){
this.resolution = length / 2;
}else{
this.resolution = length / segmentsToLengthRatio;
}
this.type = type;
this.length = length;
this.segments = [];
this.segments.push(new segment(tx, ty, this.length / this.resolution));
for (let i = 1; i < this.resolution; i++) {
this.segments.push(
new segment(this.segments[i - 1].x1, this.segments[i - 1].y1, this.length / this.resolution)
);
}
this.boundary = boundary;
}
update(target) {
this.segments[0].update(target.x, target.y);
for (let i = 1; i < this.resolution; i++) {
this.segments[i].update(this.segments[i - 1].x1, this.segments[i - 1].y1);
}
}
show() {
if(this.type == "l"){
ctx.beginPath();
for (let i = 0; i < this.segments.length; i++) {
ctx.lineTo(this.segments[i].x0, this.segments[i].y0);
}
ctx.lineTo(
this.segments[this.segments.length - 1].x1,
this.segments[this.segments.length - 1].y1
);
ctx.strokeStyle = "white";
ctx.lineWidth = this.boundary;
ctx.stroke();
ctx.beginPath();
ctx.arc(this.segments[0].x0, this.segments[0].y0, 1, 0, 2 * Math.PI);
ctx.fillStyle = "white";
ctx.fill();
ctx.beginPath();
ctx.arc(
this.segments[this.segments.length - 1].x1,
this.segments[this.segments.length - 1].y1,
2,
0,
2 * Math.PI
);
ctx.fillStyle = "white";
ctx.fill();
}else{
for (let i = 0; i < this.segments.length; i++) {
ctx.beginPath();
ctx.arc(this.segments[i].x0, this.segments[i].y0, this.segments[i].boundary, 0, 2*Math.PI);
ctx.fillStyle = "white";
ctx.fill();
}
ctx.beginPath();
ctx.arc(
this.segments[this.segments.length - 1].x1,
this.segments[this.segments.length - 1].y1,
2, 0, 2*Math.PI
);
ctx.fillStyle = "white";
ctx.fill();
}
}
}
//setting up canvas
let ctx = init("canvas").ctx,
canvas = init("canvas").canvas,
w = (canvas.width = window.innerWidth),
h = (canvas.height = window.innerHeight),
ropes = [];
//variables definition
let nameOfVariable = "value",
mouse = {},
last_mouse = {},
rl = 50,
randl = [],
target = { x: w/2, y: h/2 },
last_target = {},
t = 0,
q = 10,
da = [],
type = "l";
for (let i = 0; i < 100; i++) {
if(Math.random() > 0.25){
type = "l";
}else{
type = "o";
}
ropes.push(
new rope(
w / 2,
h / 2,
(Math.random() * 1 + 0.5) * 500,
Math.random() * 0.4 + 0.1,
Math.random()*15+5,
type
)
);
randl.push(Math.random() * 2 - 1);
da.push(0);
}
//place for objects in animation
function draw() {
if (mouse.x) {
target.errx = mouse.x - target.x;
target.erry = mouse.y - target.y;
} else {
target.errx =
w / 2 +
(h / 2 - q) *
Math.sqrt(2) *
Math.cos(t) /
(Math.pow(Math.sin(t), 2) + 1) -
target.x;
target.erry =
h / 2 +
(h / 2 - q) *
Math.sqrt(2) *
Math.cos(t) *
Math.sin(t) /
(Math.pow(Math.sin(t), 2) + 1) -
target.y;
}
target.x += target.errx / 10;
target.y += target.erry / 10;
t += 0.01;
for (let i = 0; i < ropes.length; i++) {
if (randl[i] > 0) {
da[i] += (1 - randl[i]) / 10;
} else {
da[i] += (-1 - randl[i]) / 10;
}
ropes[i].update({
x:
target.x +
randl[i] * rl * Math.cos((i * 2 * Math.PI) / ropes.length + da[i]),
y:
target.y +
randl[i] * rl * Math.sin((i * 2 * Math.PI) / ropes.length + da[i])
});
ropes[i].show();
}
last_target.x = target.x;
last_target.y = target.y;
}
//mouse position
canvas.addEventListener(
"mousemove",
function (e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
},
false
);
canvas.addEventListener("mouseleave", function(e) {
mouse.x = false;
mouse.y = false;
});
//animation frame
function loop() {
window.requestAnimFrame(loop);
ctx.clearRect(0, 0, w, h);
draw();
}
//window resize
window.addEventListener("resize", function () {
(w = canvas.width = window.innerWidth),
(h = canvas.height = window.innerHeight);
loop();
});
//animation runner
loop();
setInterval(loop, 1000 / 60);
};
window.onload = spaceworm;
body,
html {
margin: 0px;
padding: 0px;
position: fixed;
background: rgb(30, 30, 30);
cursor: none;
}
<canvas id="canvas"></canvas>