如何在jQuery中创建垂直滚动的div?

Ina*_*nam 5 html javascript css jquery

我正在使用带有动画的jquery创建垂直自动滚动div ...我已经完成了它的创建,但是唯一的问题是当我将窗口向下滚动到div滚动的列表div的中间时,它将窗口向上滚动列表分区 我不知道问题是什么。但是,当我尝试以像素为单位指定列表div宽度时,它并没有增加...

尝试向下滚动到滚动列表div的中间。您将了解问题所在。谢谢...

setInterval(function(){
  $('#list').stop().animate({scrollTop:40}, 400, 'swing', function(){
    $(this).scrollTop(0).find('div:last').after($('div:first', this));
  });
}, 1000);
Run Code Online (Sandbox Code Playgroud)
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#list {
  overflow: hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list div {
  display: block;
  height: 30px;
  padding: 10px 10px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="list">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
  <div>Item 4</div>
  <div>Item 5</div>
  <div>Item 6</div>
  <div>Item 7</div>
  <div>Item 8</div>
  <div>Item 9</div>
  <div>Item 10</div>   
</div>
Run Code Online (Sandbox Code Playgroud)

Jac*_*ack 3

多么奇怪的错误啊。据我所知,由于removal/insertion第一个元素到列表末尾,这会导致 Chrome 重新渲染列表,从而导致偏移量发生变化scrollY

就我个人而言,我可以想到两种方法来解决这个问题。

1) 从 DOM 流中删除 div (#list)。

注意:这需要将您的#list元素包装在一个containing元素中。

因为您删除/追加元素到您的#list元素,这会导致发生回流(???)。最初,我认为使用position: absolute可以解决这个问题,因为你不再影响 DOM 流。然而,即使position: absolute仍然导致滚动位置跳跃。

然后我查看了position: fixed,它确实有效(因为它基本上位于所有内容之上) - 这显然不会起作用,因为您希望列表随页面滚动!那么,我们怎样才能解决这个问题呢?

transform来救援!

让我们利用一个transform 怪癖!通常,当元素为 时position: fixed,它是相对于视口的。但是,如果祖先元素具有transformation,则定位的元素fixed将相对于转换后的元素。让我们试一试吧!

正如我所提到的,您需要应用包装/包含元素来进行转换。在下面的代码片段中,我用#list新的div#transformed.

CSS 更改很简单,如下所示:

#transformed { transform: translateZ(0); }
#list { position: fixed; }
Run Code Online (Sandbox Code Playgroud)

就是这样!查看下面的代码片段以了解其实际效果。

#transformed { transform: translateZ(0); }
#list { position: fixed; }
Run Code Online (Sandbox Code Playgroud)
setInterval(function(){
  $('#list').stop().animate({scrollTop:40}, 400, 'swing', function(){
    $(this).find('div:last').after($('div:first', this));
  });
}, 1000);
Run Code Online (Sandbox Code Playgroud)
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#transformed {
  transform: translateZ(0);
}

#list {
  position: fixed;
  overflow: hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list div {
  display: block;
  height: 30px;
  padding: 10px 10px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
Run Code Online (Sandbox Code Playgroud)

2)滑动一层

至于解决问题的第二种方法,这更多的是关于如何解决这个问题的讨论/意见(因此,遗憾的是无法提供代码)。

我不会操纵scrollTop,而是研究“滑动”层方法(使用transformYtop)。

您会发现基于 JS 的轮播采用类似的方法(有趣的是,轮播倾向于使用滚动偏移方法 - 与此问题类似,或者“滑动”层方法!他们只是倾向于水平执行)

至于您操作的层,我再次建议将其从 DOM 流中删除(so position: absolute)。理论上,操作该层不应该影响滚动偏移......

无论如何,希望这对您有所帮助并且该position: fixed方法适合您:)

编辑

关于您的评论,您可以通过反转您的逻辑来实现“向下”滚动setInterval。但是,您不需要滚动然后将刚刚滚动到列表底部的项目移动到列表底部,而是需要将要滚动到列表顶部的元素移动到列表顶部,偏移scrollTop,然后滚动到。

这是演示的片段:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
  <div id="list">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
    <div>Item 5</div>
    <div>Item 6</div>
    <div>Item 7</div>
    <div>Item 8</div>
    <div>Item 9</div>
    <div>Item 10</div>   
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)
setInterval(function(){
    $('#list')
        .find('div:first')
        .before($('div:last', '#list'))
        .end()
        .scrollTop(40)
        .stop()
    .animate({scrollTop:0}, 400, 'swing');
}, 1000);
Run Code Online (Sandbox Code Playgroud)
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#transformed {
  transform: translateZ(0);
}

#list {
  position: fixed;
  overflow: hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list div {
  display: block;
  height: 30px;
  padding: 10px 10px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
Run Code Online (Sandbox Code Playgroud)

编辑#2:

关于向上/向下按钮,您可以通过组合我们迄今为止编写的两个脚本轻松实现!这是两个在您单击时向上/向下动画的片段(第一个片段将在您每次单击时滚动,第二个片段将更改动画方向):

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
  <div id="list">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
    <div>Item 5</div>
    <div>Item 6</div>
    <div>Item 7</div>
    <div>Item 8</div>
    <div>Item 9</div>
    <div>Item 10</div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)
function animateList(direction) {
if (direction === 'down') {
    $('#list')
        .find('div:first')
        .before($('div:last', '#list'))
        .end()
        .scrollTop(40)
        .stop()
        .animate({scrollTop:0}, 400, 'swing');
} else {
    $('#list')
        .animate({scrollTop:40}, 400, 'swing', function(){
            $(this)
                .find('div:last')
                .after($('div:first', this));
        });
}
}

$('button').on('click', function () {
var direction = $(this).attr('id');
animateList(direction);
});
Run Code Online (Sandbox Code Playgroud)
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#transformed {
  transform: translateZ(0);
}

#list {
  position: fixed;
  overflow: hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list div {
  display: block;
  height: 30px;
  padding: 10px 10px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
Run Code Online (Sandbox Code Playgroud)

以及改变方向的片段:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="transformed">
  <div id="list">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
    <div>Item 5</div>
    <div>Item 6</div>
    <div>Item 7</div>
    <div>Item 8</div>
    <div>Item 9</div>
    <div>Item 10</div>
  </div>
</div>

<button id="up">Scroll Up</button>
<button id="down">Scroll Down</button>
Run Code Online (Sandbox Code Playgroud)
var interval;
function animateList(direction) {
    // Reset interval
    if (interval) {
        clearInterval(interval);
    }
    if (direction === 'down') {
        interval = setInterval(function () {
            $('#list')
                .find('div:first')
                .before($('div:last', '#list'))
                .end()
                .scrollTop(40)
                .stop()
                .animate({scrollTop:0}, 400, 'swing');
        }, 1000);
    } else {
        interval = setInterval(function () {
            $('#list')
                .animate({scrollTop:40}, 400, 'swing', function(){
                    $(this)
                        .find('div:last')
                        .after($('div:first', this));
                });

        }, 1000);
    }
}
$('button').on('click', function () {
    var direction = $(this).attr('id');
    animateList(direction);
});

// Initial animation
animateList('up');
Run Code Online (Sandbox Code Playgroud)
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

#transformed {
  transform: translateZ(0);
}

#list {
  position: fixed;
  overflow: hidden;
  width: 100%;
  height: 250px;
  background: red;
  padding: 10px;
  margin-top: 100px;
}

#list div {
  display: block;
  height: 30px;
  padding: 10px 10px;
  margin-bottom: 10px;
  background: yellow;
}

.item:last-child {
  margin-bottom: 0px;
}
Run Code Online (Sandbox Code Playgroud)