1

我正在做一个小的 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

4 回答 4

7

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

鉴于此,并且我们知道正弦波从 -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';

让我知道是否有任何不清楚的地方。问候。

于 2012-11-30T15:56:34.330 回答
7

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

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

为了保持与您设计的一样多,它会变成这样(需要 50 个 x 移动步骤来完成一个完整的正弦并使用 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()一直使用)

请参阅我更新的 JSFiddle 示例

于 2012-11-30T15:20:36.903 回答
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); 
}
于 2012-11-30T15:38:23.180 回答
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); 
}
于 2012-11-30T15:34:24.220 回答