1

我所追求的:

我的页面上有 5 个计数器,它们都应该从 0 开始并同时向上计数(递增)到以不同速度设置的不同值。因此,例如,我在变量中设置了 10、25、1500、400、500,我希望它们都达到这些值。

• 同时开始 • 所有增量以不同的速度 • 在每个设置的值处停止

我的问题

我想不出一个好方法来编写一些简单的非常有效的 javascript 来做到这一点(将在移动设备上使用),目前我正在使用 setinterval 似乎在不同时间启动所有计数器并且抽搐/不顺畅..

到目前为止我已经走了多远 http://jsfiddle.net/95smH/

setInterval(f1,500);
setInterval(f2,1500);
setInterval(f3,500);
setInterval(f4,50);

var v1      = 0
,   v2 = 0
,   v3  = 0
,   v4  = 0;

function f1() {
    $('.count.v1').text(v1);
    if ( v1 < 450 )
    {
        v1 ++;
    }
}
function f2() {
    $('.count.v2').text(v2);
    if ( v2 < 50 )
    {
        v2 ++;  
    }
}
function f3() {
    $('.count.v3').text(v3);
    if ( v3 < 23 )
    {
        v3 ++;  
    }
 }
function f4() {
    $('.count.v4').text(v4);
    if ( v4 < 4 )
   {
        v4 ++;  
    }
}
4

4 回答 4

1

这是一个对 cpu 非常友好的解决方案:
- 您只有一个 setInterval 使用您决定的基期。
- 在每个时间间隔上,您遍历所有计数器,每次只做很少的工作。(我什至避免使用 % )。
- 元素被缓存。

jsbin 在这里: http ://jsbin.com/urUxojo/2/edit?html,js,console,output

window.onload=function() {

// this is the period of the base Interval in ms. 
// The counters will be aligned on this base period
Counter.basePeriod = 50 ;

// constructor of a Counter
// ! initializes the counter display.
function Counter(id, period_ms, max, initialValue) {
         this.element  = document.getElementById(id);
         this.period   = Math.ceil(period_ms / Counter.basePeriod) || 1;
         this.max      = max ;
         this.value    = initialValue || 0 ;
         this.last     = 0;
         this.element.value = (this.value);
         return this;
};

// called on each basePeriod tick
// updates the element every period until it reaches its max value.
Counter.prototype.tick = function() {
        this.last++;
        if (this.last == this.period  && 
                           this.value != this.max ) {
             this.value++;
             this.element.value = (this.value);
             this.last=0;
        } 
};

Counter.counters = []; 

Counter.start= function () {   
       function handleCounters() {
         for (var i=0; i< Counter.counters.length; i++) {  Counter.counters[i].tick();  }
       }
       Counter._interval = setInterval(handleCounters, Counter.basePeriod); 
};

Counter.add = function() {
    var newCounter = Object.create(Counter.prototype);
    Counter.counters.push( Counter.apply(newCounter, arguments) );
}

// -------------------------------

Counter.add('cnt1'      , 500  , 450 );
Counter.add('cnt2'      , 400  , 40 );
Counter.add('topCounter', 1000 , 5  );

Counter.start();

}
于 2013-09-08T19:26:15.643 回答
1

这是基于你自己的代码风格:

setInterval(tick,50);

var cusers      = 0
,   cawardshows = 0
,   ccountries  = 0
,   cregions    = 0;

var susers = 500
,   sawardshows = 1500
,   scountries = 500
,   sregions = 50;

var i = 0;

function tick() {    
    $('.count.users').text(cusers);
    if ( cusers < 450 && i % susers == 0)
    {
        cusers ++;
    }

    $('.count.awardshows').text(cawardshows);
    if ( cawardshows < 50 && i % sawardshows == 0 )
    {
        cawardshows ++; 
    }
    $('.count.countries').text(ccountries);
    if ( ccountries < 23  && i % scountries == 0 )
    {
        ccountries ++;  
    }
    $('.count.regions').text(cregions);
    if ( cregions < 4 && i % sregions == 0)
    {
        cregions ++;    
    }
    i += 50;
}

这个想法是只有一个计时器,所以所有更新都将同步到同一个时钟。由于值具有不同的“速度”,因此您仅每第 n 步更新其中一些值。

于 2013-09-08T18:49:59.603 回答
1

这将是我以更一般的方式进行的拍摄。setInterval一旦每个计数器完成,它也会杀死。当然,这仍然会有 Javascript 间隔的典型不准确性。

var counter = new (function () {
    'use strict';

    var counters = [],
        handler = null,
        precision = 50;

    this.addCounter = function (maxValue, interval, selector) {
        counters.push({
            maxValue: maxValue,
            currentValue: 0,
            interval: interval / precision,
            intervalCounter: 0,
            $output: $(selector)
        });

        return this;
    };

    this.start = function () {
        handler = setInterval(function () {
            var stillRunning = false;
            for (var i = 0; i < counters.length; i++) {
                var counter = counters[i];

                counter.intervalCounter++;
                if (counter.intervalCounter === counter.interval) {
                    counter.intervalCounter = 0;
                    counter.currentValue++;

                    if (counter.currentValue <= counter.maxValue) {
                        stillRunning = true;
                        counter.$output.val(counter.currentValue);
                    }
                } else {
                    stillRunning = true;
                }
            }

            if (!stillRunning) {
                clearInterval(handler);
            }
        }, precision);
    };

    return this;
})();

counter
    .addCounter(50, 250, '.v1')
    .addCounter(25, 500, '.v2')
    .start();

演示小提琴: http: //jsfiddle.net/s9AYz/1/ 注意必须设置精度,使得每个计数器的间隔是它的倍数(Boris 解决方案具有相同的要求)。

于 2013-09-08T19:18:14.900 回答
0

好吧,你总是想摆脱重复,所以你可以这样做:

function IntervalClass(selector, sleepTime, maxValue, startValue) {
    var curValue = startValue;

    this.tick = function () {
        if (curValue < maxValue) {
            curValue++;
        }
        $(selector).html(curValue);
    };

    this.start = function () {
        setInterval(this.tick, sleepTime);
    };
}

new IntervalClass(".count.users", 1000, 35, 0).start();
new IntervalClass(".count.awardshows", 500, 20, 0).start();
new IntervalClass(".count.countries", 1500, 15, 0).start();
new IntervalClass(".count.regions", 200, 100, 0).start();

JSFIDDLE

于 2013-09-08T20:08:38.667 回答