jQuery沿正弦波动画化

4

我已经花了几天时间尝试,但我放弃了。

我正在尝试让一个对象无限地沿着正弦波动画。它不应该在第一个周期后结束。

主要问题:周期在约1 1/3 Pi处结束,而不仅仅是Pi。这个额外的运动破坏了动画效果。

我卡在这里:http://jsfiddle.net/WPnQG/12/。每个周期后,它会跳过大约40像素,然后继续沿着它的路径。这就是我无法解决的问题--它停止并重新开始的值不相等,因此对象看起来会跳来跳去。有人能帮忙一下吗?谢谢

我正在使用jQuery Path Plugin执行动画的路径--即所提到的正弦曲线。

enter image description here


来源:

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);
    });

}

我可以问一下,为什么你调用float(true,false),尽管float(dir)只需要一个参数吗?我只是想学习JS。 - ankit
我正在测试一些东西,忘记将“false”去掉,因为我已经删除了该参数,在IE中可能会抛出错误,但不会执行任何其他操作。 - Atticus
6个回答

2

我必须承认,我对这篇文章的写法有点困惑,但我理解你是从维基百科上得到的。只是让我感到奇怪的是正弦波在重新开始之前超过了2pi。通常,正弦波的完整循环是从0到2pi。我更新了一些JavaScript代码来解决这个问题,现在已经没有问题了。

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);

注意:你可以通过更改 s 中的常量来告诉它需要完成多少正弦波(1 表示一条完整的正弦波,2 表示两条完整的正弦波等)。此外,不再需要“翻转”波形。
JSFiddle 链接:http://jsfiddle.net/P5vqG/8/

干得好,Gary。是啊,它继续超过了它的结束点,这不奇怪吗?我用了Mike的解决方案,但如果我改变事情,我肯定会保留这个方便。谢谢你的意见,伙计,这确实教给我一些东西。赞 +1。 - Atticus
虽然我很感激你的回复,但现在我可以很容易地看出为什么之前它没有起作用。非常感谢。 - Atticus

1
当我注释掉这行时:
setTimeout(function(){float(!dir)}, 0);

该元素精确停止在标记为It skips here的线上。

当您将运动重置为// avoid exceeding stack时,似乎它会将元素的位置重置为y = 0,同时保留元素的x值以及其运动路径。

这个假设进一步验证了每当跳过发生(在y轴的任何地方),元素总是从y = 0恢复其运动。有时它的y值大于y = 0,有时它小于y = 0 - 因此看起来像是随机“跳跃”。

编辑

回到源正弦演示,通过操纵x= ...行,似乎可以获得接近无限滚动。经过查看原始源代码后,似乎演示脚本只编写了一个特定的示例,并解决了固定宽度的问题。

这里有一个可工作的示例。

通过操作第1行和第2行的数字,您可以指定路径要遍历的像素数,并在第3行上减慢路径速度,使其与原始演示相同的速度。因此,虽然不是数学上的无限,但在我的电脑上完成需要大约45秒。通过操作这些特定行,您可以使其尽可能“无限”。
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"
  );

好的,我需要它从上次离开的地方继续执行。尝试了很多方法,但是无法解决这个问题。 - Atticus
Mike!太棒了,这完美无缺。是的,你说得对,我的只允许穿过一个周期。在你的修复中,如何允许多个周期?(通过周期,我指的是正弦波的一个周期)是第一行还是第二行允许它循环超过一次?还是两者都可以?我以为第一行只改变振幅,第二行改变周期的宽度,显然我错了。+1,你太棒了,我已经为此烦恼了很久。 - Atticus

0

您可以使用PathAnimator沿着任何路径动画化任何内容。您只需要SVG坐标来描述您的路径。

演示页面


0

由于项目特定原因,无法使用它。 - Atticus

0

这里有一个解决方案(在这个fiddle中演示),可以仅通过使用Jquery的四个.animate参数来制作一个正弦波

    $("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.)
                })                                                                                  

            })
        })
    })

-1

改变

 return {top: y + "px", left: current_x + x + "px"}; 

  return {top: y + "px", left: last_x + x + "px"};

请查看更新后的fiddle示例


它不会继续到下一个段落(需要持续向前移动)。 - Atticus
那只是将X的距离加倍,时间不变,它仍然存在相同的错误。 - Atticus
你的fiddle在大约1又1/3个pi后重置x值。这是有意为之吗? - Michael Jasper
完全没有意图。我相信这是一个错误。 - Atticus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接