【问题标题】:JavaScript sine waveJavaScript 正弦波
【发布时间】:2011-08-26 20:53:40
【问题描述】:
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)
        };
    }

此例程以正弦波方式发送雪花。

但它是如何做到的呢?请解释一下。

它将Math.sin 用于x;和Math.cos 用于y,但我见过的其他sn-ps 以相反的方式使用它们。为什么?为什么是top/20top/25

整个代码:

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

【问题讨论】:

  • 是的,通常 x = cos(theta) 和 y = sin(theta),但没关系。如果你翻转 x 和 y 轴,你仍然会得到波浪运动。都好。 top/20 和 top/25 会使 x 和 y 有点异相,这对运动很有好处。

标签: javascript algorithm math trigonometry


【解决方案1】:

基本正弦函数定义为:

f(x) = A sin(wt + p)

在哪里

  • A 是幅度
  • w 是频率
  • p 是相位

这些因素决定了 f 的图形的外观。

幅度可以看作是一个比例因子,A越大,f的峰值和低点就越大(绝对值)。

频率决定了正弦函数在重新开始之前运行所有值的速度 - 正弦函数是一个周期函数。 k越大,f运行一个周期的速度越快。

p 是相位,将其视为将函数的起点向右(正 p)或向左(负)“移动”。难以用语言解释,请看here 的图表。

您在示例中给出的函数是

的通用版本
f: R->R², f(t)=(sin(t), cos(t))

这是parametrizations of the unit circle (其中之一)。如果您单调增加 t 并绘制 x (sin(t)) 和 y (cos(t)),您将有一个点在半径为 1 的圆上飞行。

你的广义函数是

f: R->R², f(t) = (A sin(1/wt), A cos(1/wt)), w > 1

在您的情况下,x 坐标为 A=ampl、t=top 和 w=20,y 坐标为 w=25。 w 的这些细微偏差使运动变得抖动,因此它不再是一个完美的圆圈,而是一些“扭曲”的椭圆 - 我猜雪花不会落在完美的圆圈中。此外,这使得薄片的路径看起来比直的完美圆圈更随机。虽然这是一种错觉,这也是非常确定的并且仍然是周期性的——只是 x 和 y 的运动是“异相”的,所以需要更长的时间才能完成一个周期。

w 选择 > 1 以“减慢”圆周运动。您选择的 w 越大,频率越低,您的移动点完成一整圈的速度会慢得多。

你选择的A越大,你的圈子就会越大。

【讨论】:

  • 但是为什么 w = 5 和 4,我以为是 20 和 25?为什么是A sin(1/wt),A cos(1/wt),我还以为是A sin(top/20),A cos(top/25)??什么是 R->R²??
  • 大声笑,当它很晚时会发生这种情况 - 我将 top/20 读为 o.2*top,所以 w 本来应该是 5...当然是 20 和 25,抱歉让我感到困惑,我会立即更新。 R->R² 是函数的域和范围——它将 R 中的值作为输入,输出是一个二维向量 (x,y),其中 y 和 y 都在 R 中,所以 (x, y) 在RxR 在数学中缩写为 R²。
【解决方案2】:

它只是使正弦波更大,以便更容易观察曲线。

这是我尝试制作的小提琴。如果我将 20 和 25 更改为 1,则运动变得不那么有趣。 http://jsfiddle.net/AbM9z/1/

了解调用函数的值会有所帮助。

【讨论】:

  • ampl 让它变大,top/20 和 top/25 改变波长,是吗?
  • 你在哪里改成1了??在那个小提琴中,我看到了 top/20 和 top/25
  • 我改了但没有保存。我应该让它在两者之间切换。事实上,我想我现在就去做。
  • 好的,我现在把它们放在一起了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
  • 2012-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多