我有这个滑块,当我点击其中一个点时,它滑动到屏幕的中心。我遇到的问题是,如果我点击已经靠近中心的点,它移动得非常慢。 如果我单击距离更远的点,则需要相同的时间才能到达中心(但似乎移动得更快;显然这是一种错觉)。 我想做的是让他们都以同样的速度旅行。因此,距离中心越远越远,但最近的一个必须更快。
目前我的代码如下:
// Moves the current active item to the center
moveToCenter: function (e, dragOptions, animate) {
// Get the central position
var center = $window.innerWidth / 2,
rect = e.target.getBoundingClientRect(),
distance = center - rect.left - ((50 - 18) / 2), // Make these variables?
positive = rect.left > center;
// If we should animation
if (animate) {
// Get our fake mouse position
var clientX = center,
target = center + distance,
offset = clientX / $window.innerWidth,
length = distance / $window.innerWidth;
// Initiate the first move
_setupMove(dragOptions, offset);
// Execute every 1 millisecond
var timer = $interval(function () {
// Get our new clientX
clientX = clientX + length;
offset = clientX / $window.innerWidth;
// Move
_moveElements(dragOptions, offset, service.updateDragElement);
// Should we stop?
var stop = positive ? clientX <= target : clientX >= target;
// If we should stop
if (stop) {
// Cancel the interval
$interval.cancel(timer);
}
}, 1);
// Otherwise
} else {
// Update the current position
dragOptions.currentX = distance / dragOptions.speed;
// Move our elements
service.updateDragElement(dragOptions);
}
},
我知道这与设置clientX有关。我想也许我需要根据时间计算出我应该走多远,所以我创造了这个:
// Get our fake mouse position
var clientX = center,
target = center + distance,
offset = clientX / windowWidth,
percent = distance / windowWidth,
interval = 1000 * percent;
// Initiate the first move
_setupMove(dragOptions, offset);
// Execute every 1 millisecond
var timer = $interval(function () {
// Get our new clientX
clientX = clientX + (distance * percent);
offset = clientX / windowWidth;
// Move
_moveElements(dragOptions, offset, service.updateDragElement);
// Should we stop?
var stop = positive ? clientX <= target : clientX >= target;
// If we should stop
if (stop) {
// Cancel the interval
$interval.cancel(timer);
}
}, interval);
理论上它应该以相同的速度行进,而不管它必须行进的距离。但这没效果。
有没有人知道如何解决这个问题?
由于提出的答案,我已将代码更改为此内容:
// Animates the slider
animate: function (startTime, distance, duration, options) {
// Animate
requestAnimationFrame(function () {
// Get our offset
var now = Date.now(),
timeDelta = Math.min(now - startTime, duration),
timePercent = timeDelta / duration,
offset = timePercent * distance;
var finalX = options.finalX + offset;
// Create the transform
options.transform = 'translateX(' + finalX + 'px)';
// Add to our element
options.element.style.transform = options.transform;
if (timeDelta < duration) {
service.animate(startTime, distance, duration, options);
} else {
options.finalX = finalX;
options.currentX = options.xOffset + (distance / $window.innerWidth);
}
});
},
// Moves the current active item to the center
moveToCenter: function (e, dragOptions, animate) {
// Get the central position
var windowWidth = $window.innerWidth,
center = windowWidth / 2,
rect = e.target.getBoundingClientRect(),
distance = center - rect.left - ((50 - 18) / 2), // Make these variables?
positive = rect.left > center;
// If we should animation
if (animate) {
var start = center,
distance = center - rect.left - ((50 - 18) / 2), // Make these variables?
now = Date.now(),
duration = distance / 1;
// Animate our elements
service.animate(now, distance, duration, dragOptions);
// Otherwise
} else {
// Update the current position
dragOptions.currentX = distance / dragOptions.speed;
// Move our elements
service.updateDragElement(dragOptions);
}
},
如果我选择中心左侧的任何内容,现在可以正常滚动。当它位于中心右侧时,它只会跳到该点而不是动画。
答案 0 :(得分:1)
这是我推荐的方法。首先找出你想要的速度:
var velocity = 1; // pixels/millisecond
...然后使用requestAnimationFrame
“循环”:
var startPoint = center;
var endPoint = rect.left - 16;
var distance = endPoint - startPoint;
var startTime = Date.now();
var duration = distance / velocity;
animate();
function animate() {
requestAnimationFrame(function () {
var now = Date.now();
var timeDelta = Math.min(now - startTime, duration);
var timePercent = timeDelta / duration;
var offset = timePercent * distance;
_moveElements(dragOptions, offset, service.updateDragElement);
if (timeDelta < duration) {
animate();
}
});
}
使用setTimeout
/ setInterval
可以为动画添加人工延迟,并且不会跨设备执行一致。