在 vanilla/pure JS 中无限滚动而不产生间隙
make infinite scroll in vanilla/pure JS without creating gap
当一个循环完成后,你就可以看到差距了。我想摆脱它。
它会一个接一个地循环而不会产生间隙。
谁能给我一些时间来解决这个问题..
const scrollAnimation = (function() {
let element = null;
// let obejct = {};
let scroller = true;
let scrollSpeed = 0;
let parentElement = null;
let childElement = null;
let viewHeight = 0;
const toggleScrollEvent = function(e) {
scroller = (e.type == 'mouseenter') ? false : true;
}
const setProperty = function(element, obejct) {
viewHeight = document.querySelector(element).clientHeight
scrollSpeed = obejct.scrollSpeed;
// create child element
childElement = document.createElement('div');
childElement.id = 'childElement';
// append scroll content to child element
let items = document.querySelectorAll(element + ' .item');
items.forEach(function(item) {
childElement.appendChild(item)
});
// append child element to parent element
element = document.querySelector(element);
parentElement = element.appendChild(childElement)
// set child element top property value manually 200px
// let hg = childElement.getBoundingClientRect();
childElement.style.top = viewHeight + 'px';
parentElement.addEventListener('mouseenter', toggleScrollEvent);
parentElement.addEventListener('mouseleave', toggleScrollEvent);
}
const scrollEelement = function() {
let posY = parseInt(childElement.style.top);
if (scroller) {
if (posY + childElement.clientHeight > 0) {
childElement.style.top = posY - scrollSpeed + 'px'
} else {
childElement.style.top = viewHeight + 'px';
}
}
}
setInterval(scrollEelement, 50)
return {
init: function(element, obejct) {
setProperty(element, obejct)
}
}
})([]);
window.addEventListener("DOMContentLoaded", function() {
scrollAnimation.init('#parentElement', {
scrollSpeed: 5,
});
})
*,
*::after,
*::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body,
html {
margin: 0;
padding: 0;
}
#parentElement {
position: relative;
width: 400px;
background: #eeeeee;
height: 200px;
overflow: hidden;
border: 2px solid royalblue;
}
#parentElement #childElement {
padding: 10px;
position: absolute;
width: 100%;
top: 0;
left: 0;
}
<div id="parentElement">
<h1 class="item">Start</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item" style="background: orangered;">End</h1>
</div>
在你的 scrollEelement 函数中,你检查是否需要重新开始滚动,你可以检查当前顶部位置是否小于“.item”之一的高度负值 divs。如果是,请从 div 中删除第一项并在末尾再次附加它。由于这些 div 的高度为 45px,一旦子元素 div 的顶部小于 -45,顶部的“.item”div 就不再可见,可以在 div 的末尾被删除和替换 - 并调整子元素的顶部以添加回 45px 以用于删除的项目。所以:
const scrollAnimation = (function(){
let element = null;
// let obejct = {};
let scroller = true;
let scrollSpeed = 0;
let parentElement= null;
let childElement = null;
let viewHeight = 0;
const toggleScrollEvent = function (e){
scroller = (e.type == 'mouseenter') ? false : true;
}
const setProperty = function(element,obejct){
viewHeight = document.querySelector(element).clientHeight
scrollSpeed = obejct.scrollSpeed;
// create child element
childElement = document.createElement('div');
childElement.id = 'childElement';
// append scroll content to child element
let items = document.querySelectorAll(element+ ' .item');
items.forEach(function(item){
childElement.appendChild(item)
});
// append child element to parent element
element = document.querySelector(element);
parentElement = element.appendChild(childElement)
// set child element top property value manually 200px
// let hg = childElement.getBoundingClientRect();
childElement.style.top = viewHeight+ 'px';
parentElement.addEventListener('mouseenter',toggleScrollEvent);
parentElement.addEventListener('mouseleave',toggleScrollEvent);
}
const scrollEelement = function(){
let posY = parseInt(childElement.style.top);
// Get the first child div
let firstDiv = childElement.querySelectorAll(".item")[0];
// Check its height
let firstDivHeight = firstDiv.clientHeight;
// If we are scrolling...
if(scroller){
// Find out where the scroll would move to
let tmppos = posY - scrollSpeed;
// If it is higher than the height of the first div
if (tmppos < 0 - firstDivHeight) {
// remove the first div
childElement.removeChild(firstDiv);
// .. and append it to the end
childElement.appendChild(firstDiv);
// .. and do the scroll
childElement.style.top = (tmppos + firstDivHeight) + "px";
} else {
// otherwise, just do the scroll
childElement.style.top = tmppos + "px";
}
}
}
setInterval(scrollEelement,10)
return {
init:function(element,obejct){
setProperty(element,obejct)
}
}
})([]);
window.addEventListener("DOMContentLoaded",function(){
scrollAnimation.init('#parentElement',{
scrollSpeed:1,
});
})
*,*::after,*::before{
box-sizing: border-box;
margin: 0;
padding: 0;
}
body,html{
margin: 0;
padding: 0;
}
#parentElement{
position: relative;
width: 400px;
background: #eeeeee;
height: 200px;
overflow: hidden;
border: 2px solid royalblue;
}
#parentElement #childElement{
padding: 10px;
position: absolute;
width: 100%;
top: 0;
left: 0;
}
<div id="parentElement">
<h1 class="item">Start</h1>
<h1 class="item">Mid................<br>..............on two lines</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item" style="background: orangered;">End</h1>
</div>
这是一个主要使用 css 动画的解决方案。
const containerElem = document.querySelector('.container');
const contentElem = document.querySelector('.content');
const contentCloneElem = contentElem.cloneNode(true);
containerElem.appendChild(contentCloneElem);
const pxPerSec = 100;
const contentHeight = contentElem.clientHeight;
containerElem.style.animationDuration = `${contentHeight / pxPerSec}s`;
.infiniteScroll {
border: 2px solid blue;
height: 150px;
overflow: hidden;
}
.container {
border: 2px solid red;
}
.content {
border: 1px solid green;
}
@keyframes changePos {
from {
transform: translateY(0px);
}
to {
transform: translateY(-50%);
}
}
.container {
animation-duration: 5s;
animation-timing-function: linear;
animation-name: changePos;
animation-iteration-count: infinite;
animation-direction: normal;
}
.container:hover {
animation-play-state: paused;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Infinite Scroll</title>
</head>
<body>
<div class="infiniteScroll">
<div class="container">
<div class="content">
<h1 class="item">Start</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item" style="background: orangered;">End</h1>
</div>
</div>
</div>
</body>
</html>
当一个循环完成后,你就可以看到差距了。我想摆脱它。 它会一个接一个地循环而不会产生间隙。
谁能给我一些时间来解决这个问题..
const scrollAnimation = (function() {
let element = null;
// let obejct = {};
let scroller = true;
let scrollSpeed = 0;
let parentElement = null;
let childElement = null;
let viewHeight = 0;
const toggleScrollEvent = function(e) {
scroller = (e.type == 'mouseenter') ? false : true;
}
const setProperty = function(element, obejct) {
viewHeight = document.querySelector(element).clientHeight
scrollSpeed = obejct.scrollSpeed;
// create child element
childElement = document.createElement('div');
childElement.id = 'childElement';
// append scroll content to child element
let items = document.querySelectorAll(element + ' .item');
items.forEach(function(item) {
childElement.appendChild(item)
});
// append child element to parent element
element = document.querySelector(element);
parentElement = element.appendChild(childElement)
// set child element top property value manually 200px
// let hg = childElement.getBoundingClientRect();
childElement.style.top = viewHeight + 'px';
parentElement.addEventListener('mouseenter', toggleScrollEvent);
parentElement.addEventListener('mouseleave', toggleScrollEvent);
}
const scrollEelement = function() {
let posY = parseInt(childElement.style.top);
if (scroller) {
if (posY + childElement.clientHeight > 0) {
childElement.style.top = posY - scrollSpeed + 'px'
} else {
childElement.style.top = viewHeight + 'px';
}
}
}
setInterval(scrollEelement, 50)
return {
init: function(element, obejct) {
setProperty(element, obejct)
}
}
})([]);
window.addEventListener("DOMContentLoaded", function() {
scrollAnimation.init('#parentElement', {
scrollSpeed: 5,
});
})
*,
*::after,
*::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body,
html {
margin: 0;
padding: 0;
}
#parentElement {
position: relative;
width: 400px;
background: #eeeeee;
height: 200px;
overflow: hidden;
border: 2px solid royalblue;
}
#parentElement #childElement {
padding: 10px;
position: absolute;
width: 100%;
top: 0;
left: 0;
}
<div id="parentElement">
<h1 class="item">Start</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item" style="background: orangered;">End</h1>
</div>
在你的 scrollEelement 函数中,你检查是否需要重新开始滚动,你可以检查当前顶部位置是否小于“.item”之一的高度负值 divs。如果是,请从 div 中删除第一项并在末尾再次附加它。由于这些 div 的高度为 45px,一旦子元素 div 的顶部小于 -45,顶部的“.item”div 就不再可见,可以在 div 的末尾被删除和替换 - 并调整子元素的顶部以添加回 45px 以用于删除的项目。所以:
const scrollAnimation = (function(){
let element = null;
// let obejct = {};
let scroller = true;
let scrollSpeed = 0;
let parentElement= null;
let childElement = null;
let viewHeight = 0;
const toggleScrollEvent = function (e){
scroller = (e.type == 'mouseenter') ? false : true;
}
const setProperty = function(element,obejct){
viewHeight = document.querySelector(element).clientHeight
scrollSpeed = obejct.scrollSpeed;
// create child element
childElement = document.createElement('div');
childElement.id = 'childElement';
// append scroll content to child element
let items = document.querySelectorAll(element+ ' .item');
items.forEach(function(item){
childElement.appendChild(item)
});
// append child element to parent element
element = document.querySelector(element);
parentElement = element.appendChild(childElement)
// set child element top property value manually 200px
// let hg = childElement.getBoundingClientRect();
childElement.style.top = viewHeight+ 'px';
parentElement.addEventListener('mouseenter',toggleScrollEvent);
parentElement.addEventListener('mouseleave',toggleScrollEvent);
}
const scrollEelement = function(){
let posY = parseInt(childElement.style.top);
// Get the first child div
let firstDiv = childElement.querySelectorAll(".item")[0];
// Check its height
let firstDivHeight = firstDiv.clientHeight;
// If we are scrolling...
if(scroller){
// Find out where the scroll would move to
let tmppos = posY - scrollSpeed;
// If it is higher than the height of the first div
if (tmppos < 0 - firstDivHeight) {
// remove the first div
childElement.removeChild(firstDiv);
// .. and append it to the end
childElement.appendChild(firstDiv);
// .. and do the scroll
childElement.style.top = (tmppos + firstDivHeight) + "px";
} else {
// otherwise, just do the scroll
childElement.style.top = tmppos + "px";
}
}
}
setInterval(scrollEelement,10)
return {
init:function(element,obejct){
setProperty(element,obejct)
}
}
})([]);
window.addEventListener("DOMContentLoaded",function(){
scrollAnimation.init('#parentElement',{
scrollSpeed:1,
});
})
*,*::after,*::before{
box-sizing: border-box;
margin: 0;
padding: 0;
}
body,html{
margin: 0;
padding: 0;
}
#parentElement{
position: relative;
width: 400px;
background: #eeeeee;
height: 200px;
overflow: hidden;
border: 2px solid royalblue;
}
#parentElement #childElement{
padding: 10px;
position: absolute;
width: 100%;
top: 0;
left: 0;
}
<div id="parentElement">
<h1 class="item">Start</h1>
<h1 class="item">Mid................<br>..............on two lines</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item" style="background: orangered;">End</h1>
</div>
这是一个主要使用 css 动画的解决方案。
const containerElem = document.querySelector('.container');
const contentElem = document.querySelector('.content');
const contentCloneElem = contentElem.cloneNode(true);
containerElem.appendChild(contentCloneElem);
const pxPerSec = 100;
const contentHeight = contentElem.clientHeight;
containerElem.style.animationDuration = `${contentHeight / pxPerSec}s`;
.infiniteScroll {
border: 2px solid blue;
height: 150px;
overflow: hidden;
}
.container {
border: 2px solid red;
}
.content {
border: 1px solid green;
}
@keyframes changePos {
from {
transform: translateY(0px);
}
to {
transform: translateY(-50%);
}
}
.container {
animation-duration: 5s;
animation-timing-function: linear;
animation-name: changePos;
animation-iteration-count: infinite;
animation-direction: normal;
}
.container:hover {
animation-play-state: paused;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Infinite Scroll</title>
</head>
<body>
<div class="infiniteScroll">
<div class="container">
<div class="content">
<h1 class="item">Start</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item">Mid</h1>
<h1 class="item" style="background: orangered;">End</h1>
</div>
</div>
</div>
</body>
</html>