Reputation: 6720
I've spent a couple days at this and I give up.
I'm trying to get an object to animate along a sine wave infinitely. It should not end after the first period.
Main Problem: The cycle ends at approx 1 1/3 Pi rather than just Pi. This extra movement ruins the animation.
I'm stuck here: http://jsfiddle.net/WPnQG/12/. After each period, it skips about 40 pixels and then continues along its path. This is the problem I can't get past -- the value it ends at and proceeds to restart at are not equal, so the object appears to skip around. Could anyone help a man out? Thanks
I am using the jQuery Path Plugin to perform the path of the animation -- the sine wave in question.
Source:
function float(dir){
var x_current = $("div").offset().left;
var y_current = $("div").offset().top;
var SineWave = function() {
this.css = function(p) {
var s = Math.sin(Math.abs(p-1)*10);
if (!dir){// flip the sin wave to continue traversing
s = -s;
}
var x = 300 -p * 300;
var y = s * 100 + 150;
//var o = ((s+2)/4+0.1); //opacity change
last_x = x;
// add the current x-position to continue the path, rather than restarting
return {top: y + "px", left: x_current + x + "px"};
}
};
$("div").stop().animate({
path: new SineWave
}, 5000, 'linear', function(){
// avoid exceeding stack
setTimeout(function(){float(!dir)}, 0);
});
}
Upvotes: 4
Views: 10539
Reputation: 147
Here's a solution (demonstrated in this fiddle) to making a Sinusoidal Wave just by using Jquery's four .animate
parameters:
$("div").animate({ left: [ '+=8%', 'linear' ],
top: [ '+=5%' , 'swing' ] }, 1000, null, function() {
$(this).animate({ left: [ '+=8%', 'linear' ],
top: [ '-=5%' , 'swing' ] }, 1000, null, function() {
$(this).animate({ left: [ '+=8%', 'linear' ],
top: [ '+=5%' , 'swing' ] }, 1000, null, function() {
$(this).animate({ left: [ '+=8%', 'linear' ],
top: [ '-=5%' , 'swing' ] }, 1000, null, function() {
//(etc.)
})
})
})
})
Upvotes: 0
Reputation: 130075
You can use PathAnimator to animate anything along any path. you only need the SVG coordinates that describe your path.
Upvotes: 0
Reputation: 7121
I must confess i was a bit confused about how this was written however i do understand you got it from the wiki. It just struck me as odd that the sin wave went beyond 2 pi before restarting. Typically a sin wave is from 0 to 2pi for a complete loop. I have some updated javascript taking this into account and the hiccup is now gone.
function float(dir){
var x_current = $("div").offset().left;
var y_current = $("div").offset().top;
var SineWave = function() {
this.css = function(p) {
var pi2 = (3.1415927 * 2);
var a = p * pi2;
var s = Math.sin((pi2 - a)*2);
var x = 300 * (1 - p);
var y = s * 100 + 150;
//var o = ((s+2)/4+0.1); //opacity change
last_x = x;
// add the current x-position to continue the path, rather than restarting
return {top: y + "px", left: x_current + x + "px"};
}
};
$("div").stop().animate({
path: new SineWave
}, 5000, 'linear', function(){
// avoid exceeding stack
setTimeout(function(){float(!dir)}, 0);
});
}
float(true);
Note: you can tell it how many sin waves to complete by changing the constant in s (1 is one full sin wave, 2 is two full sin waves, etc.) Also, there is no more need to "reverse" the wave.
JSFiddle link: http://jsfiddle.net/P5vqG/8/
Upvotes: 2
Reputation: 8058
When I comment out this line:
setTimeout(function(){float(!dir)}, 0);
the element stops motion precisely on the line marked It skips here
.
It appears that when you reset the motion to // avoid exceeding stack
it resets the position of the element to to y=0, while preserving the x value of the element as well as its path of motion.
This hypothesis is further validated in that when ever a skip occurs (anywhere on the y axis) the element always resumes its motion from y=0. Sometimes its y value is > y = 0 while sometimes it is < y = 0 -- thus the random looking "skipping around."
Going back to the source sine demo, it seems you can get near infinite scrolling, by manipulating the x= ...
line. After some looking at the original source, it appears that the demo script was only written to accommodate that one specific example and fixed width problems.
By manipulating the numbers on line 1 and 2 you can specify the number of pixels for the path to traverse, and the slow the path down on line 3 to make it the same speed as the original demo. So, not mathematically infinite, but it took a good 45 seconds to complete on my computer. By manipulating these specific lines you can make it as "infinite" as you need.
window.SineWave = SineWave = function() {
this.css = function(p) {
s = Math.sin((p-1)*500); // 1
x = (5000 - p*5000) * 10; // 2
y = s * 100 + 150;
return {top: y + "px", left: x + "px"};
}
}
$("#nyan").stop().animate(
{path: new SineWave},
50000, // 3
"linear"
);
Upvotes: 1
Reputation: 1621
Change
return {top: y + "px", left: current_x + x + "px"};
to
return {top: y + "px", left: last_x + x + "px"};
See an updated fiddle
Upvotes: -1
Reputation: 1241
Why don't you use HTML5 Canvas? http://falcon80.com/HTMLCanvas/Animation/SineWave.html
Upvotes: 0