Related
I've been working on a JavaScript raycasting project, I use DDA to cast the rays. I want to add textures, but I'm not exactly sure how to do that (maybe exporting images in the .ppm file format, but I wouldn't know how to actually cast the textures on each wall).
Here's my code (two canvases, #canvas is for the 2D world, #canvas2 is for the projection):
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
const canvas2 = document.querySelector("#canvas2");
const ctx2 = canvas2.getContext("2d");
let width = 513;
let height = 513;
let width2 = 1024;
let height2 = 512;
const columns = 2000;
let columnWidth = width2 / columns;
canvas.width = width;
canvas.height = height;
canvas2.width = width2;
canvas2.height = height2;
let deltaTime = 0;
let lastFrame = Date.now();
const moveSpeed = 3.5;
const rotationSpeed = 175;
const FOV = 80;
let map = [
"##########",
"#...#....#",
"#...#....#",
"### #....#",
"#...#....#",
"# ###....#",
"#...#### #",
"#........#",
"#........#",
"##########"
];
let tileHeight = 512 / map.length;
let tileWidth = 512 / map[0].length;
const player = {
x: 2.5,
y: 8.5,
heading: 270
}
const keyMap = {};
const deg2rad = deg => deg * Math.PI / 180;
const willCollide = ({ xC, yC }, { x, y, w, h }) => {
boundingBox = {
left: x - w / 2,
right: x + w / 2,
top: y - h / 2,
bottom: y + h / 2
}
return xC > boundingBox.left && xC < boundingBox.right && yC > boundingBox.top && yC < boundingBox.bottom;
}
const handlePlayerMovement = () => {
if (keyMap.w) {
let dx = Math.cos(player.heading * Math.PI / 180);
let dy = Math.sin(player.heading * Math.PI / 180);
const xCheck = player.x + dx * 5 * deltaTime;
const yCheck = player.y + dy * 5 * deltaTime;
let canMoveX = true;
let canMoveY = true;
if (map[Math.floor(yCheck)][Math.floor(player.x)] == "#") canMoveY = false;
if (map[Math.floor(player.y)][Math.floor(xCheck)] == "#") canMoveX = false;
if (canMoveX) player.x += dx * moveSpeed * deltaTime;
if (canMoveY) player.y += dy * moveSpeed * deltaTime;
}
if (keyMap.s) {
let dx = Math.cos((player.heading * Math.PI / 180) + Math.PI);
let dy = Math.sin((player.heading * Math.PI / 180) + Math.PI);
const xCheck = player.x + dx * 5 * deltaTime;
const yCheck = player.y + dy * 5 * deltaTime;
let canMoveX = true;
let canMoveY = true;
if (map[Math.floor(yCheck)][Math.floor(player.x)] == "#") canMoveY = false;
if (map[Math.floor(player.y)][Math.floor(xCheck)] == "#") canMoveX = false;
if (canMoveX) player.x += dx * moveSpeed * deltaTime;
if (canMoveY) player.y += dy * moveSpeed * deltaTime;
}
if (keyMap.a) player.heading -= rotationSpeed * deltaTime;
if (keyMap.d) player.heading += rotationSpeed * deltaTime;
}
const generateColumns = () => {
for (let i = 0; i < columns; i++) {
let collided = false;
let angle = (player.heading - FOV / 2) + (i / columns) * FOV;
let dx = Math.cos(angle * Math.PI / 180);
let dy = Math.sin(angle * Math.PI / 180);
let stepX = Math.sign(dx);
let stepY = Math.sign(dy);
let dispX = dx == 0 ? 0 : Math.abs(1 / dx);
let dispY = dy == 0 ? 0 : Math.abs(1 / dy);
let distX = (dx > 0 ? Math.ceil(player.x) - player.x : player.x - Math.floor(player.x)) * dispX;
let distY = (dy > 0 ? Math.ceil(player.y) - player.y : player.y - Math.floor(player.y)) * dispY;
let gridX = Math.floor(player.x);
let gridY = Math.floor(player.y);
let dist = 0;
let side = 0;
while (!collided) {
if (distX < distY) {
gridX += stepX;
dist = distX;
distX += dispX;
side = 1;
} else {
gridY += stepY;
dist = distY;
distY += dispY;
side = 0;
}
// ctx.beginPath();
// ctx.arc((player.x + dist * dx) * tileWidth, (player.y + dist * dy) * tileHeight, 3, 0, Math.PI * 2);
// ctx.fill();
if (map[gridY][gridX] == "#") {
collided = true;
let fix_dist = dist * Math.cos((player.heading - angle) * Math.PI / 180); // fisheye fix
let h = 550 / fix_dist;
let fill = `rgb(0, ${side ? 220 : 255}, 0`;
ctx2.fillStyle = fill;
ctx2.fillRect(Math.round(columnWidth * i), height2 / 2 - h / 2, columnWidth + 1, h);
}
}
ctx.strokeStyle = "#fff";
ctx.beginPath();
ctx.moveTo(player.x * tileWidth, player.y * tileHeight);
ctx.lineTo((player.x + dist * dx) * tileWidth, (player.y + dist * dy) * tileHeight);
ctx.stroke();
}
}
const update = () => {
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, width, height);
ctx2.fillStyle = "#000";
ctx2.fillRect(0, 0, width2, height2 / 2);
ctx2.fillStyle = "#fff";
ctx2.fillRect(0, height2 - height2 / 2, width2, height2 / 2);
if (player.heading < 0) player.heading += 360;
if (player.heading > 360) player.heading -= 360;
handlePlayerMovement();
for (let y = 0; y < map.length; y++) {
for (let x = 0; x < map[y].length; x++) {
ctx.fillStyle = "#fff";
if (map[y][x] == "#") ctx.fillRect(x * tileWidth, y * tileHeight, tileWidth, tileHeight);
ctx.fillStyle = "#666";
ctx.fillRect(0, y * tileHeight, 512, 1);
ctx.fillRect(x * tileWidth, 0, 1, 512);
}
}
generateColumns();
deltaTime = (Date.now() / 1000 - lastFrame / 1000);
lastFrame = Date.now();
requestAnimationFrame(update);
}
update();
window.onkeydown = (e) => {
keyMap[e.key.toLowerCase()] = true;
}
window.onkeyup = (e) => {
keyMap[e.key.toLowerCase()] = false;
}
The purpose of code is to display some letters in the center of window. And when cursor is brought close to it the letters move in different direction. This behaviour works fine in Chrome but in firefox, when cursor is brought on the letter, it moves to top-left corner. To see live effect, visit: https://prakashaditya369.github.io.
Canvas Code:
/*Display LEIBTON in Homepage using Canvas*/
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
//Resizing
canvas.height = window.innerHeight - 5;
canvas.width = window.innerWidth - 5;
//Initializing Variables.
var gap = 60
var vGap = 30
var particles;
var collide_limit = 40;
var velocity = 20;
var angular_velocity = 30;
var working_factor = {
space_typed: false,
space_needed: false
}
var mouse = {
timestamp: 0,
dx: 0,
dy: 0,
prevX: 0,
prevY: 0,
x: 0,
y: 0,
clicked: false
}
//Functions required For Collision Tasks
//Function to find Distance between two points
function distance(point1x, point1y, point2x, point2y) {
return Math.sqrt((point1x - point2x) * (point1x - point2x) + (point1y - point2y) * (point1y - point2y))
}
//Function to find rotated velocities.
function rotate(velocity, angle) {
const rotatedVelocities = {
x: velocity.x * Math.cos(angle) - velocity.y * Math.sin(angle),
y: velocity.x * Math.sin(angle) + velocity.y * Math.cos(angle)
};
return rotatedVelocities;
}
//Function to resolve collision
/*Code used from somewhere else.*/
function resolveCollision(particle, otherParticle) {
const xVelocityDiff = particle.velocity.x - otherParticle.velocity.x;
const yVelocityDiff = particle.velocity.y - otherParticle.velocity.y;
const xDist = otherParticle.x - particle.x;
const yDist = otherParticle.y - particle.y;
// Prevent accidental overlap of particles
if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0) {
// Grab angle between the two colliding particles
const angle = -Math.atan2(otherParticle.y - particle.y, otherParticle.x - particle.x);
// Store mass in var for better readability in collision equation
const m1 = particle.mass;
const m2 = otherParticle.mass;
// Velocity before equation
const u1 = rotate(particle.velocity, angle);
const u2 = rotate(otherParticle.velocity, angle);
// Velocity after 1d collision equation
const v1 = {
x: u1.x * (m1 - m2) / (m1 + m2) + u2.x * 2 * m2 / (m1 + m2),
y: u1.y
};
const v2 = {
x: u2.x * (m1 - m2) / (m1 + m2) + u1.x * 2 * m2 / (m1 + m2),
y: u2.y
};
// Final velocity after rotating axis back to original location
const vFinal1 = rotate(v1, -angle);
const vFinal2 = rotate(v2, -angle);
// Swap particle velocities for realistic bounce effect
particle.velocity.x = vFinal1.x;
particle.velocity.y = vFinal1.y;
otherParticle.velocity.x = vFinal2.x;
otherParticle.velocity.y = vFinal2.y;
}
}
//Function to write Heading.
function writeHeading() {
ctx.fillStyle = "#424874"
ctx.font = '30px Raleway';
ctx.textAlign = "center"
ctx.fillText("Personal Website of Aditya Prakash", window.innerWidth / 2, window.innerHeight / 2 + vGap)
}
//Function to write instruction to unjumble.
function writeJumble() {
ctx.fillStyle = "#424874"
ctx.font = '15px Raleway';
ctx.textAlign = "center"
ctx.fillText("Damn it! LeibTon got Jumbled, Press Space to Unjumble", window.innerWidth / 2, window.innerHeight / 2 + vGap + 40)
}
//Particle Class.
function Particle(letter, x, y) {
this.x = x;
this.y = y;
this.velocity = {
x: 0,
y: 0
}
this.mass = 10;
this.d2x = 0;
this.d2y = 0;
this.basey = y;
this.basex = x;
this.drotate = 0;
this.ddrotate = 0;
this.rotation = 0;
this.letter = letter;
this.draw = function() {
ctx.font = '100px "Playfair Display"';
ctx.fillStyle = "#7981AF";
ctx.textAlign = "center";
ctx.translate(this.x, this.y)
ctx.rotate(this.rotation * Math.PI / 180)
ctx.fillText(this.letter, 0, 0);
ctx.rotate(-this.rotation * Math.PI / 180);
ctx.translate(-this.x, -this.y)
}
this.update = function() {
if (working_factor.space_typed) {
working_factor.space_needed = false;
if (this.x - this.basex < 0.1 && this.y - this.basey < 0.1 && this.rotation < 0.1) {
working_factor.space_typed = false;
} else {
this.velocity.x = (this.basex - this.x) / 20;
this.velocity.y = (this.basey - this.y) / 20;
this.drotate = -this.rotation / 20;
this.x += this.velocity.x;
this.y += this.velocity.y;
this.rotation += this.drotate;
}
} else {
if (distance(this.x, this.y, mouse.x, mouse.y) < 50) {
working_factor.space_needed = true;
this.velocity.x = (mouse.x - mouse.prevX) / mouse.dt * velocity
this.velocity.y = (mouse.y - mouse.prevY) / mouse.dt * velocity
this.drotate = Math.random() * angular_velocity;
}
for (let i = 0; i < particles.length; i++) {
if (this === particles[i]) continue;
if (distance(this.x, this.y, particles[i].x, particles[i].y) < 120) {
resolveCollision(this, particles[i])
}
}
if (this.x - 100 < 0 || this.x + 100 > window.innerWidth) {
this.velocity.x = -this.velocity.x;
this.d2x = -this.d2x;
}
if (this.y - 100 < 0 || this.y + 100 > window.innerHeight) {
this.velocity.y = -this.velocity.y;
this.d2y = -this.d2y;
}
this.x += this.velocity.x;
this.y += this.velocity.y;
this.rotation += this.drotate;
this.ddrotate = (this.drotate - 0) / 20;
this.drotate -= this.ddrotate;
this.d2x = (this.velocity.x - 0) / 10
this.d2y = (this.velocity.y - 0) / 10
this.velocity.x -= this.d2x;
this.velocity.y -= this.d2y;
}
this.draw();
}
}
//Init Function.
function init() {
particles = [new Particle('L', window.innerWidth / 2 - gap * 3 + 2.5, window.innerHeight / 2 - vGap), new Particle('e', window.innerWidth / 2 - gap * 2 + 5, window.innerHeight / 2 - vGap), new Particle('i', window.innerWidth / 2 - gap - 4.5, window.innerHeight / 2 - vGap), new Particle('b', window.innerWidth / 2 - 7.5, window.innerHeight / 2 - vGap), new Particle('T', window.innerWidth / 2 + gap - 2.5, window.innerHeight / 2 - vGap), new Particle('o', window.innerWidth / 2 + 2 * gap + 1, window.innerHeight / 2 - vGap), new Particle('n', window.innerWidth / 2 + 3 * gap + 2, window.innerHeight / 2 - vGap)]
}
//Animate Function
function animate() {
requestAnimationFrame(animate)
ctx.clearRect(0, 0, canvas.width, canvas.height)
for (var i = 0; i < particles.length; i++) {
particles[i].update();
}
writeHeading();
if (working_factor.space_needed)
writeJumble();
}
//Event Listeners
//Click Event Listener
canvas.addEventListener("click", function(e) {
if (e.clientX - window.innerWidth / 2 > 14.5 && e.clientX - window.innerWidth / 2 < 205.5 && e.clientY - window.innerHeight / 2 - vGap > -25 && e.clientY - window.innerHeight / 2 - vGap < 10) {
window.open("/about.html", "_self")
}
})
//Space Event Listener
window.addEventListener("keypress", function(e) {
if (e.key === " ") {
e.preventDefault();
working_factor.space_typed = true;
}
})
//Mouse movement Event Listener
canvas.addEventListener("mousemove", function(e) {
var now = Date.now()
mouse.prevX = mouse.x;
mouse.prevY = mouse.y;
mouse.x = e.clientX;
mouse.y = e.clientY;
mouse.dt = now - mouse.timestamp;
mouse.timestamp = now;
if (e.clientX - window.innerWidth / 2 > 14.5 && e.clientX - window.innerWidth / 2 < 205.5 && e.clientY - window.innerHeight / 2 - vGap > -25 && e.clientY - window.innerHeight / 2 - vGap < 10) {
canvas.style.cursor = "pointer"
} else {
canvas.style.cursor = "auto"
}
})
//When Loaded.
window.addEventListener("load", () => {
init();
animate();
})
//When resized.
window.addEventListener("resize", () => {
canvas.height = window.innerHeight - 5;
canvas.width = window.innerWidth - 5;
init();
})
im trying to implement this
https://codepen.io/Mertl/pen/XWdyRwJ into a hugo template https://themes.gohugo.io/somrat/ ;
I dont know where to put the html file; put only the no cursor part into style.css; and copy the .js into script.js, nothing happens on the localhost website when I do this, any help is appreciated <3
code: (html, css and js)
<canvas id="canvas"></canvas>
body,
html {
margin: 0px;
padding: 0px;
position: fixed;
background: rgb(30, 30, 30);
cursor: none;
}
window.onload = function () {
//functions definition
//class definition
class segm {
constructor(x, y, l) {
this.b = Math.random()*1.9+0.1;
this.x0 = x;
this.y0 = y;
this.a = Math.random() * 2 * Math.PI;
this.x1 = this.x0 + l * Math.cos(this.a);
this.y1 = this.y0 + l * Math.sin(this.a);
this.l = l;
}
update(x, y) {
this.x0 = x;
this.y0 = y;
this.a = Math.atan2(this.y1 - this.y0, this.x1 - this.x0);
this.x1 = this.x0 + this.l * Math.cos(this.a);
this.y1 = this.y0 + this.l * Math.sin(this.a);
}
}
class rope {
constructor(tx, ty, l, b, slq, typ) {
if(typ == "l"){
this.res = l / 2;
}else{
this.res = l / slq;
}
this.type = typ;
this.l = l;
this.segm = [];
this.segm.push(new segm(tx, ty, this.l / this.res));
for (let i = 1; i < this.res; i++) {
this.segm.push(
new segm(this.segm[i - 1].x1, this.segm[i - 1].y1, this.l / this.res)
);
}
this.b = b;
}
update(t) {
this.segm[0].update(t.x, t.y);
for (let i = 1; i < this.res; i++) {
this.segm[i].update(this.segm[i - 1].x1, this.segm[i - 1].y1);
}
}
show() {
if(this.type == "l"){
c.beginPath();
for (let i = 0; i < this.segm.length; i++) {
c.lineTo(this.segm[i].x0, this.segm[i].y0);
}
c.lineTo(
this.segm[this.segm.length - 1].x1,
this.segm[this.segm.length - 1].y1
);
c.strokeStyle = "white";
c.lineWidth = this.b;
c.stroke();
c.beginPath();
c.arc(this.segm[0].x0, this.segm[0].y0, 1, 0, 2 * Math.PI);
c.fillStyle = "white";
c.fill();
c.beginPath();
c.arc(
this.segm[this.segm.length - 1].x1,
this.segm[this.segm.length - 1].y1,
2,
0,
2 * Math.PI
);
c.fillStyle = "white";
c.fill();
}else{
for (let i = 0; i < this.segm.length; i++) {
c.beginPath();
c.arc(this.segm[i].x0, this.segm[i].y0, this.segm[i].b, 0, 2*Math.PI);
c.fillStyle = "white";
c.fill();
}
c.beginPath();
c.arc(
this.segm[this.segm.length - 1].x1,
this.segm[this.segm.length - 1].y1,
2, 0, 2*Math.PI
);
c.fillStyle = "white";
c.fill();
}
}
}
//setting up canvas
let c = init("canvas").c,
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);
c.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);
};
Try to implement like this
window.init = function(elemid) {
let canvas = document.getElementById(elemid),
c = canvas.getContext("2d"),
w = (canvas.width = window.innerWidth),
h = (canvas.height = window.innerHeight);
c.fillStyle = "rgba(30,30,30,1)";
c.fillRect(0, 0, w, h);
return {c:c,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 segm {
constructor(x, y, l) {
this.b = Math.random()*1.9+0.1;
this.x0 = x;
this.y0 = y;
this.a = Math.random() * 2 * Math.PI;
this.x1 = this.x0 + l * Math.cos(this.a);
this.y1 = this.y0 + l * Math.sin(this.a);
this.l = l;
}
update(x, y) {
this.x0 = x;
this.y0 = y;
this.a = Math.atan2(this.y1 - this.y0, this.x1 - this.x0);
this.x1 = this.x0 + this.l * Math.cos(this.a);
this.y1 = this.y0 + this.l * Math.sin(this.a);
}
}
class rope {
constructor(tx, ty, l, b, slq, typ) {
if(typ == "l"){
this.res = l / 2;
}else{
this.res = l / slq;
}
this.type = typ;
this.l = l;
this.segm = [];
this.segm.push(new segm(tx, ty, this.l / this.res));
for (let i = 1; i < this.res; i++) {
this.segm.push(
new segm(this.segm[i - 1].x1, this.segm[i - 1].y1, this.l / this.res)
);
}
this.b = b;
}
update(t) {
this.segm[0].update(t.x, t.y);
for (let i = 1; i < this.res; i++) {
this.segm[i].update(this.segm[i - 1].x1, this.segm[i - 1].y1);
}
}
show() {
if(this.type == "l"){
c.beginPath();
for (let i = 0; i < this.segm.length; i++) {
c.lineTo(this.segm[i].x0, this.segm[i].y0);
}
c.lineTo(
this.segm[this.segm.length - 1].x1,
this.segm[this.segm.length - 1].y1
);
c.strokeStyle = "white";
c.lineWidth = this.b;
c.stroke();
c.beginPath();
c.arc(this.segm[0].x0, this.segm[0].y0, 1, 0, 2 * Math.PI);
c.fillStyle = "white";
c.fill();
c.beginPath();
c.arc(
this.segm[this.segm.length - 1].x1,
this.segm[this.segm.length - 1].y1,
2,
0,
2 * Math.PI
);
c.fillStyle = "white";
c.fill();
}else{
for (let i = 0; i < this.segm.length; i++) {
c.beginPath();
c.arc(this.segm[i].x0, this.segm[i].y0, this.segm[i].b, 0, 2*Math.PI);
c.fillStyle = "white";
c.fill();
}
c.beginPath();
c.arc(
this.segm[this.segm.length - 1].x1,
this.segm[this.segm.length - 1].y1,
2, 0, 2*Math.PI
);
c.fillStyle = "white";
c.fill();
}
}
}
//setting up canvas
let c = init("canvas").c,
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);
c.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>
i'm trying to use this Fireworks javascript. But when i write some text in the middle of the HTML page, the fireworks will not go over it and is limited by the text position...how can i override this and keep the fireworks go up to the top of the page ?
i tryed to fix the SCREEN_WIDTH and SCREEN_HEIGHT position but it doesn't work...
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight,
mousePos = {
x: 400,
y: 300
},
// create canvas
canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
particles = [],
rockets = [],
MAX_PARTICLES = 400,
colorCode = 0;
// init
$(document).ready(function() {
document.body.appendChild(canvas);
canvas.width = SCREEN_WIDTH;
canvas.height = SCREEN_HEIGHT;
setInterval(launch, 800);
setInterval(loop, 1000 / 50);
});
// update mouse position
$(document).mousemove(function(e) {
e.preventDefault();
mousePos = {
x: e.clientX,
y: e.clientY
};
});
// launch more rockets!!!
$(document).mousedown(function(e) {
for (var i = 0; i < 5; i++) {
launchFrom(Math.random() * SCREEN_WIDTH * 2 / 3 + SCREEN_WIDTH / 6);
}
});
function launch() {
launchFrom(mousePos.x);
}
function launchFrom(x) {
if (rockets.length < 10) {
var rocket = new Rocket(x);
rocket.explosionColor = Math.floor(Math.random() * 360 / 10) * 10;
rocket.vel.y = Math.random() * -3 - 4;
rocket.vel.x = Math.random() * 6 - 3;
rocket.size = 8;
rocket.shrink = 0.999;
rocket.gravity = 0.01;
rockets.push(rocket);
}
}
function loop() {
// update screen size
if (SCREEN_WIDTH != window.innerWidth) {
canvas.width = SCREEN_WIDTH = window.innerWidth;
}
if (SCREEN_HEIGHT != window.innerHeight) {
canvas.height = SCREEN_HEIGHT = window.innerHeight;
}
// clear canvas
context.fillStyle = "rgba(0, 0, 0, 0.05)";
context.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
var existingRockets = [];
for (var i = 0; i < rockets.length; i++) {
// update and render
rockets[i].update();
rockets[i].render(context);
// calculate distance with Pythagoras
var distance = Math.sqrt(Math.pow(mousePos.x - rockets[i].pos.x, 2) + Math.pow(mousePos.y - rockets[i].pos.y, 2));
// random chance of 1% if rockets is above the middle
var randomChance = rockets[i].pos.y < (SCREEN_HEIGHT * 2 / 3) ? (Math.random() * 100 <= 1) : false;
/* Explosion rules
- 80% of screen
- going down
- close to the mouse
- 1% chance of random explosion
*/
if (rockets[i].pos.y < SCREEN_HEIGHT / 5 || rockets[i].vel.y >= 0 || distance < 50 || randomChance) {
rockets[i].explode();
} else {
existingRockets.push(rockets[i]);
}
}
rockets = existingRockets;
var existingParticles = [];
for (var i = 0; i < particles.length; i++) {
particles[i].update();
// render and save particles that can be rendered
if (particles[i].exists()) {
particles[i].render(context);
existingParticles.push(particles[i]);
}
}
// update array with existing particles - old particles should be garbage collected
particles = existingParticles;
while (particles.length > MAX_PARTICLES) {
particles.shift();
}
}
function Particle(pos) {
this.pos = {
x: pos ? pos.x : 0,
y: pos ? pos.y : 0
};
this.vel = {
x: 0,
y: 0
};
this.shrink = .97;
this.size = 2;
this.resistance = 1;
this.gravity = 0;
this.flick = false;
this.alpha = 1;
this.fade = 0;
this.color = 0;
}
Particle.prototype.update = function() {
// apply resistance
this.vel.x *= this.resistance;
this.vel.y *= this.resistance;
// gravity down
this.vel.y += this.gravity;
// update position based on speed
this.pos.x += this.vel.x;
this.pos.y += this.vel.y;
// shrink
this.size *= this.shrink;
// fade out
this.alpha -= this.fade;
};
Particle.prototype.render = function(c) {
if (!this.exists()) {
return;
}
c.save();
c.globalCompositeOperation = 'lighter';
var x = this.pos.x,
y = this.pos.y,
r = this.size / 2;
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
gradient.addColorStop(0.1, "rgba(255,255,255," + this.alpha + ")");
gradient.addColorStop(0.8, "hsla(" + this.color + ", 100%, 50%, " + this.alpha + ")");
gradient.addColorStop(1, "hsla(" + this.color + ", 100%, 50%, 0.1)");
c.fillStyle = gradient;
c.beginPath();
c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size : this.size, 0, Math.PI * 2, true);
c.closePath();
c.fill();
c.restore();
};
Particle.prototype.exists = function() {
return this.alpha >= 0.1 && this.size >= 1;
};
function Rocket(x) {
Particle.apply(this, [{
x: x,
y: SCREEN_HEIGHT}]);
this.explosionColor = 0;
}
Rocket.prototype = new Particle();
Rocket.prototype.constructor = Rocket;
Rocket.prototype.explode = function() {
var count = Math.random() * 10 + 80;
for (var i = 0; i < count; i++) {
var particle = new Particle(this.pos);
var angle = Math.random() * Math.PI * 2;
// emulate 3D effect by using cosine and put more particles in the middle
var speed = Math.cos(Math.random() * Math.PI / 2) * 15;
particle.vel.x = Math.cos(angle) * speed;
particle.vel.y = Math.sin(angle) * speed;
particle.size = 10;
particle.gravity = 0.2;
particle.resistance = 0.92;
particle.shrink = Math.random() * 0.05 + 0.93;
particle.flick = true;
particle.color = this.explosionColor;
particles.push(particle);
}
};
Rocket.prototype.render = function(c) {
if (!this.exists()) {
return;
}
c.save();
c.globalCompositeOperation = 'lighter';
var x = this.pos.x,
y = this.pos.y,
r = this.size / 2;
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
gradient.addColorStop(0.1, "rgba(255, 255, 255 ," + this.alpha + ")");
gradient.addColorStop(1, "rgba(0, 0, 0, " + this.alpha + ")");
c.fillStyle = gradient;
c.beginPath();
c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size / 2 + this.size / 2 : this.size, 0, Math.PI * 2, true);
c.closePath();
c.fill();
c.restore();
};
body {
background-color: #000000;
margin: 0px;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Fireworks!</title>
</head>
<body/>
</html>
The problem is the canvas used by the script is positioned relative by default. To make it always visible completely on screen we have to make it fixed and set the top and left CSS values to 0.
Now because its fixed the canvas renders on top of everything. To get it in the background set z-index to -1.
All additions together:
canvas.style.position="fixed";
canvas.style.top="0";
canvas.style.left="0";
canvas.style.zIndex="-1";
Complete Source:
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight,
mousePos = {
x: 400,
y: 300
},
// create canvas
canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
particles = [],
rockets = [],
MAX_PARTICLES = 400,
colorCode = 0;
// init
$(document).ready(function() {
document.body.appendChild(canvas);
canvas.width = SCREEN_WIDTH;
canvas.height = SCREEN_HEIGHT;
canvas.style.position = "fixed";
canvas.style.top = "0";
canvas.style.left = "0";
canvas.style.zIndex = "-1";
setInterval(launch, 800);
setInterval(loop, 1000 / 50);
});
// update mouse position
$(document).mousemove(function(e) {
e.preventDefault();
mousePos = {
x: e.clientX,
y: e.clientY
};
});
// launch more rockets!!!
$(document).mousedown(function(e) {
for (var i = 0; i < 5; i++) {
launchFrom(Math.random() * SCREEN_WIDTH * 2 / 3 + SCREEN_WIDTH / 6);
}
});
function launch() {
launchFrom(mousePos.x);
}
function launchFrom(x) {
if (rockets.length < 10) {
var rocket = new Rocket(x);
rocket.explosionColor = Math.floor(Math.random() * 360 / 10) * 10;
rocket.vel.y = Math.random() * -3 - 4;
rocket.vel.x = Math.random() * 6 - 3;
rocket.size = 8;
rocket.shrink = 0.999;
rocket.gravity = 0.01;
rockets.push(rocket);
}
}
function loop() {
// update screen size
if (SCREEN_WIDTH != window.innerWidth) {
canvas.width = SCREEN_WIDTH = window.innerWidth;
}
if (SCREEN_HEIGHT != window.innerHeight) {
canvas.height = SCREEN_HEIGHT = window.innerHeight;
}
// clear canvas
context.fillStyle = "rgba(0, 0, 0, 0.05)";
context.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
var existingRockets = [];
for (var i = 0; i < rockets.length; i++) {
// update and render
rockets[i].update();
rockets[i].render(context);
// calculate distance with Pythagoras
var distance = Math.sqrt(Math.pow(mousePos.x - rockets[i].pos.x, 2) + Math.pow(mousePos.y - rockets[i].pos.y, 2));
// random chance of 1% if rockets is above the middle
var randomChance = rockets[i].pos.y < (SCREEN_HEIGHT * 2 / 3) ? (Math.random() * 100 <= 1) : false;
/* Explosion rules
- 80% of screen
- going down
- close to the mouse
- 1% chance of random explosion
*/
if (rockets[i].pos.y < SCREEN_HEIGHT / 5 || rockets[i].vel.y >= 0 || distance < 50 || randomChance) {
rockets[i].explode();
} else {
existingRockets.push(rockets[i]);
}
}
rockets = existingRockets;
var existingParticles = [];
for (var i = 0; i < particles.length; i++) {
particles[i].update();
// render and save particles that can be rendered
if (particles[i].exists()) {
particles[i].render(context);
existingParticles.push(particles[i]);
}
}
// update array with existing particles - old particles should be garbage collected
particles = existingParticles;
while (particles.length > MAX_PARTICLES) {
particles.shift();
}
}
function Particle(pos) {
this.pos = {
x: pos ? pos.x : 0,
y: pos ? pos.y : 0
};
this.vel = {
x: 0,
y: 0
};
this.shrink = .97;
this.size = 2;
this.resistance = 1;
this.gravity = 0;
this.flick = false;
this.alpha = 1;
this.fade = 0;
this.color = 0;
}
Particle.prototype.update = function() {
// apply resistance
this.vel.x *= this.resistance;
this.vel.y *= this.resistance;
// gravity down
this.vel.y += this.gravity;
// update position based on speed
this.pos.x += this.vel.x;
this.pos.y += this.vel.y;
// shrink
this.size *= this.shrink;
// fade out
this.alpha -= this.fade;
};
Particle.prototype.render = function(c) {
if (!this.exists()) {
return;
}
c.save();
c.globalCompositeOperation = 'lighter';
var x = this.pos.x,
y = this.pos.y,
r = this.size / 2;
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
gradient.addColorStop(0.1, "rgba(255,255,255," + this.alpha + ")");
gradient.addColorStop(0.8, "hsla(" + this.color + ", 100%, 50%, " + this.alpha + ")");
gradient.addColorStop(1, "hsla(" + this.color + ", 100%, 50%, 0.1)");
c.fillStyle = gradient;
c.beginPath();
c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size : this.size, 0, Math.PI * 2, true);
c.closePath();
c.fill();
c.restore();
};
Particle.prototype.exists = function() {
return this.alpha >= 0.1 && this.size >= 1;
};
function Rocket(x) {
Particle.apply(this, [{
x: x,
y: SCREEN_HEIGHT
}]);
this.explosionColor = 0;
}
Rocket.prototype = new Particle();
Rocket.prototype.constructor = Rocket;
Rocket.prototype.explode = function() {
var count = Math.random() * 10 + 80;
for (var i = 0; i < count; i++) {
var particle = new Particle(this.pos);
var angle = Math.random() * Math.PI * 2;
// emulate 3D effect by using cosine and put more particles in the middle
var speed = Math.cos(Math.random() * Math.PI / 2) * 15;
particle.vel.x = Math.cos(angle) * speed;
particle.vel.y = Math.sin(angle) * speed;
particle.size = 10;
particle.gravity = 0.2;
particle.resistance = 0.92;
particle.shrink = Math.random() * 0.05 + 0.93;
particle.flick = true;
particle.color = this.explosionColor;
particles.push(particle);
}
};
Rocket.prototype.render = function(c) {
if (!this.exists()) {
return;
}
c.save();
c.globalCompositeOperation = 'lighter';
var x = this.pos.x,
y = this.pos.y,
r = this.size / 2;
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
gradient.addColorStop(0.1, "rgba(255, 255, 255 ," + this.alpha + ")");
gradient.addColorStop(1, "rgba(0, 0, 0, " + this.alpha + ")");
c.fillStyle = gradient;
c.beginPath();
c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size / 2 + this.size / 2 : this.size, 0, Math.PI * 2, true);
c.closePath();
c.fill();
c.restore();
};
body {
background-color: #000000;
margin: 0px;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Fireworks!</title>
</head>
<body>
<p>
test
</p>
<br />
<p>
test2
</p>
</body>
</html>
I have a canvas
(check in Chrome only)
$(function() {
var Fire = function(){
this.canvas = document.getElementById('fire');
this.ctx = this.canvas.getContext('2d');
this.canvas.height = window.innerHeight;
this.canvas.width = window.innerWidth;
this.aFires = [];
this.aSpark = [];
this.aSpark2 = [];
this.mouse = {
x : this.canvas.width * .5,
y : this.canvas.height * .75,
}
this.init();
}
Fire.prototype.init = function()
{
//this.canvas.addEventListener('mousemove', this.updateMouse.bind( this ), false);
}
Fire.prototype.run = function(){
this.update();
this.draw();
if( this.bRuning )
requestAnimationFrame( this.run.bind( this ) );
}
Fire.prototype.start = function(){
this.bRuning = true;
this.run();
}
Fire.prototype.update = function(){
this.aFires.push( new Flame( this.mouse ) );
this.aSpark.push( new Spark( this.mouse ) );
this.aSpark2.push( new Spark( this.mouse ) );
for (var i = this.aFires.length - 1; i >= 0; i--) {
if( this.aFires[i].alive )
this.aFires[i].update();
else
this.aFires.splice( i, 1 );
}
for (var i = this.aSpark.length - 1; i >= 0; i--) {
if( this.aSpark[i].alive )
this.aSpark[i].update();
else
this.aSpark.splice( i, 1 );
}
for (var i = this.aSpark2.length - 1; i >= 0; i--) {
if( this.aSpark2[i].alive )
this.aSpark2[i].update();
else
this.aSpark2.splice( i, 1 );
}
}
Fire.prototype.draw = function(){
this.ctx.globalCompositeOperation = "source-over";
this.ctx.fillStyle = "rgba( 15, 5, 2, 1 )";
this.ctx.fillRect( 0, 0, window.innerWidth, window.innerHeight );
this.grd = this.ctx.createRadialGradient( this.mouse.x, this.mouse.y - 200,200,this.mouse.x, this.mouse.y - 100,0 );
this.grd.addColorStop(0,"rgb( 15, 5, 2 )");
this.grd.addColorStop(1,"rgb(30, 10, 2 )");
this.ctx.beginPath();
this.ctx.arc( this.mouse.x, this.mouse.y - 100, 200, 0, 2*Math.PI );
this.ctx.fillStyle= this.grd;
this.ctx.fill();
this.ctx.globalCompositeOperation = "overlay";//or lighter or soft-light
for (var i = this.aFires.length - 1; i >= 0; i--) {
this.aFires[i].draw( this.ctx );
}
this.ctx.globalCompositeOperation = "soft-light";//"soft-light";//"color-dodge";
for (var i = this.aSpark.length - 1; i >= 0; i--) {
if( ( i % 2 ) === 0 )
this.aSpark[i].draw( this.ctx );
}
this.ctx.globalCompositeOperation = "color-dodge";//"soft-light";//"color-dodge";
for (var i = this.aSpark2.length - 1; i >= 0; i--) {
this.aSpark2[i].draw( this.ctx );
}
}
// Flame
var Flame = function( mouse ){
this.cx = mouse.x;
this.cy = mouse.y;
this.x = rand( this.cx - 600, this.cx + 600);
this.y = rand( this.cy - -200, this.cy + 5);
this.vy = rand( 1, 3 );
this.vx = rand( -1, 1 );
this.r = rand( 20, 30 );
this.life = rand( 3, 6 );
this.alive = true;
this.c = {
h : Math.floor( rand( 2, 40) ),
s : 1000,
l : rand( 80, 100 ),
a : 0,
ta : rand( 0.8, 0.9 )
}
}
Flame.prototype.update = function()
{
this.y -= this.vy;
this.vy += 0.05;
this.x += this.vx;
if( this.x < this.cx )
this.vx += 0.1;
else
this.vx -= 0.1;
if( this.r > 0 )
this.r -= 0.1;
if( this.r <= 0 )
this.r = 0;
this.life -= 0.15;
if( this.life <= 0 ){
this.c.a -= 0.05;
if( this.c.a <= 0 )
this.alive = false;
}else if( this.life > 0 && this.c.a < this.c.ta ){
this.c.a += .08;
}
}
Flame.prototype.draw = function( ctx ){
ctx.beginPath();
ctx.arc( this.x, this.y, this.r * 3, 0, 2*Math.PI );
ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a/20) + ")";
ctx.fill();
ctx.beginPath();
ctx.arc( this.x, this.y, this.r, 0, 2*Math.PI );
ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")";
ctx.fill();
}
// Spark
var Spark = function( mouse ){
this.cx = mouse.x;
this.cy = mouse.y;
this.x = rand( this.cx -600, this.cx + 600);
this.y = rand( this.cy - -200, this.cy + 5);
this.lx = this.x;
this.ly = this.y;
<!-- Edit Value -->
this.vy = rand( 1, 3 );
this.vx = rand( -4, 4 );
this.r = rand( 0, 1 );
this.life = rand( 4, 5 );
this.alive = true;
this.c = {
h : Math.floor( rand( 2, 40) ),
s : 100,
l : rand( 40, 100 ),
a : rand( 0.8, 0.9 )
}
}
Spark.prototype.update = function()
{
this.lx = this.x;
this.ly = this.y;
this.y -= this.vy;
this.x += this.vx;
if( this.x < this.cx )
this.vx += 0.2;
else
this.vx -= 0.2;
this.vy += 0.08;
this.life -= 0.1;
if( this.life <= 0 ){
this.c.a -= 0.05;
if( this.c.a <= 0 )
this.alive = false;
}
}
Spark.prototype.draw = function( ctx ){
ctx.beginPath();
ctx.moveTo( this.lx , this.ly);
ctx.lineTo( this.x, this.y);
ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a / 2) + ")";
ctx.lineWidth = this.r * 2;
ctx.lineCap = 'round';
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.moveTo( this.lx , this.ly);
ctx.lineTo( this.x, this.y);
ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")";
ctx.lineWidth = this.r;
ctx.stroke();
ctx.closePath();
}
rand = function( min, max ){ return Math.random() * ( max - min) + min; };
onresize = function () { oCanvas.canvas.width = window.innerWidth; oCanvas.canvas.height = window.innerHeight; };
var oCanvas;
init = function()
{
oCanvas = new Fire();
oCanvas.start();
}
window.onload = init;
});
h1
{
position:relative;
z-index:1;
float:right;
width:100%;
color:#fff;
}
#fire
{
position:fixed;
height:100%;
top:0;
right:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<canvas id="fire"></canvas>
<h1>Hover Me!</h1>
I want to change the amount of canvas every time the Hover Me! is hoverd.
For example, this value is this.vy = rand (1, 3); To this value this.vy = rand (1, 30); When the hover changes.
Another thing to note is why the Mozilla browser is extremely difficult to execute and the colors in the Internet Explorer are not supported.
please help me!