在悬停时生涩的水平滚动

时间:2016-12-27 12:26:54

标签: jquery scroll hover carousel mousemove

我使用以下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/

2 个答案:

答案 0 :(得分:6)

要获得平稳效果,需要进行两项重大更改:

一:尝试制作流畅的动画时,请始终选择window.requestAnimationFrame ...

二:在您的示例中,您正在检测ul上的鼠标事件,这意味着每当光标通过li元素之间的“间隙”时动画就会中断。

更新小提琴: 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方法的顺畅程度做事。

更新

实际上为了使速度在不同的设备上保持一致,而不管其他东西“窃取”资源,我想你还需要考虑帧之间经过的时间。我已经更新了演示这个的小提琴: https://jsfiddle.net/dk6f3snf/7/

更新

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

答案 1 :(得分:0)

我在JS代码中做了一些更改,现在当鼠标在容器内移动时,滚动动画并没有那么不稳定。如果有人有更好的解决方案,请随时在此发布。

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/