I am drawing an arc which increases gradually and turns in to a circle.On completion of animation(arc turning in to a circle) i want to draw another circle with increased radius with the previous circle persisting and the second animation continuing.
Arc to circle fiddle
After the circle is drawn,it gets washed out which is something that I dont want and continue the second animation.
Some unnecessary animation appears after the completion.
What should I do?
MyCode:
setInterval(function(){
context.save();
context.clearRect(0,0,500,400);
context.beginPath();
increase_end_angle=increase_end_angle+11/500;
dynamic_end_angle=end_angle+increase_end_angle;
context.arc(x,y,radius,start_angle,dynamic_end_angle,false);
context.lineWidth=6;
context.lineCap = "round";
context.stroke();
context.restore();
if(dynamic_end_angle>3.5*Math.PI){ //condition for if circle completion
draw(radius+10);//draw from same origin and increasd radius
}
},66);
window.onload=draw(30);
UPDATE:when should i clear the interval to save some cpu cycles and why does the animation slows down on third circle ??
First of all, about the flicker: you are using setInterval and not clearing it for the next draw(). So there’s that.
But I’d use a completely different approach; just check the time elapsed since the start, and draw an appropriate number of circles using a loop.
var start = new Date().getTime();
var timePerCircle = 2;
var x = 190, y = 140;
function draw() {
requestAnimationFrame(draw);
g.clearRect(0, 0, canvas.width, canvas.height);
var t = (new Date().getTime() - start) / 1000;
var circles = t / timePerCircle;
var r = 30;
do {
g.beginPath();
g.arc(x, y, r, 0, Math.PI * 2 * Math.min(circles, 1));
g.stroke();
r += 10;
circles--;
} while(circles > 0);
}
draw();
This snippet from your code has some flaw.
if(dynamic_end_angle>3.5*Math.PI){ //condition for if circle completion
draw(radius+10);//draw from same origin and increased radius
}
The recursive call to draw() will continue to run after the first circle was drawn completely. This is why the performance will be slow down immediately. You need to somehow block it.
I did a simple fix, you can polish it if you like. FIDDLE DEMO
My fix is to remove context.clearRect(0, 0, 500, 400); and change the new circle drawing logic to:
if (dynamic_end_angle > 3.5 * Math.PI) { //condition for if circle completion
increase_end_angle = 0; // this will prevent the draw() from triggering multiple times.
draw(radius + 10); //draw from same origin.
}
In this stackoverflow thread, it mentions how to make it more smooth. You'd better use some drawing framework since the optimization needs a lot of work.
When should I clear the interval to save some cpu cycles?
Better yet not use an interval at all for a couple of reasons:
Intervals are unable to sync to monitor's VBLANK gap so you will get jerks from time to time.
If you use setInterval you risk stacking calls (not high risk in this case though).
A much better approach is as you probably already know to use requestAnimationFrame. It's less CPU hungry, is able to sync to monitor and uses less resources in general even less if current tab/window is not active.
Why does the animation slows down on third circle ??
Your drawing calls are accumulating which slows everything down (setInterval is not cleared).
Here is a different approach to this. It's a simplified way and uses differential painting.
ONLINE DEMO
The main draw function here takes two arguments, circle index and current angle for that circle. The circles radius are stored in an array:
...,
sa = 0, // start angle
ea = 359, // end angle
angle = sa, // current angle
oldAngle = sa, // old angle
steps = 2, // number of degrees per step
current = 0, // current circle index
circles = [70, 80, 90], // the circle radius
numOfCircles = circles.length, ...
The function stores the old angle and only draws a new segment between old angle and new angle with 0.5 added to compensate for glitches due to anti-alias, rounding errors etc.
function drawCircle(circle, angle) {
angle *= deg2rad; // here: convert to radians
/// draw arc from old angle to new angle
ctx.beginPath();
ctx.arc(0, 0, circles[circle], oldAngle, angle + 0.5);
ctx.stroke();
/// store angle as old angle for next round
oldAngle = angle;
}
The loop increases the angle, if above or equal to end angle it will reset the angle and increase the current circle counter. When current counter has reach last circle the loop ends:
function loop() {
angle += steps;
/// check angle and reset, move to next circle
if (angle >= ea - steps) {
current++;
angle = sa;
oldAngle = angle;
}
drawCircle(current, angle);
if (current < numOfCircles)
requestAnimationFrame(loop);
}
Related
i am making a javascript shooter game.i want the the player to rotate towards the mouse.it is working, but the rotation was not correct.
I tried this with an image, and it works, but with the sprite itself(player1), is not.
i have asked this once before but received no answer
I am a beginner in javascript, so help would be appreciated.
I am using the p5.js libraries
Here is my code snippet:
//variables
var player1;
var gun1;
var gun2;
function preload(){
img = loadImage('rect1.png');
}
function setup(){
//creating sprites
player1 = createSprite(200,200,30,30)
gun = createSprite(player1.x,player1.y-20,5,30)
gun.shapeColor = "black"
player1.addImage("player",img)
player1.scale = 0.2
}
function draw(){
canvas = createCanvas(displayWidth-20, displayHeight-120);
background("#32CD32");
push()
gun.x = player1.x;
gun.y = player1.y-15;
// functions to move
//up
if(keyDown("up")){
player1.y = player1.y - 5;
}
//down
if(keyDown("down")){
player1.y = player1.y + 5;
}
//right
if(keyDown("right")){
player1.x = player1.x + 5;
}
//left
if(keyDown("left")){
player1.x = player1.x - 5;
}
angleMode(DEGREES)
imageMode(CENTER)
let a = atan2(mouseY - height / 2, mouseX - width / 2);
translate(width/2, height/2);
//rotate(a)
player1.rotation = a
//image(img,0,0,40,40)
pop()
drawSprites();
}
I think I'm using a dated version of p5.play, so there's not much in your code that works for me, but here's what I think is going on based on what you're saying.
If you want to understand what the deal is with atan2(), you first have to understand atan(). Basically, you have the ordinary trig functions sin, cos, and tan. Then you have the inverse trig functions arcsin, arccos, and arctan (abbreviated asin, acos, and atan). The arctan function is useful because you can input a slope and it will give you the angle of that slope. There's a catch, though; atan will only give values between -pi/2 and pi/2. This covers all non-vertical lines, but what if you wanted to use it for a vector or something that has direction? atan2() solves that problem. Instead of taking one input (a ratio: rise/run), it takes two inputs, a rise and a run. This prevents dividing by zero (for vertical lines) and signs of rise and run cancelling. The first input is the rise, and the second is the run. The output is the angle between the vector with those coordinates and the x-axis. So atan2() will give you some angle between -pi and pi.
Now let's look at what you have put into the atan2() function:
atan2(mouseY - height / 2, mouseX - width / 2);
So the vector you're considering is the vector from the middle of the canvas to the mouse. If this is what you want, great. If it's not, maybe consider
atan2(mouseY - player1.y, mouseX - player1.y);
which yields the "heading" (not really the heading) of the vector from the player's position to the mouse.
There are a couple of other potential problems (I can't figure out which one it is because p5.play isn't behaving, or I'm doing something else wrong):
radians/degrees: sometimes this stuff goes wrong. Try printing a and seeing if it's what you're looking for. If it's in degrees, consider saying player1.rotation = radians(a) instead. I know that p5.Vector.fromAngle() doesn't care about angleMode, maybe sprite.rotation doesn't either?
I don't know how drawSprites works, but you might consider putting it inside of the push()/pop() section. When drawing other shapes, this is how you get a rotation about the point (x, y):
let x = 100;
let y = 200;
let a = atan2(mouseY - y, mouseX - x);
push();
translate(x, y);
rotate(a);
square(-10, -10, 20);
pop();
The square is centered at (x,y), and is rotated about (x,y) toward the cursor. It's necessary that you do it in this order: push, translate, rotate, shape, pop. If you mix up that order, it doesn't do it right. But what you have is push, translate, pop, shape. I don't know how sprite.rotate works, so maybe it's supposed to do what you want. But here is another way to do a rotation. (If you're going to do it this way, I think you'd have to draw player1 "at (0,0)" after the translation and rotation, before pop)
I hope this helped!
I have been looking around for this function and thus far I just can't find any I can make any sense of. I already have a rotating function to make it equal to the position but slowly is proving to be a bit harder with 0-360 and all.
I am using a html canvas 2d context to render the objects on a Cartesian coordinate system .
I would like object1 to face at positionX and positionY at a turn rate (R) , fairly straightforward.
there is no need for me to supply any code since your likely going to make your own anyways. But I will anyways here you go:
let faceAt = function (thisObject,positionX,positionY) {
let desiredLocationX = positionX - thisObject.transform.x;
let desiredLocationY = positionY -thisObject.transform.y;
thisObject.transform.rotation = Math.degrees(Math.atan2(desiredLocationY, desiredLocationX));
};
The (Math.degrees) function converts radians to degrees.
This thread says it all : https://www.google.ca/amp/s/jibransyed.wordpress.com/2013/09/05/game-maker-gradually-rotating-an-object-towards-a-target/amp/
This question is quite unclear. But, I'm assuming you essentially just want to rotate an element around an arbitrary point on a HTML5 canvas.
On a canvas, you can only draw one element at a time. You can't really manipulate singular elements - for example, you can't rotate an element by itself. Instead, you'd need to rotate the entire canvas. This will always rotate around the centre of the canvas, but if you move the canvas origin, then you will draw on a different part of the canvas; thus allowing you to rotate around a point.
Check out the following example. You can click anywhere on the canvas to make the square rotate around that point. Hopefully this is what you are after:
let cv = document.getElementById("cv");
let ctx = cv.getContext("2d");
let angle = 0;
//Variables you can change:
let speed = 1; //Degrees to rotate per frame
let pointX = 250; //The x-coord to rotate around
let pointY = 250; //The y-coord to rotate around
ctx.fillStyle = "#000";
setInterval(()=>{ //This code runs every 40ms; so that the animation looks smooth
angle = (angle + speed) % 360; //Increment the angle. Bigger changes here mean that the element will rotate faster. If we go over 360deg, reset back to 0.
ctx.clearRect(0, 0, 400, 400); //Clear away the previous frame.
//Draw the point we are rotating around
ctx.beginPath();
ctx.arc(pointX,pointY,5,0,2*Math.PI);
ctx.fill();
ctx.closePath();
ctx.save(); //Save the state before we transform and rotate the canvas; so we can go back to the unrotated canvas for the next frame
ctx.translate(pointX, pointY); //Move the origin (0, 0) point of the canvas to the point to rotate around. The canvas always rotates around the origin; so this will allow us to rotate around that point
ctx.rotate(angle*Math.PI/180); //Rotate the canvas by the current angle. You can use your Math.degrees function to convert between rads / degs here.
ctx.fillStyle = "#f00"; //Draw in red. This is also restored when ctx.restore() is called; hence the point will always be black; and the square will always be red.
ctx.fillRect(0, 0, 50, 50); //Draw the item we want rotated. You can draw anything here; I just draw a square.
ctx.restore(); //Restore the canvas state
}, 40);
//Boring event handler stuff
//Move the point to where the user clicked
//Not too robust; relys on the body padding not changing
//Really just for the demo
cv.addEventListener("click", (event)=>{
pointX = event.clientX - 10;
pointY = event.clientY - 10;
});
#cv {
border:solid 1px #000; /*Just so we can see the bounds of the canvas*/
padding:0;
margin:0;
}
body {
padding:10px;
margin:0;
}
<canvas id="cv" width="400" height="400"></canvas><br>
Click on the canvas above to make the rectangle rotate around the point that was clicked.
I am trying to move an object smoothly from point A to point B using HTML canvas and regular javascript.
Point A is a set of coordinates
Point B is in the case the cursor location.
I made a jsfiddle of what I have so far: https://jsfiddle.net/as9fhmw8/
while(projectile.mouseX > projectile.x && projectile.mouseY < projectile.y)
{
ctx.save();
ctx.beginPath();
ctx.translate(projectile.x, projectile.y);
ctx.arc(0,0,5,0,2*Math.PI);
ctx.fillStyle = "blue";
ctx.fill();
ctx.stroke();
ctx.restore();
if(projectile.mouseX > projectile.x && projectile.mouseY < projectile.y)
{
var stepsize = (projectile.mouseX - projectile.x) / (projectile.y - projectile.mouseY);
projectile.x += (stepsize + 1);
}
if(projectile.mouseY < projectile.y)
{
var stepsize = (projectile.y - projectile.mouseY) / (projectile.mouseX - projectile.x);
projectile.y -= (stepsize + 1);
}
}
Essentially what I can't figure out to do is to make the while loop slower (so that it appears animated in stead of just going through every iteration and showing the result).
I also can't figure out how to prevent the Arc from duplicating so that it creates a line that is permanent, instead of appearing to move from point a to point b.
Smooth animation here is really about determining how far to move your object for each iteration of the loop.
There is a little math involved here, but it's not too bad.
Velocity
Velocity in your case is just the speed at which your particles travel in any given direction over a period of time. If you want your particle to travel 200px over the course of 4 seconds, then the velocity would be 50px / second.
With this information, you can easily determine how many pixels to move (animate) a particle given some arbitrary length of time.
pixels = pixelsPerSecond * seconds
This is great to know how many pixels to move, but doesn't translate into individual X and Y coordinates. That's where vectors come in.
Vectors
A vector in mathematics is a measurement of both direction and magnitude. For our purposes, it's like combining our velocity with an angle (47°).
One of the great properties of vectors is it can be broken down into it's individual X and Y components (for 2-Dimensional space).
So if we wanted to move our particle at 50px / second at a 47° angle, we could calculate a vector for that like so:
function Vector(magnitude, angle){
var angleRadians = (angle * Math.PI) / 180;
this.magnitudeX = magnitude * Math.cos(angleRadians);
this.magnitudeY = magnitude * Math.sin(angleRadians);
}
var moveVector = new Vector(50, 47);
The wonderful thing about this is that these values can simply be added to any set of X and Y coordinates to move them based on your velocity calculation.
Mouse Move Vector
Modeling your objects in this way has the added benefit of making things nice and mathematically consistent. The distance between your particle and the mouse is just another vector.
We can back calculate both the distance and angle using a little bit more math. Remember that guy Pythagoras? Turns out he was pretty smart.
function distanceAndAngleBetweenTwoPoints(x1, y1, x2, y2){
var x = x2 - x1,
y = y2 - y1;
return {
// x^2 + y^2 = r^2
distance: Math.sqrt(x * x + y * y),
// convert from radians to degrees
angle: Math.atan2(y, x) * 180 / Math.PI
}
}
var mouseCoords = getMouseCoords();
var data = distanceAndAngleBetweenTwoPoints(particle.x, particle.y, mouse.x, mouse.y);
//Spread movement out over three seconds
var velocity = data.distance / 3;
var toMouseVector = new Vector(velocity, data.angle);
Smoothly Animating
Animating your stuff around the screen in a way that isn't jerky means doing the following:
Run your animation loop as fast as possible
Determine how much time has passed since last time
Move each item based on elapsed time.
Re-paint the screen
For the animation loop, I would use the requestAnimationFrame API instead of setInterval as it will have better overall performance.
Clearing The Screen
Also when you re-paint the screen, just draw a big rectangle over the entire thing in whatever background color you want before re-drawing your items.
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
Putting It All Together
Here is a Fiddle demonstrating all these techniques: https://jsfiddle.net/jwcarroll/2r69j1ok/3/
Currently I have this fiddle from Blindman67 which draws Golden spiral figure 1(see image below).
function renderSpiral(pointA, pointB, turns){
var dx, dy, rad, i, ang, cx, cy, dist, a, c, angleStep, numberTurns, nTFPB, scale, styles;
// clear the canvas
ctx.clearRect(0, 0, ctx.canvas.width,ctx.canvas.height)
// spiral stuff
a = 1; // the larger this number the larger the spiral
c = 1.358456; // constant See https://en.wikipedia.org/wiki/Golden_spiral
angleStep = Math.PI/20; // set the angular resultion for drawing
numberTurns = 6; // total half turns drawn
nTFPB = 2; // numberOfTurnsForPointB is the number of turns to point
// B should be integer and describes the number off
// turns made befor reaching point B
// get the ang from pointA to B
ang = Math.atan2(pointB.y-pointA.y,pointB.x-pointA.x);
// get the distance from A to B
dist = Math.sqrt(Math.pow(pointB.y-pointA.y,2)+Math.pow(pointB.x-pointA.x,2));
if(dist === 0){
return; // this makes no sense so exit as nothing to draw
}
// get the spiral radius at point B
rad = Math.pow(c,ang + nTFPB * 2 * Math.PI); // spiral radius at point2
// now just need to get the correct scale so the spiral fist to the
// constraints requiered.
scale = dist / rad;
// ajust the number of turns so that the spiral fills the canvas
while(Math.pow(c,Math.PI*numberTurns)*scale < ctx.canvas.width){
numberTurns += 2;
}
// set the scale, and origin to centre
ctx.setTransform(scale, 0, 0, scale, pointA.x, pointA.y)
// make it look nice create some line styles
// first just draw the line A-B
ctx.strokeStyle = "black";
ctx.lineWidth = 2 * ( 1 / scale); // because it is scaled invert the scale
// can calculate the width requiered
// ready to draw
ctx.beginPath();
ctx.moveTo(0, 0) // start at center
ctx.lineTo((pointB.x-pointA.x)*(1/scale),(pointB.y-pointA.y)*(1/scale) ); // add line
ctx.stroke(); // draw it all
// Now draw the sporal. draw it for each style
styles.forEach( function(style) {
ctx.strokeStyle = style.colour;
ctx.lineWidth = style.width * ( 1 / scale); // because it is scaled invert the scale
// can calculate the width requiered
// ready to draw
ctx.beginPath();
for( i = 0; i <= Math.PI *numberTurns; i+= angleStep){
dx = Math.cos(i); // get the vector for angle i
dy = Math.sin(i);
var rad = Math.pow(c, i); // calculate the radius
if(i === 0) {
ctx.moveTo(0, 0) // start at center
}else{
ctx.lineTo(dx * rad, dy * rad ); // add line
}
}
ctx.stroke(); // draw it all
});
ctx.setTransform(1,0,0,1,0,0); // reset tranfrom to default;
}
What I want to obtain is figure 2 (see image below).
Q1. How can I change mine spiral so line AB will fit between first and second screw while A is the start of spiral?
You can also refer to my earlier question for better understanding of my problem.
To achieve the properties you need you need to adjust your spiral like following:
choose the right angular position of the line AB
I choose 1.5*M_PI [rad] for A and 3.5*M_PI [rad] for B (on unrotated spiral)
rotate your spiral by angle of your AB line
that is easy just add the angle to the final polar -> cartesian coordinates conversion and that will rotate entire spiral so computed angular positions of A,B on spiral will match the real points AB direction
rescale your spiral to match the AB size
So compute the radiuses for angular points A,B positons on spiral and then compute the scale=|AB|-(r(b)-r(a)). Now just multiply this to compute radius of each rendered point ...
I played a bit with the golden ratio and spiral a bit and here is the result
Yellow spiral is approximation by quarter circle arcs
Aqua is the Golden spiral
As you can see they do not match so much (this is with ratio*0.75 to make them more similar but it should be just ratio) Either I have a bug somewhere, or the origin of spiral is shifted (but does not look like it) or I have wrong ratio constant ratio = 0.3063489 or the Golden rectangles are introducing higher floating round errors then I taught or I am missing something stupid.
Here the C++ source code so you can extract what you need:
//---------------------------------------------------------------------------
#include <Math.h>
//---------------------------------------------------------------------------
bool _redraw=false; // just signal to repaint window after spiral change
double Ax,Ay,Bx,By; // mouse eddited points
double gr=0.75; // golden spiral ratio scale should be 1 !!!
void GoldenSpiral_draw(TCanvas *can) // GDI draw
{
double a0,a,b,l,x,y,r=5,ratio;
// draw AB line
can->Pen->Color=clWhite;
can->MoveTo(Ax,Ay);
can->LineTo(Bx,By);
// draw A,B points
can->Pen->Color=clBlue;
can->Brush->Color=clAqua;
can->Ellipse(Ax-r,Ay-r,Ax+r,Ay+r);
can->Ellipse(Bx-r,By-r,Bx+r,By+r);
// draw golden ratio rectangles
can->Pen->Color=clDkGray;
can->Brush->Style=bsClear;
ratio=1.6180339887;
a=5.0; b=a/ratio; x=Ax; y=Ay;
y-=0.5*b; x-=0.5*b; // bias to match real golden spiral
can->Rectangle(x,y,x+a,y+b); y-=a;
for (int i=0;i<5;i++)
{
can->Rectangle(x,y,x+a,y+a); b=a; a*=ratio; x-=a;
can->Rectangle(x,y,x+a,y+a); y+=a; b=a; a*=ratio;
can->Rectangle(x,y,x+a,y+a); x+=a; y-=b; b=a; a*=ratio;
can->Rectangle(x,y,x+a,y+a); x-=b; b=a; a*=ratio; y-=a;
}
// draw circle arc approximation of golden spiral
ratio=1.6180339887;
a=5.0; b=a/ratio; x=Ax; y=Ay; r=10000; y-=a;
y-=0.5*b; x-=0.5*b; // bias to match real golden spiral
can->Pen->Color=clYellow;
for (int i=0;i<5;i++)
{
can->Arc(x-a,y,x+a,y+a+a,+r, 0, 0,-r); b=a; a*=ratio; x-=a;
can->Arc(x,y,x+a+a,y+a+a, 0,-r,-r, 0); y+=a; b=a; a*=ratio;
can->Arc(x,y-a,x+a+a,y+a,-r, 0, 0,+r); x+=a; y-=b; b=a; a*=ratio;
can->Arc(x-a,y-a,x+a,y+a, 0,+r,+r, 0); x-=b; b=a; a*=ratio; y-=a;
}
can->Brush->Style=bsSolid;
// compute golden spiral parameters
ratio=0.3063489*gr;
x=Bx-Ax;
y=By-Ay;
l=sqrt(x*x+y*y); // l=|AB|
if (l<1.0) return; // prevent domain errors
a0=atan2(-y,x); // a=atan2(AB)
a0+=0.5*M_PI; // offset so direction of AB matches the normal
a=1.5*M_PI; r=a*exp(ratio*a); b=r;
a+=2.0*M_PI; r=a*exp(ratio*a); b=r-b;
b=l/r; // b=zoom of spiral to match AB screw distance
// draw golden spiral
can->Pen->Color=clAqua;
can->MoveTo(Ax,Ay);
for (a=0.0;a<100.0*M_PI;a+=0.001)
{
r=a*b*exp(ratio*a); if (r>512.0) break;
x=Ax+r*cos(a0+a);
y=Ay-r*sin(a0+a);
can->LineTo(x,y);
}
}
//---------------------------------------------------------------------------
You can ignore the golden ratio rectangles and circular arcs ...
change the drawings based on can-> to your gfx API. It is just GDI Canvas
Hard to say if your spiral is correct ... you can check with the golden ratio rectangles (as I did). If you got correct spiral then just apply the bullets #1,#2,#3 to it and you should be fine.
Here's a fiddle which I believe gives you the output your looking for.
https://jsfiddle.net/8a7fdg3d/4/
The main problem was starting the spiral from 0 results in the initial straight line.
Starting the spiral from 1 removes this part of the graph and then you just had to adjust the starting point of your black |AB| line.
This was done by adjusting
for( i = 0; i <= Math.PI *numberTurns; i+= angleStep)
to
for( i = 1; i <= Math.PI *numberTurns; i+= angleStep)
to change the starting point of the spiral, then changing
// ready to draw
ctx.beginPath();
ctx.moveTo(0, 0) // start at center
to
// ready to draw
ctx.beginPath();
dx = Math.cos(1); // get the vector for angle i
dy = Math.sin(1);
var rad = Math.pow(c, 1); // calculate the radius
ctx.moveTo(dx * rad, dy * rad ) // start at center
to make your |AB| line match up.
I am developing a casino based game using html5. The animation is working properly but this is not quite smooth i.e. once the wheel stops rotation I move ball as a final repositioning to smoothen the transition but it is not upto the expectation. Complete Code here
BallReposition Function - runs after I wheel stops movement for the final repositioning of the ball to give some reality to the animation.
function ballReposition(){
curX = findNearestOnCircle(curX);
if(curX > deadXRight){
sign = "-";
}else if(curX < deadXLeft){
sign = "+";
}
if(sign == "+"){
curX = parseInt(curX) + ballRepositionIncVal;
curY = Math.floor(Math.abs(getYOnCircle(curX, 130, 1)) + 0.5);
}else{
curX = parseInt(curX) - ballRepositionIncVal;
curY = Math.floor(Math.abs(getYOnCircle(curX, 130, 0)) + 0.5);
}
var xy = normalizeXY(curX, curY);
curX = parseInt(xy.split("-")[0]);
curY = parseInt(xy.split("-")[1]);
surface = document.getElementById("myCanvas");
var surfaceContext = surface.getContext("2d");
//removing older ball image.
surfaceContext.save();
// Translate to the center point of our image
surfaceContext.translate(happy.width * 0.5, happy.height * 0.5);
// Perform the rotation
surfaceContext.rotate(DegToRad(angle));
// Translate back to the top left of our image
surfaceContext.translate(-happy.width * 0.5, -happy.height * 0.5);
surface.getContext("2d").drawImage(happy, 0, 0);
surface.getContext("2d").drawImage(ball, curX, curY);
console.log(curX + curY);
surfaceContext.restore();
ballRepositionIncVal-=5;
if(ballRepositionIncVal <= 0){
clearInterval(myIntervalVar);
}
}
Other function details -
drawCanvas - loads the images and once the images are loaded it will start calling loop function which will rotate the wheel and move the ball in anticlockwise direction.
normalizeXY - used to put the ball at some discrete positions i.e. proper positions below numbers of wheel.
EDIT - Fiddle Configuration updated here
To create a realistic spinning wheel you can use a logarithmic-ish approach to reduce the speed of the wheel.
This means the angle is decremented by small per-centage for each frame. As it is per-centage you will get a smooth ending spin (you will also notice you get the infamous wagon wheel aliasing effect).
This online demo shows the loop isolated (implement as you please):
var angle = 2; /// start angle in radians
ctx.translate(w, h); /// prepare canvas for rotation (w and h = 50%)
ctx.globalAlpha = 0.67; /// optional bonus: motion blur(-ish)
loop(); /// start loop
function loop() {
ctx.rotate(a); /// use incremental rotation
ctx.drawImage(img, -w , -h);
/// spin down and only loop if angle > certain value
a *= 0.995;
/// continue if there is enough "inertia"
if (a > 0.001) requestAnimationFrame(loop);
}
The threshold value for continue the loop determines how "brutal" you want the stop to be. If you want the wheel to appear heavier (more mass) you can decrement the angle with an even tinier increment (eg. try 0.998).
For the ball to bounce around you need to resort to physics modelling, or at least pseudo-physics-modelling. This includes collision detections for all the small details on the wheel as well as sub-time-steps (ray casting) checking and positioning in z-axis.
I feel this is a bit broad to describe here on SO but find a good article on collision detection and physics simulation. Here is a good start with the basics.