这个javascript动画不应该产生正弦波运动吗?

时间:2012-11-30 15:12:54

标签: javascript animation sine

我正在做一个小的JavaScript动画,希望小div可以沿着正弦波移动,而目前水平路径工作正常(只是直线)。我几乎可以确定Y轴的数学公式是错误的。我试图用我发现的一些例子来纠正它,但它们都没有为我工作。在我尝试的所有可能性中,Y轴被忽略,小盒子只是水平移动。

我怎样才能解决这个问题,所以这个动作沿着正弦波传播?我知道使用jQuery或使用html 5可以更容易地做到这一点,但我只是想知道我的原始代码有什么问题......如果可能的话我宁愿解决这个问题。

function animate() {
    xnow = item.style.left;
    item.style.left = parseInt(xnow)+1+'px';
    ynow = item.style.top;
    item.style.top = ynow + (Math.sin((2*Math.PI*xnow)/document.width))*document.heigth;
    setTimeout(animate,20); 
}

这里的完整代码: JSFiddle

4 个答案:

答案 0 :(得分:7)

我发现您的代码有几个问题:

  • xnow包含以下格式的字符串:###px您无法将其相乘,因此请在parseInt()来电中使用Math.sin()
  • 您的代码要抓取ynow,它需要parseInt()
  • 更好的是使用其他(全局)变量将x和y坐标存储为数字。并在更新div元素的坐标时添加px
  • 当您将2*Math.PIxnow(仅包含整数)相乘时,sin()函数将始终返回0。所以你不会得到正弦运动。您需要将xnow除以您想要用来执行完整正弦运动的x步数
  • Math.sin()返回介于-1和+1之间的值,因此您需要将其乘以振幅才能看到(更清晰)效果。

为了保持它与你设计的一样多,它会变成这样的东西(需要50个移动步骤来完成正弦并使用10像素的振幅):

function animate() {
    xnow = parseInt(item.style.left);
    item.style.left = (xnow+1)+'px';
    ynow = parseInt(item.style.top);
    item.style.top = (ynow+Math.sin(2*Math.PI*(xnow/50))*10) + "px";
    setTimeout(animate,20);
}

如上所述:使用包含值的一些全局变量(而不是一直使用parseInt())要好得多。

查看我的updated JSFiddle example

答案 1 :(得分:7)

sin函数的形式为y = a * sin(b * x)+ c,其中c是函数的y-中点(或函数振荡的水平线),其中a是幅度(从y = c的最大y偏移量)和b是周期(每个波的x = 2 * pi段的数量)。

鉴于此,并且我们知道sin波从-a到+ a振荡,我们知道我们的偏移量(c)应该是1)是常数,2)在我们的上限和下限之间。为此,我们可以使用

c = document.height / 2;

如果您希望对象遍历整个屏幕,您的幅度将与c的值相同。在测试中,你会发现这会让它超越页面的底部,所以让我们把它做到90%。

a = 0.9 * c;

对于整个页面的1周期,你需要使b乘以一个因子,使得它将是2 * pi的分数。在这种情况下

b = 2*Math.PI/document.width;

在每次迭代中,不需要获取ynow的值,它是xnow的函数。你可以按照

的方式做点什么

xnow = parseInt(item.top.left) + 5;

然后用

计算新的y

ynow = c + a * Math.sin(b * xnow);

然后设置项目的样式。

item.style.left = xnow + 'px';

item.style.top = ynow + 'px';

如果有什么不清楚,请告诉我。问候。

答案 2 :(得分:2)

您需要在parseInt()上使用xnow。您还需要将“px”添加到数字的末尾,以生成格式正确的字符串。

此代码有效:

function animate() {
  xnow = parseInt(item.style.left);
  item.style.left = xnow+1+'px';
  item.style.top = 200 + (Math.sin((2*Math.PI*xnow)/200))*document.height+'px';
  setTimeout(animate,20); 
}

答案 3 :(得分:1)

有几个错误:

  • height拼写错误
  • 在获取正弦之前将xnow解析为int
  • 在添加之前将ynow解析为int(尽管实际上并不需要,请参见下文)
  • "px"添加到item.style.top
  • 的作业的末尾
  • 这个等式可以使用一些调整:

我建议从(400 + Math.sin(2*Math.PI*xnow/document.width) * 200) + "px"开始,然后再玩它。 400是基于正弦波的水平轴。如果使用ynow代替常数,则会产生累积效果(波浪将比您想要的高得多,或者水平轴会随着时间的推移而变化)。

document.width是一个完整句点的宽度。 200是峰值幅度(从水平到峰值的距离 - document.height会在两个方向上将屏幕推离屏幕)。插入此功能代替当前功能,然后您可以使用数字:

function animate() {
  xnow = parseInt(item.style.left);
  item.style.left = xnow+1+'px';
  item.style.top = (400 + Math.sin(2*Math.PI*xnow/document.width) * 200) + "px";
  setTimeout(animate,20); 
}