动画速度问题

时间:2016-07-25 23:37:37

标签: javascript

我有这个滑块,当我点击其中一个时,它滑动到屏幕的中心。我遇到的问题是,如果我点击已经靠近中心的,它移动得非常慢。 如果我单击距离更远的,则需要相同的时间才能到达中心(但似乎移动得更快;显然这是一种错觉)。 我想做的是让他们都以同样的速度旅行。因此,距离中心越远越远,但最近的一个必须更快。

目前我的代码如下:

// 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);
    }
},

如果我选择中心左侧的任何内容,现在可以正常滚动。当它位于中心右侧时,它只会跳到该点而不是动画。

1 个答案:

答案 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可以为动画添加人工延迟,并且不会跨设备执行一致。