Related
I am trying to get alert when any of the balls turn red. Every time when the balls turn red, alert should come. Anyone can you help me out to get this thing?
And i want the canvas outline stroke as black color. How to do that? I tried adding > canvas.stokestyle also but it not showing anything.
function getBall(xVal, yVal, dxVal, dyVal, rVal, colorVal) {
var ball = {
x: xVal,
y: yVal,
dx: dxVal,
dy: dyVal,
r: rVal,
color: colorVal
};
return ball;
}
var canvas = document.getElementById("Canvas");
var ctx = canvas.getContext("2d");
ctx.globalAlpha = 0.8
var containerR = 150;
canvas.width = canvas.height = containerR * 2;
canvas.style["border-radius"] = containerR + "px";
var balls = [
getBall(canvas.width / 2, canvas.height - 30, 2, 2, 8, "#32CD32"),
getBall(canvas.width / 3, canvas.height - 50, 2, 2, 8, "#32CD32"),
getBall(canvas.width / 4, canvas.height - 60, 2, 2, 8, "#32CD32"),
getBall(canvas.width / 2, canvas.height / 5, 2, 2, 8, "#32CD32")
];
function drawBall(curBall) {
ctx.beginPath();
ctx.arc(curBall.x, curBall.y, curBall.r, 0, Math.PI * 2, false);
ctx.fillStyle = curBall.color;
ctx.fill();
ctx.closePath();
}
function updatePos(curBall) {
curBall.x += curBall.dx;
curBall.y += curBall.dy;
var dx = curBall.x - containerR;
var dy = curBall.y - containerR;
if (Math.sqrt(dx * dx + dy * dy) >= containerR - curBall.r) {
var v = Math.sqrt(curBall.dx * curBall.dx + curBall.dy * curBall.dy);
var angleToCollisionPoint = Math.atan2(-dy, dx);
var oldAngle = Math.atan2(-curBall.dy, curBall.dx);
var newAngle = 2 * angleToCollisionPoint - oldAngle;
curBall.dx = -v * Math.cos(newAngle);
curBall.dy = v * Math.sin(newAngle);
}
}
function ballsMeet(b1, b2) {
return (Math.hypot(Math.abs(b1.x - b2.x), Math.abs(b1.y - b2.y)) < (b1.r + b2.r))
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < balls.length; i++) {
drawBall(balls[i])
updatePos(balls[i])
meet = false
for (var j = 0; j < balls.length; j++) {
if (ballsMeet(balls[i], balls[j]) && i != j) {
meet = true
balls[j].color = "red"
break
}
}
balls[i].color = (meet) ? "red" : "green"
}
requestAnimationFrame(draw);
}
draw();
canvas {
background: #eee;
margin: 0 auto;
}
<html>
<canvas id="Canvas"></canvas>
<div id="x"></div>
<div id="y"></div>
<div id="dx"></div>
<div id="dy"></div>
</html>
Thanks in advance
Don't use alert() when working with RequestAnimationFrame
Don't color balls inside draw (BTW call it engine since it's a RAF recursion), use the drawBall instead.
Given the above, on collision, set the ball property collider to be the colliding ball - and paint accordingly inside drawBall - that way you can restore to the original color once the ball exits collision: ctx.fillStyle = ball.collider ? "red" : ball.color;
You could use CSS radius and box-shadow on the CANVAS element
const ctx = document.getElementById("Canvas").getContext("2d");
const containerR = 90;
const size = containerR * 2
ctx.canvas.width = ctx.canvas.height = size;
ctx.globalAlpha = 0.8
const getBall = (x, y, dx, dy, r, color) => ({x, y, dx, dy, r, color});
const balls = [
getBall(size / 2, size - 30, 1, 1, 30, "Blue"),
getBall(size / 3, size - 50, 1, 1, 20, "Yellow"),
getBall(size / 4, size - 60, 1, 1, 10, "Fuchsia"),
getBall(size / 2, size / 5, 1, 1, 8, "Green"),
];
const drawBall = (ball) => {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2, false);
ctx.fillStyle = ball.collider ? "red" : ball.color;
ctx.fill();
ctx.closePath();
}
const updatePos = (ball) => {
ball.x += ball.dx;
ball.y += ball.dy;
const dx = ball.x - containerR;
const dy = ball.y - containerR;
if (Math.sqrt(dx * dx + dy * dy) >= containerR - ball.r) {
const v = Math.sqrt(ball.dx * ball.dx + ball.dy * ball.dy);
const angleToCollisionPoint = Math.atan2(-dy, dx);
const oldAngle = Math.atan2(-ball.dy, ball.dx);
const newAngle = 2 * angleToCollisionPoint - oldAngle;
ball.dx = -v * Math.cos(newAngle);
ball.dy = v * Math.sin(newAngle);
}
}
const collides = (a, b) => (Math.hypot(Math.abs(a.x - b.x), Math.abs(a.y - b.y)) < (a.r + b.r));
function engine() {
console.clear(); // Clear console test messages
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
balls.forEach((a, ai) => {
a.collider = undefined;
balls.forEach((b, bi) => {
if (bi === ai) return; // Don't look at self
if (collides(a, b)) a.collider = b; // Store the colliding B ball
});
if (a.collider) { // If ball has a collider:
console.log(`${a.color[0]} → ← ${a.collider.color[0]}`);
}
updatePos(a);
drawBall(a);
});
requestAnimationFrame(engine);
}
engine();
canvas {
background: #eee;
margin: 0 auto;
border-radius: 50%;
box-shadow: 0 0 0 4px #000;
}
<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 found this js spinner and I like how it has the counter at the end. It counts down from 15 seconds. I was wondering if it would be possible to make it so that if you land on geography for example it counts down 5 seconds and then redirects you to a separate website. And history would bring you to a different link and so on. Thanks
JavaScript
var colors = ["#ffff00" , "#1be11b", "#0000ff", "#7e7e7e", "#8a2be2", "#006400", "#2980B9", "#E74C3C"];
// NEED to pre load this data prior
var prize_descriptions = ["GENERAL", "GEOGRAPHY", "HISTORY", "ARTS", "SCIENCE", "SPORTS", "RELIGION", "MEDIA"];
var current_user_status = {};
var startAngle = 0;
var arc = Math.PI / 4;
var spinTimeout = null;
var spinArcStart = 10;
var spinTime = 0;
var spinTimeTotal = 0;
var current_user_status = null;
var spin_results = null;
var wheel;
var counter, tt;
function drawSpinnerWheel() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var outsideRadius = 200;
var textRadius = 160;
var insideRadius = 125;
wheel = canvas.getContext("2d");
wheel.clearRect(0, 0, 500, 500);
wheel.strokeStyle = "#ecf0f1";
wheel.lineWidth = 5;
wheel.font = '12px Helvetica, Arial';
for (var i = 0; i < 8; i++) {
var angle = startAngle + i * arc;
wheel.fillStyle = colors[i];
wheel.beginPath();
wheel.arc(250, 250, outsideRadius, angle, angle + arc, false);
wheel.arc(250, 250, insideRadius, angle + arc, angle, true);
wheel.stroke();
wheel.fill();
wheel.save();
wheel.shadowOffsetX = -1;
wheel.shadowOffsetY = -1;
wheel.shadowBlur = 0;
wheel.shadowColor = "rgb(220,220,220)";
wheel.fillStyle = "#ecf0f1";
wheel.translate(250 + Math.cos(angle + arc / 2) * textRadius, 250 + Math.sin(angle + arc / 2) * textRadius);
wheel.rotate(angle + arc / 2 + Math.PI / 2);
var text = prize_descriptions[i];
if (text === undefined) text = "Not this time!";
wheel.fillText(text, -wheel.measureText(text).width / 2, 0);
wheel.restore();
}
//Arrow
wheel.fillStyle = "#ecf0f1";
wheel.beginPath();
wheel.moveTo(250 - 4, 250 - (outsideRadius + 5));
wheel.lineTo(250 + 4, 250 - (outsideRadius + 5));
wheel.lineTo(250 + 4, 250 - (outsideRadius - 5));
wheel.lineTo(250 + 9, 250 - (outsideRadius - 5));
wheel.lineTo(250 + 0, 250 - (outsideRadius - 13));
wheel.lineTo(250 - 9, 250 - (outsideRadius - 5));
wheel.lineTo(250 - 4, 250 - (outsideRadius - 5));
wheel.lineTo(250 - 4, 250 - (outsideRadius + 5));
wheel.fill();
}
}
function spin() {
$("#spin").unbind('click');
$("#spin").attr("id", "nospin");
document.getElementById('timer').innerHTML = " ";
document.getElementById('category').innerHTML = " ";
spinMovement = Math.floor(Math.random() * 20) + prize_descriptions.length * 2;
spinAngleStart = 1 * 10 + spinMovement;
spinTime = 0;
spinTimeTotal = Math.floor(Math.random() * 4) * Math.floor(Math.random() * 6) + Math.floor(Math.random() * 8) * Math.floor(Math.random() * 2000) + 2000;
console.log(spinMovement + " - " + spinTimeTotal);
rotateWheel();
}
function rotateWheel() {
spinTime += 30;
if (spinTime >= spinTimeTotal) {
stopRotateWheel();
return;
}
var spinAngle = spinAngleStart - easeOut(spinTime, 0, spinAngleStart, spinTimeTotal);
startAngle += (spinAngle * Math.PI / 180);
drawSpinnerWheel();
spinTimeout = setTimeout('rotateWheel()', 30);
}
function stopRotateWheel() {
clearTimeout(spinTimeout);
var degrees = startAngle * 180 / Math.PI + 90;
var arcd = arc * 180 / Math.PI;
var index = Math.floor((360 - degrees % 360) / arcd);
wheel.save();
wheel.font = '30px "Homestead-Inline", Helvetica, Arial';
var text = prize_descriptions[index];
//wheel.fillText(text, 250 - wheel.measureText(text).width / 2, 250 + 10);
wheel.restore();
document.getElementById('timer').innerHTML = "15";
document.getElementById('category').innerHTML = "Your Category is: " + text;
counter = 15;
tt=setInterval(function(){startTime()},1000);
}
function easeOut(t, b, c, d) {
var ts = (t /= d) * t;
var tc = ts * t;
return b + c * (tc + -3 * ts + 3 * t);
}
drawSpinnerWheel();
function startTime() {
if(counter == 0) {
clearInterval(tt);
$("#nospin").attr("id", "spin");
$("#spin").bind('click', function(e) {
e.preventDefault();
spin();
});
} else {
counter--;
}
document.getElementById('timer').innerHTML = counter;
}
$("#spin").bind('click', function(e) {
e.preventDefault();
spin();
});
To see it in action click here
It seems that all your changes should be made in the function stopRotateWheel() and startTime()
When the function is called, a variable called text holds the result ("Geography" or "Science", etc.).
From that, we can perform conditions based on the value of text and determine the total time of countdown, plus the link when the countdown expires.
Something like this:
function stopRotateWheel() {
clearTimeout(spinTimeout);
var degrees = startAngle * 180 / Math.PI + 90;
var arcd = arc * 180 / Math.PI;
var index = Math.floor((360 - degrees % 360) / arcd);
wheel.save();
wheel.font = '30px "Homestead-Inline", Helvetica, Arial';
var text = prize_descriptions[index];
//wheel.fillText(text, 250 - wheel.measureText(text).width / 2, 250 + 10);
wheel.restore();
document.getElementById('timer').innerHTML = "15";
document.getElementById('category').innerHTML = "Your Category is: " + text;
/*do an if else*/
if(text=="Geography")
{
counter = 5;
tt=setInterval(function(){startTime("www.geography.com")},1000);
/*countdown, and when timer expires... go to another link*/
}
else if (text=="Science")
{
//do the same as above :)
}
}
notice the code startTime("www.geography.com")? that's because we also modify function startTime to accept a parameter (in this case, the website) so that when the countdown is finished the webpage goes to that link :)
function startTime(gotoLink) {
if(counter == 0) {
/*go to that link */
window.location.replace(gotoLink)
} else {
counter--;
}
document.getElementById('timer').innerHTML = counter;
}
try it out!
I have created a circle in which I can choose two points along the circumference of of circle.
I want to fill the portion between those two points.
Demo
If you see the demo, I want to fill the angle between two points.
JS:
(function (Raphael) {
Raphael.colorwheel = function (x, y, size, initcolor, element) {
return new ColorWheel(x, y, size, initcolor, element);
};
var pi = Math.PI,
doc = document,
win = window,
ColorWheel = function (x, y, size, initcolor, element) {
size = size || 200;
var w3 = 3 * size / 200,
w1 = size / 200,
fi = 1.6180339887,
segments = 3,//pi * size / 50,
size20 = size / 20,
size2 = size / 2,
padding = 2 * size / 200,
t = this;
var H = 1, S = 1, B = 1, s = size - (size20 * 4);
var r = element ? Raphael(element, size, size) : Raphael(x, y, size, size),
xy = s / 6 + size20 * 2 + padding,
wh = s * 2 / 3 - padding * 2;
w1 < 1 && (w1 = 1);
w3 < 1 && (w3 = 1);
// ring drawing
var a = pi / 2 - pi * 2 / segments * 1.3,
R = size2 - padding,
R2 = size2 - padding - size20 * 2,
path = ["M", size2, padding, "A", R, R, 0, 0, 1, R * Math.cos(a) + R + padding, R - R * Math.sin(a) + padding, "L", R2 * Math.cos(a) + R + padding, R - R2 * Math.sin(a) + padding, "A", R2, R2, 0, 0, 0, size2, padding + size20 * 2, "z"].join();
for (var i = 0; i < segments; i++) {
r.path(path).attr({
stroke: "none",
fill: "#8fd117",
transform: "r" + [(360 / segments) * i, size2, size2]
});
}
r.path(["M", size2, padding, "A", R, R, 0, 1, 1, size2 - 1, padding, "l1,0", "M", size2, padding + size20 * 2, "A", R2, R2, 0, 1, 1, size2 - 1, padding + size20 * 2, "l1,0"]).attr({
"stroke-width": w3,
stroke: "#fff"
});
t.startCursor = r.set();
var h = size20 * 2 + 2;
t.startCursor.push(r.rect(size2 - h / fi / 2, padding - 1, h / fi, h, 3 * size / 200).attr({
stroke: "#00A0C6",
opacity: .5,
"stroke-width": w3
}));
t.startCursor.push(t.startCursor[0].clone().attr({
stroke: "#00A0C6",
opacity: 1,
"stroke-width": w1
}));
t.endCursor = r.set();
var h = size20 * 2 + 2;
t.endCursor.push(r.rect(size2 - h / fi / 2, padding - 1, h / fi, h, 3 * size / 200).attr({
stroke: "#F96E5B",
opacity: .5,
"stroke-width": w3
}));
t.endCursor.push(t.endCursor[0].clone().attr({
stroke: "#F96E5B",
opacity: 1,
"stroke-width": w1
}));
t.ring = r.path(["M", size2, padding, "A", R, R, 0, 1, 1, size2 - 1, padding, "l1,0M", size2, padding + size20 * 2, "A", R2, R2, 0, 1, 1, size2 - 1, padding + size20 * 2, "l1,0"]).attr({
fill: "#000",
opacity: 0,
stroke: "none"
});
t.H = t.S = t.B = 1;
t.raphael = r;
t.size2 = size2;
t.wh = wh;
t.x = x;
t.xy = xy;
t.y = y;
t.endCursor.attr({transform: "r" + [50, t.size2, t.size2]});
// events
t.ring.drag(function (dx, dy, x, y) {
t.docOnMove(dx, dy, x, y);
}, function (x, y) {
// Rotate on click
t.setH(x - t.x - t.size2, y - t.y - t.size2);
}, function () {
});
},
proto = ColorWheel.prototype;
proto.setH = function (x, y) {
var d = Raphael.angle(x, y, 0, 0);
this.H = (d + 90) / 360;
var a = 0;
if(d > 270) {
d = d - 270;
}
else {
d = d + 90;
}
var m = Math.abs(d - this.startCursor[0]._.deg);
var n = Math.abs(d - this.endCursor[0]._.deg);
if(m > 180) {
m = 360 - m ;
}
if(n > 180) {
n = 360 - n;
}
if( m <= n) {
this.startCursor.attr({transform: "r" + [d, this.size2, this.size2]});
}
else {
this.endCursor.attr({transform: "r" + [d, this.size2, this.size2]});
}
m = this.startCursor[0]._.deg ;
n = this.endCursor[0]._.deg;
if(m > 360) {
m = m - 360;
}
if( n > 360 ) {
n = n - 360;
}
var diff = m > n ? m - n : n - m;
this.onchange(m,n,diff);
};
proto.docOnMove = function (dx, dy, x, y) {
this.setH(x - this.x - this.size2, y - this.y - this.size2);
};
})(window.Raphael);
window.onload = function () {
var cp2 = Raphael.colorwheel(60, 20, 200, "#eee");
var X = document.getElementById('x');
var Y = document.getElementById('y');
var angle = document.getElementById('angle');
cp2.onchange = function (x, y, ang) {
X.innerHTML = Math.round(x * 100) / 100;
Y.innerHTML = Math.round(y * 100) / 100;
angle.innerHTML = Math.round(ang * 100) / 100;
}
};
HTML:
<div id="wrapper">X : <span id="x">0</span>
<br>Y: <span id="y">50</span>
<br>Angle: <span id="angle">50</span>
</div>
CSS:
body {
background: #e6e6e6;
}
#wrapper {
position: absolute;
top: 240px;
left: 100px;
}
UPDATE:
With Chris's help,
I have got some success.
See Demo
Bugs :
1. If you start green first, red breaks,
2. If you start red first and makes angle of greater than 180 degree and when green reduces that below 180 degree, it breaks again.
UPDATE 2
DEMO
BUGS:
1. If you start red first and makes angle of greater than 180 degree and when green reduces that below 180 degree, it breaks again.
2. Sometimes arcs in opposite direction.
Cool project. You just need to add an elliptical arc to the color wheel and redraw the path on the onchange event.
I got you half the way here: It works if you move the orange cursor, completely breaks if you move the blue cursor.
To start:
t.x0 = t.startCursor[0].attr("x") + t.startCursor[0].attr("width") / 2;
t.y0 = t.startCursor[0].attr("y") + t.startCursor[0].attr("height") / 2;
t.R1 = (R2 + R) / 2;
t.x1 = t.x0 + t.R1 * Math.sin(50 * Math.PI / 180);
t.y1 = t.y0 + t.R1 - t.R1 * Math.cos(50 * Math.PI / 180);
t.arc = r.path("M" + t.x0 + "," + t.y0 + "A" + t.R1 + "," + t.R1 + " 50 0,1 " + t.x1 + "," + t.y1)
.attr({
stroke: "#009900",
"stroke-width": 10
});
On update:
if (n > 180) {
flag = 1;
}
var diff = m > n ? m - n : n - m;
t.x0 = t.x0 + t.R1 * Math.sin(m * Math.PI / 180);
t.y0 = t.y0 + t.R1 - t.R1 * Math.cos(m * Math.PI / 180);
t.x1 = t.x0 + t.R1 * Math.sin(diff * Math.PI / 180);
t.y1 = t.y0 + t.R1 - t.R1 * Math.cos(diff * Math.PI / 180);
t.arc = t.arc.attr("path", "M" + t.x0 + "," + t.y0 + "A" + t.R1 + "," + t.R1 + " " + diff + " " + flag + ",1 " + t.x1 + "," + t.y1);
jsfiddle
Should be able to take it from here.
UPDATE, May 8:
You can fix your first problem by changing the flag on the diff, not on the second angle:
if (diff > 180) {
flag = 1;
}
The event that's triggering the second problem is the second angle (the red handle) passing the 0-degree mark. The easiest way to catch this is just to add 360 to the angle IF it's less than the first angle:
var m = this.startCursor[0]._.deg ;
var n = this.endCursor[0]._.deg;
var t = this;
var flag = 0;
var sweep = 1;
var path = "";
if (n < m) {
m += 360;
}
var diff = Math.abs(m - n);
if (diff > 180) {
flag = 1;
}
Here's the fiddle
Note: You were catching situations where (n > 360) and (m > 360), but this doesn't appear necessary -- the angles arrive at this point in the code already set below 360, at least in Chrome.
Here's working solution:
Demo
(function (Raphael) {
Raphael.colorwheel = function (x, y, size, initcolor, element) {
return new ColorWheel(x, y, size, initcolor, element);
};
var pi = Math.PI,
doc = document,
win = window,
ColorWheel = function (x, y, size, initcolor, element) {
size = size || 200;
var w3 = 3 * size / 200,
w1 = size / 200,
fi = 1.6180339887,
segments = 3,//pi * size / 50,
size20 = size / 20,
size2 = size / 2,
padding = 2 * size / 200,
t = this;
var H = 1, S = 1, B = 1, s = size - (size20 * 4);
var r = element ? Raphael(element, size, size) : Raphael(x, y, size, size),
xy = s / 6 + size20 * 2 + padding,
wh = s * 2 / 3 - padding * 2;
w1 < 1 && (w1 = 1);
w3 < 1 && (w3 = 1);
// ring drawing
var a = pi / 2 - pi * 2 / segments * 1.3,
R = size2 - padding,
R2 = size2 - padding - size20 * 2,
path = ["M", size2, padding, "A", R, R, 0, 0, 1, R * Math.cos(a) + R + padding, R - R * Math.sin(a) + padding, "L", R2 * Math.cos(a) + R + padding, R - R2 * Math.sin(a) + padding, "A", R2, R2, 0, 0, 0, size2, padding + size20 * 2, "z"].join();
for (var i = 0; i < segments; i++) {
r.path(path).attr({
stroke: "none",
fill: "#8fd117",
transform: "r" + [(360 / segments) * i, size2, size2]
});
}
r.path(["M", size2, padding, "A", R, R, 0, 1, 1, size2 - 1, padding, "l1,0", "M", size2, padding + size20 * 2, "A", R2, R2, 0, 1, 1, size2 - 1, padding + size20 * 2, "l1,0"]).attr({
"stroke-width": w3,
stroke: "#fff"
});
t.startCursor = r.set();
var h = size20 * 2 + 2;
t.startCursor.push(r.rect(size2 - h / fi / 2, padding - 1, h / fi, h, 3 * size / 200).attr({
stroke: "#00A0C6",
opacity: 1,
"stroke-width": w3
}));
t.startCursor.push(t.startCursor[0].clone().attr({
stroke: "#00A0C6",
fill : "#8fd117",
opacity: 1,
"stroke-width": w1
}));
t.endCursor = r.set();
var h = size20 * 2 + 2;
t.endCursor.push(r.rect(size2 - h / fi / 2, padding - 1, h / fi, h, 3 * size / 200).attr({
stroke: "#F96E5B",
opacity: 1,
"stroke-width": w3,
}));
t.endCursor.push(t.endCursor[0].clone().attr({
stroke: "#F96E5B",
fill : "#8fd117",
opacity: 1,
"stroke-width": w1
}));
t.ring = r.path(["M", size2, padding, "A", R, R, 0, 1, 1, size2 - 1, padding, "l1,0M", size2, padding + size20 * 2, "A", R2, R2, 0, 1, 1, size2 - 1, padding + size20 * 2, "l1,0"]).attr({
fill: "#000",
opacity: 0,
stroke: "none"
});
t.H = t.S = t.B = 1;
t.raphael = r;
t.size2 = size2;
t.wh = wh;
t.x = x;
t.xy = xy;
t.y = y;
t.endCursor.attr({transform: "r" + [50, t.size2, t.size2]});
t.x0 = t.startCursor[0].attr("x") + t.startCursor[0].attr("width") / 2;
t.y0 = t.startCursor[0].attr("y") + t.startCursor[0].attr("height") / 2;
t.initX0 = t.x0;
t.initY0 = t.y0;
t.R1 = (R2 + R) / 2;
t.x1 = t.x0 + t.R1 * Math.sin(50 * Math.PI / 180);
t.y1 = t.y0 + t.R1 - t.R1 * Math.cos(50 * Math.PI / 180);
t.initX1 = t.x1;
t.initY1 = t.y1;
var path = "M" + t.x0 + "," + t.y0 + "A" + t.R1 + "," + t.R1 + " 50 0,1 " + t.x1 + "," + t.y1;
t.arc = r.path(path)
.attr({
stroke: "#009900",
"stroke-width": 10
});
t.startCursor.drag(function (dx, dy, x, y) {
t.docOnMove(dx, dy, x, y,'startCursor');
}, function (x, y) {
t.setH(x - t.x - t.size2, y - t.y - t.size2,'startCursor');
}, function () {
});
t.endCursor.drag(function (dx, dy, x, y) {
t.docOnMove(dx, dy, x, y,'endCursor');
}, function (x, y) {
t.setH(x - t.x - t.size2, y - t.y - t.size2,'endCursor');
}, function () {
});
t.startCursor.toFront();
t.endCursor.toFront();
},
proto = ColorWheel.prototype;
proto.setH = function (x, y,cursor) {
var d = Raphael.angle(x, y, 0, 0);
if(d > 270) {
d = d - 270;
}
else {
d = d + 90;
}
if((cursor === 'startCursor' && d > this.endCursor[0]._.deg) || (cursor === 'endCursor' && d <= this.startCursor[0]._.deg)) {
return;
}
if(cursor === 'startCursor') {
this.startCursor.attr({transform: "r" + [d, this.size2, this.size2]});
}
else {
this.endCursor.attr({transform: "r" + [d, this.size2, this.size2]});
}
var m = this.startCursor[0]._.deg ;
var n = this.endCursor[0]._.deg;
var t = this;
var flag = 0;
if(m > 360) {
m = m - 360;
flag = 1;
}
if( n > 360 ) {
n = n - 360;
}
var diff = Math.abs(m - n);
if (diff > 180) {
flag = 1;
}
var path = "";
var sweep = 1;
if(cursor === 'endCursor') {
t.x1 = t.initX0 + t.R1 * Math.sin(n * Math.PI / 180);
t.y1 = t.initY0 + t.R1 - t.R1 * Math.cos(n * Math.PI / 180);
}
else {
t.x0 = t.initX0 + t.R1 * Math.sin(m * Math.PI / 180);
t.y0 = t.initY0 + t.R1 - t.R1 * Math.cos(m * Math.PI / 180);
}
console.log(m,t.x0,t.y0,t.x1,t.y1);
path = "M" + t.x0 + "," + t.y0 + "A" + t.R1 + "," + t.R1 + " " + diff + " " + flag + "," + sweep + " " + t.x1 + "," + t.y1;
t.arc = t.arc.attr("path", path );
this.onchange(m,n,diff);
};
proto.docOnMove = function (dx, dy, x, y,cursor) {
this.setH(x - this.x - this.size2, y - this.y - this.size2,cursor);
};
})(window.Raphael);
window.onload = function () {
var cp2 = Raphael.colorwheel(60, 20, 200, "#eee");
var X = document.getElementById('x');
var Y = document.getElementById('y');
var angle = document.getElementById('angle');
cp2.onchange = function (x, y, ang) {
X.innerHTML = Math.round(x * 100) / 100;
Y.innerHTML = Math.round(y * 100) / 100;
angle.innerHTML = Math.round(ang * 100) / 100;
}
};
I have some html5 and javascript code to create a spinning roulette wheel. It is split up into 14 outcomes. My question is, how can I get some unique HTML code to display per each outcome of the wheel. For example, if the wheel lands on Business, some text will appear below the wheel that has information on Business.
Here is my HTML code and below it is a link to a working example:
<!--[if IE]><script type="text/javascript" src="/sites/default/files/1010/source/excanvas.js"></script><![endif]-->
<input type="button" value="spin" onclick="spin();" style="float: left;" />
<canvas id="wheelcanvas" width="800" height="750"></canvas>
<script type="application/javascript">
var colors = ["#B8D430", "#3AB745", "#029990", "#3501CB",
"#2E2C75", "#673A7E", "#CC0071", "#F80120",
"#F35B20", "#FB9A00", "#FFCC00", "#FEF200", "#B2DF00", "#5C8300"];
var classes = ["Business", "Office Education", "Continuing Care Assistant", "Practical Nursing",
"Primary Care Paramedic", "Early Childhood Education", "Cooking", "Electrician",
"Heavy Equipment Operator", "Industrial Mechanic - Millwright", "Plumbing & Pipefitting", "Truck Driver Training", "Welding", "Power Engineering"];
var startAngle = 0;
var arc = Math.PI / 7;
var spinTimeout = null;
var spinArcStart = 10;
var spinTime = 0;
var spinTimeTotal = 0;
var ctx;
function draw() {
drawRouletteWheel();
}
function drawRouletteWheel() {
var canvas = document.getElementById("wheelcanvas");
if (canvas.getContext) {
var outsideRadius = 300;
var textRadius = 260;
var insideRadius = 100;
ctx = canvas.getContext("2d");
ctx.clearRect(5,0,1000,1000);
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.font = 'bold 10px sans-serif';
for(var i = 0; i < 14; i++) {
var angle = startAngle + i * arc;
ctx.fillStyle = colors[i];
ctx.beginPath();
ctx.arc(400, 400, outsideRadius, angle, angle + arc, false);
ctx.arc(400, 400, insideRadius, angle + arc, angle, true);
ctx.stroke();
ctx.fill();
ctx.save();
ctx.shadowOffsetX = -1;
ctx.shadowOffsetY = -1;
ctx.shadowBlur = 0;
ctx.shadowColor = "rgb(220,220,220)";
ctx.fillStyle = "black";
ctx.translate(400 + Math.cos(angle + arc / 2) * textRadius, 400 + Math.sin(angle + arc / 2) * textRadius);
ctx.rotate(angle + arc / 2 + Math.PI / 2);
var text = classes[i];
ctx.fillText(text, -ctx.measureText(text).width / 2, 0);
ctx.restore();
}
//Arrow
ctx.fillStyle = "black";
ctx.beginPath();
ctx.moveTo(400 - 4, 400 - (outsideRadius + 5));
ctx.lineTo(400 + 4, 400 - (outsideRadius + 5));
ctx.lineTo(400 + 4, 400 - (outsideRadius - 5));
ctx.lineTo(400 + 9, 400 - (outsideRadius - 5));
ctx.lineTo(400 + 0, 400 - (outsideRadius - 13));
ctx.lineTo(400 - 9, 400 - (outsideRadius - 5));
ctx.lineTo(400 - 4, 400 - (outsideRadius - 5));
ctx.lineTo(400 - 4, 400 - (outsideRadius + 5));
ctx.fill();
}
}
function spin() {
spinAngleStart = Math.random() * 10 + 10;
spinTime = 0;
spinTimeTotal = Math.random() * 3 + 4 * 1000;
rotateWheel();
}
function rotateWheel() {
spinTime += 30;
if(spinTime >= spinTimeTotal) {
stopRotateWheel();
return;
}
var spinAngle = spinAngleStart - easeOut(spinTime, 0, spinAngleStart, spinTimeTotal);
startAngle += (spinAngle * Math.PI / 180);
drawRouletteWheel();
spinTimeout = setTimeout('rotateWheel()', 30);
}
function stopRotateWheel() {
clearTimeout(spinTimeout);
var degrees = startAngle * 180 / Math.PI + 90;
var arcd = arc * 180 / Math.PI;
var index = Math.floor((360 - degrees % 360) / arcd);
ctx.save();
ctx.font = 'bold 30px sans-serif';
var text = classes[index]
ctx.fillText(text, 400 - ctx.measureText(text).width / 2, 400 + 10);
ctx.restore();
document.getElementById('wheelResult').innerHTML = 'Test' + text;
}
function easeOut(t, b, c, d) {
var ts = (t/=d)*t;
var tc = ts*t;
return b+c*(tc + -3*ts + 3*t);
}
draw();
</script>
<p id="wheelResult"></p>
http://www.ctrc.sk.ca/wheel.html
There are a couple of ways to do it but this is the way I would do it.
You could create a div tag with the css style of display:none and then set it with the info desired and hide and show it as needed.
Example:
<script>
var htmlData = ['<h1>Business</h1><br><span>What is Business?</span><br>...', ...];
....
function spin()
{
//Hide description box.
document.getElementById('idDescriptionBox').style.display = 'none';
spinAngleStart = Math.random() * 10 + 10;
....
}
....
function stopRotateWheel()
{
....
//Set description and display it.
var descriptionBox = document.getElementById('idDescriptionBox');
descriptionBox.innerHTML = htmlData[index];
descriptionBox.style.display = 'block';
}
....
</script>
<div id="idDescriptionBox" style="display:none;">
<!--Description info in here-->
....
</div>