JavaScript 正弦波
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7210458/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaScript sine wave
提问by DrStrangeLove
track : function(x, y, top, ampl) {
return {
top : top + 2,
x : x + ampl * Math.sin(top / 20),
y : (top / this.screenHeight < 0.65) ? y + 2 : 1 + y + ampl * Math.cos(top / 25)
};
}
This routine sends snowflakes flying in sine wave manner.
该例程以正弦波方式发送雪花。
But how does it do that? Please explain.
但它是如何做到的?请解释。
It uses Math.sin
for x
; and Math.cos
for y
, but other snippets I've seen use them in the opposite way. Why? Why exactly top/20
and top/25
?
它Math.sin
用于x
; 和Math.cos
for y
,但我见过的其他片段以相反的方式使用它们。为什么?为什么是top/20
和top/25
?
The whole code:
整个代码:
<script type="text/javascript">
var snowflakes = { // Namespace
/* Settings */
pics : [
['snow.gif' , 24, 24],
['snow2.gif', 24, 24],
['snow3.gif', 24, 24]
],
track : function(x, y, top, ampl) {
return {
top : top + 2,
x : x + ampl * Math.sin(top / 20),
y : (top / this.screenHeight < 0.65) ? y + 2 : 1 + y + ampl * Math.cos(top / 25)
};
},
quantity : 30,
minSpeed : 20, // 1 - 100, minSpeed <= maxSpeed
maxSpeed : 40, // 1 - 100, maxSpeed >= minSpeed
isMelt : true, // true OR false
/* Properties */
screenWidth : 0,
screenHeight : 0,
archive : [],
timer : null,
/* Methods */
addHandler : function(object, event, handler, useCapture) {
if (object.addEventListener) object.addEventListener(event, handler, useCapture);
else if (object.attachEvent)object.attachEvent('on' + event, handler);
else object['on' + event] = handler;
},
create : function(o, index) {
var rand = Math.random();
this.timer = null;
this.o = o;
this.index = index;
this.ampl = 3 + 7*rand;
this.type = Math.round((o.pics.length - 1) * rand);
this.width = o.pics[this.type][1];
this.height = o.pics[this.type][2];
this.speed = o.minSpeed + (o.maxSpeed - o.minSpeed) * rand;
this.speed = 1000 / this.speed;
this.deviation = o.maxDeviation * rand;
this.x = o.screenWidth * rand - this.width;
this.y = 0 - this.height;
this.top = this.y;
this.img = document.createElement('img');
this.img.src = o.pics[this.type][0];
this.img.style.top = this.y + 'px';
this.img.style.position = 'absolute';
this.img.style.zIndex = 10000;
this.img.style.left = this.x + 'px';
this.img.obj = this;
if (o.isMelt) this.img.onmouseover = function() {
clearTimeout(this.obj.timer);
this.obj.timer = null;
this.parentNode.removeChild(this);
}
document.body.appendChild(this.img);
this.move();
},
init : function() {
this.screenWidth = window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.offsetWidth);
this.screenWidth = navigator.userAgent.toLowerCase().indexOf('gecko') == -1 ? this.screenWidth : document.body.offsetWidth;
this.screenHeight = window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight);
this.screenScroll = (window.scrollY) ? window.scrollY : document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
this.archive[this.archive.length] = new this.create(this, this.archive.length);
clearTimeout(this.timer);
this.timer = null
this.timer = setTimeout(function(){snowflakes.init()}, 60000 / this.quantity);
}
};
snowflakes.create.prototype = {
move : function() {
var newXY = this.o.track(this.x, this.y, this.top, this.ampl);
this.x = newXY.x;
this.y = newXY.y;
this.top = newXY.top;
if (this.y < this.o.screenHeight + this.o.screenScroll - this.height) {
this.img.style.top = this.y + 'px';
this.x = this.x < this.o.screenWidth - this.width ? this.x : this.o.screenWidth - this.width;
this.img.style.left = this.x + 'px';
var index = this.index;
this.timer = setTimeout(function(){snowflakes.archive[index].move()}, this.speed);
} else {
delete(this.o.archive[this.index]);
this.img.parentNode.removeChild(this.img);
}
}
};
snowflakes.addHandler(window, 'load', function() {snowflakes.init();});
snowflakes.addHandler(window, 'resize', function() {snowflakes.init();});
</script>
回答by emboss
The basic sine function is defined as:
基本正弦函数定义为:
f(x) = A sin(wt + p)
where
在哪里
- A is the amplitude
- w is the frequency
- p is the phase
- A 是振幅
- w 是频率
- p是相位
These factors determine how the graph of f will look like.
这些因素决定了 f 的图形的样子。
The amplitude can be thought of as a scaling factor, the larger A, the larger (absolute values) the peaks and lows of f.
幅度可以被认为是一个比例因子,A越大,f的峰值和低点就越大(绝对值)。
The frequency determines how fast the sine function will run through all its values until it starts over again - sine is a periodic function. The larger k, the faster f will run through one period.
频率决定了正弦函数在重新开始之前运行所有值的速度 - 正弦是一个周期函数。k 越大,f 运行一个周期的速度就越快。
p is the phase, think of it as "shifting" the starting point of the function to the right (positive p) or left (negative). Hard to explain in words, have a look herefor graphs.
p 是相位,将其视为将函数的起点向右(正 p)或向左(负)“移动”。很难用语言解释,看看这里的图表。
The function you give in your example is a generalized version of
您在示例中给出的函数是
f: R->R2, f(t)=(sin(t), cos(t))
Which is (one of) the parametrizations of the unit circle . If you increase t monotonously and plot x (sin(t)) and y (cos(t)) you will have a point flying on a circle with radius 1.
这是(之一)单位圆的参数化。如果单调增加 t 并绘制 x (sin(t)) 和 y (cos(t)),您将有一个点在半径为 1 的圆上飞行。
Your generalized function is
你的广义函数是
f: R->R2, f(t) = (A sin(1/wt), A cos(1/wt)), w > 1
In your case A=ampl, t=top and w=20 for the x coordinate and w=25 for the y coordinate. These slight deviations for w are there make the movement jittery, so that it's no longer a perfect circle, but rather some "distorted" ellipse - snow flakes don't fall in perfect circles, I guess. Additionally this makes the path of the flake appear to be more random than straight perfect circles. It's an illusion though, this is all also very deterministic and still periodic - it's just that x and y movement are "out of phase" so it takes a whole lot longer until one period is completed.
在您的情况下,A=ampl,t=top 和 w=20 用于 x 坐标,w=25 用于 y 坐标。w 的这些细微偏差使运动变得不稳定,因此它不再是一个完美的圆,而是一些“扭曲”的椭圆 - 我猜雪花不会落入完美的圆圈中。此外,这使得薄片的路径看起来比直线完美的圆更随机。不过,这是一种错觉,这也是非常确定的并且仍然是周期性的——只是 x 和 y 的运动是“异相”的,所以在一个周期完成之前需要更长的时间。
w is chosen > 1 to "slow down" the circular movement. The larger you choose w, the lower the frequency will be and your moving point will complete a full circle much slower.
w 选择 > 1 以“减慢”圆周运动。您选择的 w 越大,频率越低,您的移动点完成一整圈的速度要慢得多。
The larger you choose A, the larger your circle will become.
你选的A越大,你的圈子就越大。
回答by Benjamin Atkin
It just makes the sine wave bigger so the curves can be more easily observed.
它只是使正弦波更大,因此可以更容易地观察曲线。
Here's a fiddle I tried making. If I change 20 and 25 to 1, the movement gets less interesting. http://jsfiddle.net/AbM9z/1/
这是我尝试制作的小提琴。如果我将 20 和 25 改为 1,运动就会变得不那么有趣。http://jsfiddle.net/AbM9z/1/
It would help to know what values the function is being called with.
这将有助于了解调用函数的值。