#javascript #animation #scroll #scrollview #infinite-scroll
#javascript #Анимация #прокрутка #scrollview #бесконечная прокрутка
Вопрос:
когда один цикл завершен, вы можете увидеть пробел.. Я хочу избавиться от этого. он будет повторять цикл один за другим без создания разрыва.
кто-нибудь может дать мне несколько раз, чтобы решить эту проблему..
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>
Ответ №1:
В вашей функции scrollEelement, где вы проверяете, нужно ли перезапускать прокрутку, вы можете проверить, является ли текущая верхняя позиция меньше отрицательного значения высоты в одном из разделов «.item». Если это так, удалите первый элемент из div и добавьте его снова в конце. Поскольку эти divs имеют высоту 45 пикселей, как только вершина дочернего элемента div меньше -45, верхний элемент div «.item» больше не виден и может быть удален и заменен в конце div — и отрегулируйте вершину дочернего элемента, чтобы добавить обратно 45 пикселей дляудаленный элемент. Итак:
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>
Комментарии:
1. почему он мерцает? (анимация не гладкая)
2. Это зависит от времени / длины прокрутки. Прокрутка скачет на 5 пикселей каждые 50 мс. Если я изменяю их на 1px каждые 10 мс (т. Е. На 1/5 скорости, но в 5 раз быстрее), мерцания не будет.
3. @Gad На самом деле, также может показаться, что высота разделов «.item» отличается в разных браузерах. Я обновил ответ, чтобы установить высоту в 45 пикселей.
4.
.item
проблема с высотой… если я добавлю еще одну строку содержимого. это не работает …5. Я обновил свой ответ, чтобы проверить высоту первого div и скорректировать ее на основе этого вместо фиксированного значения 45 пикселей. Стиль css, который задает высоту, больше не требуется, поэтому он был удален. Кроме того, теперь нет необходимости сохранять код viewHeight , поскольку divs будут непрерывно прокручивать и обновлять свой собственный порядок, поэтому нам никогда не нужно будет настраивать верх вручную.
Ответ №2:
Вот решение, использующее в основном анимацию 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>