2017-01-04 69 views
4

我試圖創建一個輪盤/ CSGO類型的輪子,我已經拼湊出了一些我在網上找到的解決方案。但我似乎無法弄清楚如何處理動畫/ 減慢輪子,使其看起來儘可能平滑平滑如何順利控制javascript輪盤上的動畫速度?

基本前提是我會傳入獲勝結果編號,然後輪子會旋轉一段最短所需時間(_this.spinTime),然後「應」優雅地放慢速度,然後當然落地正確的號碼。

這裏是我到目前爲止的代碼(我評論的重點區域):

window.requestAnimFrame = (function() { 
    return window.requestAnimationFrame || 
    window.webkitRequestAnimationFrame || 
    window.mozRequestAnimationFrame || 
    window.oRequestAnimationFrame || 
    window.msRequestAnimationFrame || 
    function(callback, element) { 
     window.setTimeout(callback, 1000/60); 
    }; 
})(); 

SpinWheel = function(id) { 

    var _this = this; 

    _this.el = $('.wheel-wrapper'); 
    _this.speed = 0; 
    _this.startTime = new Date(); 
    _this.items = 20; 
    _this.itemsWidth = 50; 
    _this.spinTime = 3000; 
    _this.running = false; 
    _this.motion = 20; 
    _this.resultId = id; 
    _this.resultOffset = null; 

    _this.setup = function() { 
    _this.resultOffset = _this.resultId * _this.itemsWidth; 
    _this.loop(); 
    }; 

    _this.loop = function() { 
    _this.running = true; 
    (function gameLoop() { 
     _this.update(); 
     //this returns the translateX to 0 once wheel width is met 
     if (_this.speed >= (_this.items * _this.itemsWidth + _this.itemsWidth)) { 
     _this.speed = 0; 
     } 
     _this.speed += _this.motion; 
     if (_this.running) { 
     requestAnimFrame(gameLoop); 
     } 
    })(); 
    }; 

    _this.update = function() { 
    var now = new Date(); 
    _this.el.css({ 
     'transform': 'translateX(-' + _this.speed + 'px)' 
    }); 
    //the key area!! 
    //if the time elapsed it greater than the spin time, start the slowing down 
    if (now - _this.startTime > _this.spinTime) { 
     //if the x pos == winning pos && the transition speed is at it's slowest 
     if (_this.speed == _this.resultOffset && _this.motion == 1) { 
     //stop the animation 
     _this.running = false; 
     //here we increment down the slowing down 
     } else if (_this.speed >= _this.resultOffset) { 
     if (_this.motion == 2) { 
      _this.motion = 1; 
     } else if (_this.speed % _this.motion == 0 && _this.motion > 1) { 
      _this.motion -= 2; 
     } 
     } 
     return; 
    } 

    }; 


    _this.init = function() { 
    _this.setup(); 
    }; 

    _this.init(); 

    return _this; 

}; 
//will be passed in: 20 = number of items 
var resultId = parseInt(Math.random() * 20); 

var wheel = new SpinWheel(resultId); 

隨意撕碎它,如果有一個更理想的解決方案。

Fiddle Here

如在小提琴中可以看出,它種工作,但它只是不順利,它是如何減慢,有時等不一致。所以幫助將不勝感激。

提前致謝!

回答

2

您需要實施一些摩擦。

只需將速度乘以所需摩擦的一小部分即可。

速度=速度*摩擦

速度=速度×0.8

更高的分數,更小的摩擦,並且所述減速慢。


編輯:你的情況,你可能要應用摩擦你的運動值,但我不能沒有運行代碼完全肯定。


編輯2:

好你跑小提琴,我認爲這是你在找什麼? https://jsfiddle.net/ywm3zbc4/7/

_this.update = function() { 
    var now = new Date(); 
    _this.el.css({ 
     'transform': 'translateX(-' + _this.speed + 'px)' 
    }); 
    if (now - _this.startTime > _this.spinTime) { 
     if (_this.speed == _this.resultOffset && _this.motion == 1) { 
     _this.running = false; 
     } else if (_this.speed >= _this.resultOffset) { 
     _this.motion = _this.motion * 0.99; 
     } 
     return; 
} 

};

我像之前編輯中提到的那樣將摩擦應用於您的動作。


編輯3(從評論):

做到這一點的方法是獲得目標位置,並在使用總寬度的模翻譯緩解了這一點。你可以用這種技術玩許多不同的動畫,但我決定了緩和的正弦方程。

這可以稱爲「滑動窗口動畫」,將其視爲滾動軌跡到特定位置的小節。

新小提琴這裏: https://jsfiddle.net/ywm3zbc4/10/

這裏是它的肉:

// t: current time 
// b: start value 
// c: change in value 
// d: duration 
function easeOutSine(t, b, c, d) { 
    return c * Math.sin(t/d * (Math.PI/2)) + b; 
} 

_this.update = function(rafTime) { 
    var deltaTime = rafTime - _this.startTime; 
    if (deltaTime >= _this.spinTime) { 
    _this.running = false; 
    return; 
    } 
    // t = timeFraction 
    var t = easeOutSine(deltaTime, 0, 1, _this.spinTime); 
    _this.position = Math.round(t * _this.totalDistance); 
    var translateX = _this.position % _this.totalWidth; 
    console.log('translateX:', translateX, 'position:', _this.position, 'deltaTime:', deltaTime); 
    _this.el.css({ 
    'transform': 'translateX(-' + translateX + 'px)' 
    }); 
}; 
+0

您好,感謝您的快速回答,我有一個外觀和是它看起來的方式更好,現在問題是它不停在正確的數字上:| – user7374467

+0

對不起,我可能刪除了太多的想法。現在我看到了你的resultOffset,你可以做的是在經過一定量的摩擦之後插入這個值。如果你不熟悉插值,這個評論是不適合解釋的地方。基本上你有一個目標位置,但你試圖讓它看起來是隨機的,我明白了。所以你需要循環幾次,減速一些摩擦,等待你的目標位置在一個速度閾值內,然後緩解其餘的方式。 – drkibitz

+0

是的,很多 – user7374467