可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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);
});
}
回答1:
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."
Edit
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.
Here is a working example.
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"
);
回答2:
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/
回答3:
Why don't you use HTML5 Canvas? http://falcon80.com/HTMLCanvas/Animation/SineWave.html
回答4:
You can use PathAnimator to animate anything along any path. you only need the SVG coordinates that describe your path.
Demo Page
回答5:
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.)
})
})
})
})
回答6:
Change
return {top: y + "px", left: current_x + x + "px"};
to
return {top: y + "px", left: last_x + x + "px"};
See an updated fiddle