- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试创建一个 Roulette/CSGO 类型的轮盘,我拼凑了一些我在网上找到的解决方案。但是,我似乎无法弄清楚如何处理动画/滚轮减速以使其看起来尽可能平滑。
基本前提是我将传递中奖结果编号,然后轮子将旋转最短所需时间 (_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 中所看到的,它有点工作,但它只是不流畅并且有时会变慢等等...因此非常感谢您的帮助。 p>
提前致谢!
最佳答案
您需要实现一些摩擦。
只需将速度乘以所需摩擦力的一小部分即可。
速度=速度*摩擦力
速度 = 速度 * 0.8
分数越高,摩擦越小,减速越慢。
编辑:在您的情况下,您可能希望对运动值应用摩擦力,但如果不运行您的代码,我不能完全确定。
编辑 2:
好的,运行你的 fiddle ,我想这就是你要找的东西? 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;
}
};
就像我在之前的编辑中提到的那样,我对你的 Action 施加了摩擦力。
编辑 3(来自评论):
实现的方法是获取目标位置,并在使用总宽度的模数进行平移时轻松到达目标位置。您可以使用这种技术制作许多不同的动画,但我选择了缓出正弦方程。
这可以称为“滑动窗口动画”,可以把它想象成一个沿着轨道滚动到特定位置的条。
新 fiddle 在这里: 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)'
});
};
关于javascript - 如何平稳地控制 javascript 轮盘赌的动画速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41465771/
我是一名优秀的程序员,十分优秀!