(I'm new to coding in Javascript/HTML/CSS so excuse my terrible style!)
I'd like to animate an object in an array along a set of coordinates in that array at a static speed:
Example of the array:
_myPtArr = [{x:297, y:30},{x:299,y:47},{x:350,y:56},{x:305,y:176},{x:278,y:169},
{x:303,y:108},{x:269,y:79},{x:182,y:90},{x:137,y:81},{x:173,y:33},{x:231,y:38}];
What I did to do this was; create a function that runs at the beginning of the program to take in any array and add a distance property (named "dis") to the first of the two points it's calculating the distance of, and that looks like this:
function findDist(array) {
for (var i = 0; i<array.length-1;i++){
var p = array[i],
q = array[i+1],
dx = p.x - q.x,
dy = p.y - q.y,
dist = Math.sqrt(dx*dx + dy*dy);
array[i].dis=dist;
}
}
I did this because the way I was animating them was creating a variable named "_tick" which would move them from one point to another by incrementing from 0 thru 1, 0 being the starting point, and 1 being the ending point. And I was going to multiply the tick times the distance so that different line lengths would animate at the same speed. But I haven't gotten anything like that to work! I'm stuck! Here's the function/s which do what I was just talking about:
function calculateInnerPts(pts, pos){
var ptArr = [];
console.log(pts.length);
for(var i = 0; i < pts.length-1; i++){
ptArr[i] = {x: pts[i].x + (pts[i+1].x - pts[i].x) * pos, y: pts[i].y +
(pts[i+1].y - pts[i].y) * pos};
}
return ptArr;
}
Being called in a series like so:
In the enterFrameHandler (constant iteration) with "section" just incrementing to grab each set of 2 points/objects, so after _tick gets to "1", section++. :
ballAnim([_myPtArr[_section],_myPtArr[_section+1]],_tick);
then outside:
function ballAnim(pts,pos){
var iPts = pts;
for(var i = 0; i < pts.length-1; i++){
iPts = calculateInnerPts(iPts, pos);
}
drawBall(iPts[0]);
}
Finally, I draw the ball:
function drawBall(pts){
var w = 6,
h = 2;
ctx.clearRect(0,0,400,300);
ctx.beginPath();
ctx.arc(pts.x, pts.y, 5, 0, Math.PI * 2);
ctx.fillStyle="blue";
ctx.fill();
ctx.strokeStyle="black";
ctx.closePath();
ctx.stroke();
}
Could anyone shed any light on how I can accomplish this given this system, or even another better way of accomplishing the same effect? I would like to put in any array and get the same result (meaning the ball animates in a static speed)!
NOTE: I would NOT like to use anything but plain ol' Javascript/HTML/CSS; no API's!
Thank you all so much, this community is so amazing, and this is my first post, so go easy on me! XD
I'm sure the answers above are more elegant, but I've been working on this code all morning and I want to share ...
Demo of code here
//requestAnimFrame shim via Paul Irish
window.requestAnimFrame = (function(callback){
return (window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback){window.setTimeout(callback, 1000/60);});
})();
//main code
window.onload = function(){
//setup canvas
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
//variables
var canvasWidth = 400, canvasHeight = 400; //as set up in the <canvas> tag
var animationTime = 10000; //animation length in milliseconds
//clear canvas function
var clearCanvas = function(){
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
};
//define the line; build function for displaying it
var _myPtArr = [
{x:297, y:30}, {x:299,y:47}, {x:350,y:56}, {x:305,y:176},
{x:278,y:169}, {x:303,y:108}, {x:269,y:79}, {x:182,y:90},
{x:137,y:81}, {x:173,y:33}, {x:231,y:38}
];
var lineColor = 'red';
var drawLine = function(){
ctx.beginPath();
ctx.moveTo(_myPtArr[0].x, _myPtArr[0].y);
for(var i=1, z=_myPtArr.length; i<z; i++){
ctx.lineTo(_myPtArr[i].x, _myPtArr[i].y);
}
ctx.strokeStyle = lineColor;
ctx.stroke();
};
//define the ball; build function for displaying it
var myBall = {x: 0, y: 0, radius: 5, fillStyle: 'blue', strokeStyle: 'black'};
var drawBall = function(){
ctx.beginPath();
ctx.arc(myBall.x, myBall.y, myBall.radius, 0, (Math.PI*2));
ctx.closePath();
ctx.fillStyle = myBall.fillStyle;
ctx.strokeStyle = myBall.strokeStyle;
ctx.fill();
ctx.stroke();
};
//build an array of objects for each line to help ball position calculations
var myBallVectors = [];
var fullDistance = 0, p, q, dx, dy, tempDistance, tempTime, fullTime = 0;
for(var i=1, z=_myPtArr.length; i<z; i++){
p = _myPtArr[i-1], q = _myPtArr[i];
dx = q.x - p.x;
dy = q.y - p.y;
tempDistance = Math.sqrt((dx*dx)+(dy*dy));
fullDistance += tempDistance;
myBallVectors.push({x: p.x, y: p.y, dX: dx, dY: dy, magnitude: tempDistance});
}
for(var i=0, z=myBallVectors.length; i<z; i++){
myBallVectors[i]['start'] = fullTime * animationTime;
tempTime = myBallVectors[i].magnitude/fullDistance;
fullTime += tempTime
myBallVectors[i]['duration'] = tempTime * animationTime;
myBallVectors[i]['finish'] = fullTime * animationTime;
}
//function to work out where ball is in space and time
var myBallPosition = function(){
if(Date.now() > breakTime){
//move on to next line
currentLine++;
//check to see if animation needs to finish
if(currentLine >= myBallVectors.length){
doAnimation = false;
}
//otherwise, set new break point
else{
breakTime = startTime + parseInt(myBallVectors[currentLine].finish);
}
}
if(doAnimation){
//calculate ball's current position
var timePassed = Date.now() - (startTime + myBallVectors[currentLine].start)
var percentageLineDone = timePassed/myBallVectors[currentLine].duration;
myBall.x = myBallVectors[currentLine].x + (myBallVectors[currentLine].dX * percentageLineDone);
myBall.y = myBallVectors[currentLine].y + (myBallVectors[currentLine].dY * percentageLineDone);
}
};
//setup and display initial scene
drawLine();
myBall.x = _myPtArr[0].x;
myBall.y = _myPtArr[0].y;
drawBall();
//animation loop function
animate = function(){
clearCanvas();
drawLine();
myBallPosition();
drawBall();
if(doAnimation){
requestAnimFrame(function(){
animate();
});
}
};
//setup control variables, and start animation
var startTime = Date.now(), currentLine = 0;
var breakTime = startTime + parseInt(myBallVectors[currentLine].finish);
var doAnimation = true;
animate();
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With