悬停时水平滚动不稳定

Jerky horizontal scroll on hover

我正在使用以下 JS 代码构建一个在悬停时滚动的水平图像轮播。 mousemove 事件检测鼠标在容器上的位置并相应地向左或向右滚动。一切都如我所料,但如果我在动画 运行 时将鼠标移到容器上,它会变得有点不稳定。

有解决办法吗?

谢谢

JS:

$( '.carousel-frame ul' ).mousemove( function(e) {
    var container = $(this).parent();
    if ((e.pageX - container.offset().left) < container.width() / 2) {
        var direction = function() {
            container.animate({scrollLeft: '-=600'}, 1000, 'linear', direction);
        }
        container.stop().animate({scrollLeft: '-=600'}, 1000, 'linear', direction);
    } else {
        var direction = function() {
            container.animate({scrollLeft: '+=600'}, 1000, 'linear', direction);
        }
        container.stop().animate({scrollLeft: '+=600'}, 1000, 'linear', direction);
    }
}).mouseleave( function() {
    var container = $(this).parent();
    container.stop();
});

CSS:

.carousel-frame {
    width: 100%;
    margin-bottom: 0.5em;
    padding-bottom: 1em;
    position: relative;
    overflow-x: scroll;
    white-space: nowrap;
}
.carousel-frame ul {
    margin: 0;
    padding: 0;
    height: 100%;
    list-style: none;
}
.carousel-frame li.carousel-item {
    cursor: pointer;
    display: inline-block;
    margin: 0 5px 0 0;
    padding: 0;
}

HTML:

<div class="carousel-frame">
  <ul>
    <li class="carousel-item">
      <img src="http://placehold.it/200x150" />
    </li>
    <li class="carousel-item">
      <img src="http://placehold.it/200x150" />
    </li>
    <li class="carousel-item">
      <img src="http://placehold.it/200x150" />
    </li>
    <li class="carousel-item">
      <img src="http://placehold.it/200x150" />
    </li>
    <li class="carousel-item">
      <img src="http://placehold.it/200x150" />
    </li>
  </ul>
</div>

FIDDLE:

https://jsfiddle.net/dk6f3snf/

我对我的 JS 代码进行了一些更改,现在当鼠标在容器内移动时,滚动动画不再那么断断续续了。如果有人有更好的解决方案,请随时 post 这里。

JS:

var b = null;
$( '.carousel-frame ul' ).on( 'mousemove', function(e) {
    var container = $(this).parent();
    if ((e.pageX - container.offset().left) < container.width() / 2) {
        var direction = function() {
            container.animate( {scrollLeft: '-=600'}, 1000, 'linear', direction );
        }
        if ((b == false) || (b == null)) {
            b = true;
            container.stop( true ).animate( {scrollLeft: '-=600'}, 1000, 'linear', direction );
        }
    } else {
        var direction = function() {
            container.animate( {scrollLeft: '+=600'}, 1000, 'linear', direction );
        }
        if ((b == true) || (b == null)) {
            b = false;
            container.stop( true ).animate( {scrollLeft: '+=600'}, 1000, 'linear', direction );
        }
    }
}).on ( 'mouseleave', function() {
    var container = $(this).parent();
    container.stop( true );
    b = null;
});

FIDDLE:

https://jsfiddle.net/dk6f3snf/1/

要获得平滑效果需要进行两个主要更改:

一:当尝试创建流畅的动画时,总是选择 window.requestAnimationFrame...

二:在您的示例中,您正在检测 ul 上的鼠标事件,这意味着每次光标经过 li 元素之间的 "gap" 时动画都会中断。

已更新fiddle: https://jsfiddle.net/dk6f3snf/6/

var speed = 0;
var scroll = 0;
var container = $('.carousel-frame');
var container_w = container.width();
var max_scroll = container[0].scrollWidth - container.outerWidth();

container.on('mousemove', function(e) {
    var mouse_x = e.pageX - container.offset().left;
    var mouseperc = 100 * mouse_x / container_w;
    speed = mouseperc - 50;
}).on ( 'mouseleave', function() {
    speed = 0;
});

function updatescroll() {
  if (speed !== 0) {
      scroll += speed / 5;
        if (scroll < 0) scroll = 0;
        if (scroll > max_scroll) scroll = max_scroll;
      $('.carousel-frame').scrollLeft(scroll);
    }
    $("#speed").html('Speed: ' + speed);
    $("#scroll").html('Scroll: ' + scroll);
    window.requestAnimationFrame(updatescroll);
}
window.requestAnimationFrame(updatescroll);
.carousel-frame {
    width: 100%;
    margin-bottom: 0.5em;
    padding-bottom: 1em;
    position: relative;
    overflow-x: scroll;
    white-space: nowrap;
 }
 .carousel-frame ul {
    margin: 0;
    padding: 0;
    height: 100%;
    list-style: none;
}
.carousel-frame li.carousel-item {
    cursor: pointer;
    display: inline-block;
    margin: 0 5px 0 0;
    padding: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="carousel-frame">
      <ul>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
        <li class="carousel-item">
          <img src="http://placehold.it/200x150" />
        </li>
      </ul>
    </div>
    <div id="speed"></div>
    <div id="scroll"></div>

请注意,我还让速度取决于光标离中间的距离,而不是仅仅超过了哪一半然后放慢速度...主要是为了演示使用 window.requestAnimationFrame 方法造就东西。

更新

实际上,为了使速度在不同设备上保持一致并且不考虑其他 "stealing" 资源,我想您还需要考虑帧之间经过的时间。我已经更新了 fiddle 来证明这一点: https://jsfiddle.net/dk6f3snf/7/

更新

我认为你关于单个页面上的多个轮播的问题与你原来的问题完全不同......但一种方法是将它包装在一个简单的插件中 - 例如:https://jsfiddle.net/dk6f3snf/8/