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();
})
Related
// Initial Setup
const canvas = document.querySelector('canvas');
const c = canvas.getContext('2d');
// Canvas size
canvas.width = innerWidth;
canvas.height = innerHeight;
//Color
const colors = [
{r: 51, g: 99, b: 252}
//{r: 77, g: 57, b: 206},
// {r: 0, g: 189, b: 255},
];
// Utility Functions
function randomIntFromRange(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function randomColor(colors) {
return colors[Math.floor(Math.random() * colors.length)];
}
function distance(x1, y1, x2, y2) {
const xDist = x2 - x1;
const yDist = y2 - y1;
return Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
}
function rotateVelocities(velocity, theta) {
const rotatedVelocity = {
x: velocity.x * Math.cos(theta) - velocity.y * Math.sin(theta),
y: velocity.x * Math.sin(theta) + velocity.y * Math.cos(theta)
};
return rotatedVelocity;
}
// Objects
function Particle(x, y, radius, rgb) {
this.x = x;
this.y = y;
this.velocity = {
x: (Math.random() - 0.5) * 3,
y: (Math.random() - 0.5) * 3
};
this.radius = radius;
this.mass = 1;
this.opacity = 0;
this.r = rgb.r;
this.g = rgb.g;
this.b = rgb.b;
this.update = particles => {
this.draw();
for (let i = 0; i < particles.length; i++) {
const otherParticle = particles[i];
if (this.x === otherParticle.x) continue;
if (distance(this.x, this.y, otherParticle.x, otherParticle.y) - this.radius * 2 < 0) {
const res = {
x: this.velocity.x - otherParticle.velocity.x,
y: this.velocity.y - otherParticle.velocity.y
};
if (res.x * (otherParticle.x - this.x) + res.y * (otherParticle.y - this.y) >= 0) {
const m1 = this.mass;
const m2 = otherParticle.mass;
const theta = -Math.atan2(otherParticle.y - this.y, otherParticle.x - this.x);
const rotatedVelocity1 = rotateVelocities(this.velocity, theta);
const rotatedVelocity2 = rotateVelocities(otherParticle.velocity, theta);
const swapVelocity1 = { x: rotatedVelocity1.x * (m1 - m2) / (m1 + m2) + rotatedVelocity2.x * 2 * m2 / (m1 + m2), y: rotatedVelocity1.y };
const swapVelocity2 = { x: rotatedVelocity2.x * (m1 - m2) / (m1 + m2) + rotatedVelocity1.x * 2 * m2 / (m1 + m2), y: rotatedVelocity2.y };
const u1 = rotateVelocities(swapVelocity1, -theta);
const u2 = rotateVelocities(swapVelocity2, -theta);
this.velocity.x = u1.x;
this.velocity.y = u1.y;
otherParticle.velocity.x = u2.x;
otherParticle.velocity.y = u2.y;
}
}
if (distance(this.x, this.y, otherParticle.x, otherParticle.y) - this.radius * 2 < 0 ) {
this.opacity = 0.1;
}
}
if (this.x + this.radius >= canvas.width || this.x - this.radius <= 0)
this.velocity.x = -this.velocity.x;
if (this.y + this.radius >= canvas.height || this.y - this.radius <= 0)
this.velocity.y = -this.velocity.y;
this.x += this.velocity.x;
this.y += this.velocity.y;
};
this.draw = () => {
c.beginPath();
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
c.strokeStyle = `rgba(${this.r}, ${this.g}, ${this.b}, 1)`;
c.stroke();
c.fillStyle = `rgba(${this.r}, ${this.g}, ${this.b}, ${this.opacity}`;
c.fill();
c.closePath();
};
}
// Implementation
let particles;
function init() {
particles = [];
let radius = 80
for (let i = 0; i < 10; i++) {
let x = randomIntFromRange(radius, innerWidth - radius);
let y = randomIntFromRange(radius, innerHeight - radius);
if (particles.length >= 1) {
for (let j = 0; j < particles.length; j++) {
if (distance(x, y, particles[j].x, particles[j].y) - radius * 2 < 0) {
x = randomIntFromRange(radius, innerWidth - radius);
y = randomIntFromRange(radius, innerHeight - radius);
j = -1;
continue;
}
}
}
particles.push(new Particle(x, y, radius, randomColor(colors)));
}
}
//I would like to initiate one circle out of all as red and whenever the red circle collide with other circle, other circle got red and at last all circle become red. but when two white circle collide it should not become red. basically one infected circle making other circle infected by touching.
I have tried all the jQuery tricks as well as the CSS tricks, but none of them work.. I don't really know anything about <canvas> but I've been trying to solve this for a day now.. can anybody help?
I am trying not mess up the code and just make the black background transparent so that I could use this canvas over a carousal..
// helper functions
const PI2 = Math.PI * 2
const random = (min, max) => Math.random() * (max - min + 1) + min | 0
const timestamp = _ => new Date().getTime()
// container
class Birthday {
constructor() {
this.resize()
// create a lovely place to store the firework
this.fireworks = []
this.counter = 0
}
resize() {
this.width = canvas.width = window.innerWidth
let center = this.width / 2 | 0
this.spawnA = center - center / 4 | 0
this.spawnB = center + center / 4 | 0
this.height = canvas.height = window.innerHeight
this.spawnC = this.height * .1
this.spawnD = this.height * .5
}
onClick(evt) {
let x = evt.clientX || evt.touches && evt.touches[0].pageX
let y = evt.clientY || evt.touches && evt.touches[0].pageY
let count = random(3, 5)
for (let i = 0; i < count; i++) this.fireworks.push(new Firework(
random(this.spawnA, this.spawnB),
this.height,
x,
y,
random(0, 260),
random(30, 110)))
this.counter = -1
}
update(delta) {
ctx.globalCompositeOperation = 'hard-light'
ctx.fillStyle = `rgba(20,20,20,${ 7 * delta })`
ctx.fillRect(0, 0, this.width, this.height)
ctx.globalCompositeOperation = 'lighter'
for (let firework of this.fireworks) firework.update(delta)
// if enough time passed... create new new firework
this.counter += delta * 3 // each second
if (this.counter >= 1) {
this.fireworks.push(new Firework(
random(this.spawnA, this.spawnB),
this.height,
random(0, this.width),
random(this.spawnC, this.spawnD),
random(0, 360),
random(30, 110)))
this.counter = 0
}
// remove the dead fireworks
if (this.fireworks.length > 1000) this.fireworks = this.fireworks.filter(firework => !firework.dead)
}
}
class Firework {
constructor(x, y, targetX, targetY, shade, offsprings) {
this.dead = false
this.offsprings = offsprings
this.x = x
this.y = y
this.targetX = targetX
this.targetY = targetY
this.shade = shade
this.history = []
}
update(delta) {
if (this.dead) return
let xDiff = this.targetX - this.x
let yDiff = this.targetY - this.y
if (Math.abs(xDiff) > 3 || Math.abs(yDiff) > 3) { // is still moving
this.x += xDiff * 2 * delta
this.y += yDiff * 2 * delta
this.history.push({
x: this.x,
y: this.y
})
if (this.history.length > 20) this.history.shift()
} else {
if (this.offsprings && !this.madeChilds) {
let babies = this.offsprings / 2
for (let i = 0; i < babies; i++) {
let targetX = this.x + this.offsprings * Math.cos(PI2 * i / babies) | 0
let targetY = this.y + this.offsprings * Math.sin(PI2 * i / babies) | 0
birthday.fireworks.push(new Firework(this.x, this.y, targetX, targetY, this.shade, 0))
}
}
this.madeChilds = true
this.history.shift()
}
if (this.history.length === 0) this.dead = true
else if (this.offsprings) {
for (let i = 0; this.history.length > i; i++) {
let point = this.history[i]
ctx.beginPath()
ctx.fillStyle = 'hsl(' + this.shade + ',100%,' + i + '%)'
ctx.arc(point.x, point.y, 1, 0, PI2, false)
ctx.fill()
}
} else {
ctx.beginPath()
ctx.fillStyle = 'hsl(' + this.shade + ',100%,50%)'
ctx.arc(this.x, this.y, 1, 0, PI2, false)
ctx.fill()
}
}
}
let canvas = document.getElementById('birthday')
let ctx = canvas.getContext('2d')
let then = timestamp()
let birthday = new Birthday
window.onresize = () => birthday.resize()
document.onclick = evt => birthday.onClick(evt)
document.ontouchstart = evt => birthday.onClick(evt)
;
(function loop() {
requestAnimationFrame(loop)
let now = timestamp()
let delta = now - then
then = now
birthday.update(delta / 1000)
})()
<canvas id="birthday"></canvas>
All you need to do is replace fillRect with clearRect in the update method of the Birthday class like this:
ctx.clearRect(0, 0, this.width, this.height)
You may need to make further adjustments to the color of the firework trail though, since it seems like it was supposed to match the background color.
If your canvas still isn't transparent, check your css to ensure that you're not setting the background color that way.
const PI2 = Math.PI * 2
const random = (min, max) => Math.random() * (max - min + 1) + min | 0
const timestamp = _ => new Date().getTime()
// container
class Birthday {
constructor() {
this.resize()
// create a lovely place to store the firework
this.fireworks = []
this.counter = 0
}
resize() {
this.width = canvas.width = window.innerWidth
let center = this.width / 2 | 0
this.spawnA = center - center / 4 | 0
this.spawnB = center + center / 4 | 0
this.height = canvas.height = window.innerHeight
this.spawnC = this.height * .1
this.spawnD = this.height * .5
}
onClick(evt) {
let x = evt.clientX || evt.touches && evt.touches[0].pageX
let y = evt.clientY || evt.touches && evt.touches[0].pageY
let count = random(3, 5)
for (let i = 0; i < count; i++) this.fireworks.push(new Firework(
random(this.spawnA, this.spawnB),
this.height,
x,
y,
random(0, 260),
random(30, 110)))
this.counter = -1
}
update(delta) {
ctx.globalCompositeOperation = 'hard-light'
ctx.fillStyle = `rgba(20,20,20,${ 7 * delta })`
ctx.clearRect(0, 0, this.width, this.height)
ctx.globalCompositeOperation = 'lighter'
for (let firework of this.fireworks) firework.update(delta)
// if enough time passed... create new new firework
this.counter += delta * 3 // each second
if (this.counter >= 1) {
this.fireworks.push(new Firework(
random(this.spawnA, this.spawnB),
this.height,
random(0, this.width),
random(this.spawnC, this.spawnD),
random(0, 360),
random(30, 110)))
this.counter = 0
}
// remove the dead fireworks
if (this.fireworks.length > 1000) this.fireworks = this.fireworks.filter(firework => !firework.dead)
}
}
class Firework {
constructor(x, y, targetX, targetY, shade, offsprings) {
this.dead = false
this.offsprings = offsprings
this.x = x
this.y = y
this.targetX = targetX
this.targetY = targetY
this.shade = shade
this.history = []
}
update(delta) {
if (this.dead) return
let xDiff = this.targetX - this.x
let yDiff = this.targetY - this.y
if (Math.abs(xDiff) > 3 || Math.abs(yDiff) > 3) { // is still moving
this.x += xDiff * 2 * delta
this.y += yDiff * 2 * delta
this.history.push({
x: this.x,
y: this.y
})
if (this.history.length > 20) this.history.shift()
} else {
if (this.offsprings && !this.madeChilds) {
let babies = this.offsprings / 2
for (let i = 0; i < babies; i++) {
let targetX = this.x + this.offsprings * Math.cos(PI2 * i / babies) | 0
let targetY = this.y + this.offsprings * Math.sin(PI2 * i / babies) | 0
birthday.fireworks.push(new Firework(this.x, this.y, targetX, targetY, this.shade, 0))
}
}
this.madeChilds = true
this.history.shift()
}
if (this.history.length === 0) this.dead = true
else if (this.offsprings) {
for (let i = 0; this.history.length > i; i++) {
let point = this.history[i]
ctx.beginPath()
ctx.fillStyle = 'hsl(' + this.shade + ',100%,' + i + '%)'
ctx.arc(point.x, point.y, 1, 0, PI2, false)
ctx.fill()
}
} else {
ctx.beginPath()
ctx.fillStyle = 'hsl(' + this.shade + ',100%,50%)'
ctx.arc(this.x, this.y, 1, 0, PI2, false)
ctx.fill()
}
}
}
let canvas = document.getElementById('birthday')
let ctx = canvas.getContext('2d')
let then = timestamp()
let birthday = new Birthday
window.onresize = () => birthday.resize()
document.onclick = evt => birthday.onClick(evt)
document.ontouchstart = evt => birthday.onClick(evt)
;
(function loop() {
requestAnimationFrame(loop)
let now = timestamp()
let delta = now - then
then = now
birthday.update(delta / 1000)
})()
div {
height : 100vh;
width : 100vw;
display : flex;
flex-direction : center;
align-items : center;
justify-content : center;
}
canvas {
position : absolute;
top : 0;
left : 0;
}
<div>Content Underneath</div>
<canvas id="birthday"></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>
How make Santa follow to mouse with rotation and own speed, not mouse speed?
Where mouse now - it's destination, where go santa with own speed.
Santa rotate with speed.
How can I do this?
Demo code
game.js
var canvas, ctx, player
function init() {
canvas = document.getElementById("canvas")
ctx = canvas.getContext( "2d" )
resizeCanvas()
player = new Player(
ctx,
canvas.width / 2,
canvas.height / 2 + 100
)
window.onresize = resizeCanvas
canvas.onmousemove = mousemove
}
function mousemove( e ) {
player.x = e.clientX * devicePixelRatio
player.y = e.clientY * devicePixelRatio
}
function render() {
ctx.clearRect( 0, 0, canvas.width, canvas.height )
player.draw()
}
function step() {
render()
requestAnimationFrame( step )
}
init()
step()
It's not trivial task with rotation.
Modified version with some magic: demo
For distance used Pythagorean theorem.
Player moving to forward (by current rotation).
class Player {
constructor(ctx, x, y) {
this.x = x
this.y = y
this.dest = {
x: 0,
y: 0
}
this.width = 200
this.height = 200
this.velocity = 12
this.angularVelocity = 7
this.rotation = 0
this.ctx = ctx
this.image = new Image()
this.image.src = "//habrastorage.org/files/447/9b4/6d3/4479b46d397e439a9613ce122a66a506.png"
}
draw() {
this.ctx.translate(this.x, this.y)
this.ctx.rotate(this.rotation + 4.7)
this.ctx.drawImage(
this.image,
-this.width / 2, -this.height / 2,
this.width, this.height
)
this.ctx.rotate(-this.rotation - 4.7)
this.ctx.translate(-this.x, -this.y)
}
distance(target) {
let data = {
x: target.x - this.x,
y: target.y - this.y
}
data.len = Math.sqrt(data.x * data.x + data.y * data.y)
return data
}
rotate(dt) {
let path = this.distance(this.dest)
let target = Math.atan2(path.y, path.x)
let delta = this.rotation - target
if (delta > 0.1 || delta < -0.1) {
var _delta = delta
if (_delta < 0) {
_delta += Math.PI * 2
}
if (delta < -Math.PI || (delta > 0 && delta < Math.PI)) {
this.rotation -= _delta / this.angularVelocity
} else {
this.rotation -= (_delta - Math.PI * 2) / this.angularVelocity
}
// Reduce character rotation into the -PI thru PI range
this.rotation = (this.rotation + 3 * Math.PI) % (2 * Math.PI) - Math.PI
}
}
step() {
let distance = this.distance(this.dest).len
if (distance < this.width / 1.5) {
this.draw()
return
}
let vel = distance / 15
if (vel > this.velocity) {
vel = this.velocity
}
this.rotate()
this.x += vel * Math.cos(this.rotation)
this.y += vel * Math.sin(this.rotation)
this.draw()
}
}
kindly bear with my english
I am working on creating (I am new to Canvas) Cylinder. Dynamically fill color when the user enter the percentage value in the text box for example 10% the cylinder fill for 10% like wise till 100%.
I have created cylinder, I have created the little validation for the text box when i tried to other value instead of %
here is my code for validation and Filling color
<script type="text/javascript">
$(document).ready(function() {
$("#my_input").focusout(function(event) {
if($("#my_input").val().indexOf("%") != -1){
if($.isNumeric($("#my_input").val().replace('%',''))) {
// Allow only backspace and delete
if ( event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 37) {
//$("#myCanvas").animate({ opacity: 0.25 });
}
else {
// Ensure that it is a number and stop the keypress
if (event.keyCode < 48 || event.keyCode > 57) {
event.preventDefault();
}
}
perc = parseInt($("#my_input").val().replace('%','')) / 100;
draw();
}
}
else{
alert('Value in %');
}
});
});
function draw()
{
context.clearRect(0, 0, canvas.width, canvas.height);
var x = 180;
var y = 40;
context.beginPath();
context.rect(x, y, maxWidth, maxHeight);
context.lineWidth = 7;
var per = perc;
if(per > 1)perc = 1;
// fill
context.beginPath();
context.fillStyle = 'yellow';
context.rect(x, y, maxWidth * perc, maxHeight);
context.fill();
}
Here is my HTML Code for canvas
<canvas id="canvas" width="300px" height="300px"></canvas>
Here is the code for Creating Cylinder
<script type='text/javascript'>//<![CDATA[
//the below is code is for to work RequestAnimationFrame (SVG) in all the browsers -- Mahadevan
(function() {
var lastTime = 0;
var vendors = ['webkit', 'moz'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}());
//the below code is to generate Cylinder object -- Mahadevan
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var degreeAngle = 0;
requestAnimationFrame(animate);
function drawRotatedCylinder(x, y, w, h, degreeAngle) {
context.save();
context.translate(x + w / 10, y + h / 10);
context.rotate(degreeAngle * Math.PI / 180);
drawCylinder(-w / 10, -h / 10, w, h);
context.restore();
}
function drawCylinder(x, y, w, h) {
context.beginPath(); //to draw the top circle
for (var i = 0 * Math.PI; i < 2 * Math.PI; i += 0.01) {
xPos = (x + w / 2) - (w / 2 * Math.sin(i)) * Math.sin(0 * Math.PI) + (w / 2 * Math.cos(i)) * Math.cos(0 * Math.PI);
yPos = (y + h / 8) + (h / 8 * Math.cos(i)) * Math.sin(0 * Math.PI) + (h / 8 * Math.sin(i)) * Math.cos(0 * Math.PI);
if (i == 0) {
context.moveTo(xPos, yPos);
} else {
context.lineTo(xPos, yPos);
}
}
context.moveTo(x, y + h / 8);
context.lineTo(x, y + h - h / 8);
for (var i = 0 * Math.PI; i < Math.PI; i += 0.01) {
xPos = (x + w / 2) - (w / 2 * Math.sin(i)) * Math.sin(0 * Math.PI) + (w / 2 * Math.cos(i)) * Math.cos(0 * Math.PI);
yPos = (y + h - h / 8) + (h / 8 * Math.cos(i)) * Math.sin(0 * Math.PI) + (h / 8 * Math.sin(i)) * Math.cos(0 * Math.PI);
if (i == 0) {
context.moveTo(xPos, yPos);
} else {
context.lineTo(xPos, yPos);
}
}
context.moveTo(x + w, y + h / 8);
context.lineTo(x + w, y + h - h / 8);
context.strokeStyle = '#ff0000';
context.stroke();
context.fillStyle = 'yellow';
context.fill();
}
function animate() {
//requestAnimationFrame(animate);
context.clearRect(0, 0, canvas.width, canvas.height);
drawRotatedCylinder(100, 100, 180, 180, degreeAngle++);
}
//]]>
</script>
And here is my Final HTml Code
Numberic Value <input type ="text" id="my_input" class="numeric" name="my_input" placeholder="Enter value"/>
When i tried to enter the value in the textbox that cylinder canvas getting hidden and i am getting an error as Uncaught ReferenceError: maxWidth is not defined
When i checked for circle canvas in google it says i need to put (context.rect) instead of rect i need to put arc i tried putting that still it was not working.
Kindly help me for the above solution
Thanks & REgards
Mahadevan
You should adjust the height of the cylinder, not the width... And should redraw the cylinder if you are clearing (clearRect) the canvas.
You can try with the following function:
function draw()
{
maxWidth = 180;
maxHeight = 140;
context.clearRect(0, 0, canvas.width, canvas.height);
var x = 190;
var y = 260;
var per = perc;
if(per > 1)perc = 1;
// fill
context.beginPath();
context.fillStyle = 'yellow';
context.rect(x-maxWidth/2, y-maxHeight * perc, maxWidth, maxHeight * perc);
context.fill();
drawCylinder(100, 100, 180, 180);
}
Check working Fiddle demo ...