JavaScript синусоида - PullRequest
       8

JavaScript синусоида

3 голосов
/ 27 августа 2011
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, но другие фрагменты, которые я видел, используют их противоположным образом. Зачем? Почему именно top/20 и top/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>

Ответы [ 2 ]

10 голосов
/ 27 августа 2011

Основная синусоидальная функция определяется как:

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

, где

  • A - амплитуда
  • w - частота
  • p - фаза

Эти факторы определяют, как будет выглядеть график функции f.

Амплитуда может рассматриваться как коэффициент масштабирования, чем больше A, тем больше (абсолютные значения) пики и минимумы f.

Частота определяет, как быстро будет работать функция синусачерез все его значения, пока не начнется снова - синус является периодической функцией.Чем больше k, тем быстрее f будет проходить через один период.

p - фаза, представьте, что она «смещает» начальную точку функции вправо (положительное p) или влево (отрицательное).Трудно объяснить словами, посмотрите здесь для графиков.

Функция, которую вы даете в своем примере, является обобщенной версией

f: R->R², f(t)=(sin(t), cos(t))

То есть (одиниз) параметризации единичного круга .Если вы увеличите t монотонно и нанесете x (sin (t)) и y (cos (t)), у вас будет точка, летящая по кругу с радиусом 1.

Ваша обобщенная функция:

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

В вашем случае A = amp, t = top и w = 20 для координаты x и w = 25 для координаты y.Эти небольшие отклонения для w делают движение нервным, так что это уже не идеальный круг, а скорее какой-то «искаженный» эллипс - я думаю, снежные хлопья не падают в идеальные круги.Кроме того, это делает путь пластинки более случайным, чем прямые идеальные круги.Хотя это иллюзия, все это также очень детерминировано и все еще периодично - просто движение x и y «не в фазе», так что до завершения одного периода требуется намного больше времени.

w выбран> 1, чтобы «замедлить» круговое движение.Чем больше вы выберете w, тем ниже будет частота, и ваша точка перемещения совершит полный круг намного медленнее.

Чем больше вы выберете A, тем больше станет ваш круг.

5 голосов
/ 27 августа 2011

Это просто увеличивает синусоидальную волну, чтобы ее было легче наблюдать.

Вот скрипка, которую я пытался сделать. Если я поменяю 20 и 25 на 1, движение станет менее интересным. http://jsfiddle.net/AbM9z/1/

Было бы полезно узнать, с какими значениями вызывается функция.

...