【问题标题】:How to create vertically scrolling divs in jquery?如何在 jquery 中创建垂直滚动的 div?
【发布时间】:2019-05-04 14:54:32
【问题描述】:

我正在使用带有动画的 jquery 创建垂直自动滚动的 div...我已经完成了它的创建,但唯一的问题是当我将窗口向下滚动到 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);
* {
  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;
}
<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>

【问题讨论】:

  • 那么你想要在 div 中有一个滚动条还是不想要“循环”效果(在第 10 项之后添加第 1 项?)
  • 不先生..我的问题是,当我在滚动列表 div 中间向下滚动窗口时,窗口(文档的主体)向上滚动,我不想要这个东西跨度>
  • 在 Firefox 或 IE 中不会发生,但在 Chrome 中会发生。
  • @Shikkediel ... 是的,先生,对于此类问题,chrome 有什么可能的解决方案吗?
  • 我正在研究它,不是我熟悉的东西。

标签: javascript jquery html css


【解决方案1】:

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

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

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

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

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

然后我查看了position: fixed,它确实有效(因为它基本上位于所有内容之上) - 这显然不会有效,因为您希望列表随页面滚动!那么,我们该如何解决呢?

transform 救援!

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

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

CSS 更改是直截了当的,如下所示:

#transformed { transform: translateZ(0); }
#list { position: fixed; }

就是这样!查看下面的 sn-p 以了解它的实际效果。

setInterval(function(){
  $('#list').stop().animate({scrollTop:40}, 400, 'swing', function(){
    $(this).find('div:last').after($('div:first', this));
  });
}, 1000);
* {
  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;
}
<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>

2) 滑动图层

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

我不会操纵scrollTop,而是研究一种“滑动”层方法(使用transformY 或top)。

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

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

无论如何,希望这对您有所帮助,position: fixed 方法对您有用:)

编辑

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

这是一个演示的 sn-p:

setInterval(function(){
    $('#list')
        .find('div:first')
        .before($('div:last', '#list'))
        .end()
        .scrollTop(40)
        .stop()
    .animate({scrollTop:0}, 400, 'swing');
}, 1000);
* {
  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;
}
<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>

编辑#2:

关于向上/向下按钮,您可以通过组合我们目前编写的两个脚本轻松实现!这是两个在单击时向上/向下动画的 sn-ps(第一个会在您每次单击时滚动,第二个 sn-p 会改变动画方向):

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);
});
* {
  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;
}
<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>

还有改变方向的sn-p:

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');
* {
  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;
}
<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>

【讨论】:

  • 谢谢您的解决方案,它解决了我的问题,但还有一个问题是它向上滚动但如何向下滚动?
  • 嗨@Inam,很高兴听到它解决了您的问题。我已经更新了答案以包括向下滚动:)
  • 谢谢先生,但是如何使它与向上和向下按钮一起工作?
  • 嗨@Inam,我已经更新了答案以包括向上/向下按钮。很简单,您将我们迄今为止编写的两个脚本结合起来,根据您单击的按钮,它将调用“向上”逻辑或“向下”逻辑。我添加了两个不同的示例 - 一个在您单击时会生成一次动画,另一个在您单击时会更改自动滚动的方向。希望这会有所帮助!
  • 谢谢你先生..这是我需要的:)
【解决方案2】:

我已将您的内部 div 转换为无序列表。我最初添加了一个overflow-y:scroll,这也有效,但在看到您的评论后将其更改为overflow-y:hidden。我发现但两者都有效。如果您向下滚动页面然后向上滚动,它不会“重新开始”(除非它有时间遍历所有 10 个列表项)。您可能需要调整 css/box 高度以获得底部的红色边框,但我将把它留给您

希望对你有帮助

溢出隐藏:

setInterval(function() {
  $('#ulList').stop().animate({
    scrollTop: 40
  }, 400, 'swing', function() {
    $(this).scrollTop(0).find('li:last').after($('li:first', this));
  });
}, 1000);
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

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

#list ul {
  margin: 10px 10px;
  padding: 10px 0px;
}

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

.item:last-child {
  margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
  <ul id="ulList">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
    <li>Item 6</li>
    <li>Item 7</li>
    <li>Item 8</li>
    <li>Item 9</li>
    <li>Item 10</li>
  </ul>

</div>

溢出:滚动

setInterval(function() {
  $('#ulList').stop().animate({
    scrollTop: 40
  }, 400, 'swing', function() {
    $(this).scrollTop(0).find('li:last').after($('li:first', this));
  });
}, 1000);
* {
  box-sizing: border-box;
}

body {
  height: 1000px;
}

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

#list ul {
  margin: 10px 10px;
  padding: 10px 0px;
}

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

.item:last-child {
  margin-bottom: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
  <ul id="ulList">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
    <li>Item 6</li>
    <li>Item 7</li>
    <li>Item 8</li>
    <li>Item 9</li>
    <li>Item 10</li>
  </ul>

</div>

【讨论】:

  • 顺便说一句,我不是“先生”,但我很欣赏礼貌的态度:)
  • 哦,对不起,谢谢...但是仍然有问题尝试将您的窗口(主文档窗口滚动条)定位在滚动列表的中间 divs 主文档窗口滚动条自动向上移动随着滚动的 li 向上移动.. 你不明白我的问题 ma'm
  • @Inam 哦,我现在知道你的意思了。发生这种情况是因为它在不断地制作动画。您可能可以修复 ul 的顶部位置,这可能是一种解决方法(但由于我没有尝试过,我不知道它会如何影响动画)。虽然很棘手。
  • 是的,女士……它在 Firefox 中运行良好,但在 chrome 和 Opera 中却不行好吧,但这也给了我同样的问题..可能是浏览器问题。
  • 如果它在其他浏览器上运行,我会尝试禁用 Chrome 中的扩展并重试。你试过使用 position:sticky; 吗?
猜你喜欢
  • 2011-01-18
  • 2020-02-04
  • 1970-01-01
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
相关资源
最近更新 更多