以下场景:用户正在页面上滚动内容,突然一个元素出现在视口中,其子元素从不同方向飞入屏幕。
一旦元素出现,其子元素就会通过动画在视口中可见,并在离开视口时再次完美消失。文本可能比视口本身大。
各个起始方向可以作为各个元素的属性找到。由于某些事件,位置计算不正确。似乎在正方形的高度和纬度上一切正常。请参阅我在 javascript 代码中的注释。我实际上现在不知道出了什么问题。
请参阅我的小提琴示例代码:https://jsfiddle.net/oqe145tv/23/
那里使用了 jQuery:https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js
<div class="marquee">
<div class="marquee-row" data-position="start">
<div class="marquee-row-data">
<p class="marquee-row-data-text"><span>Mertingen</span></p>
</div>
<div class="marquee-row-data">
<p class="marquee-row-data-text"><span>Praha</span></p>
</div>
<div class="marquee-row-data">
<p class="marquee-row-data-text"><span>Budapest</span></p>
</div>
<div class="marquee-row-data">
<p class="marquee-row-data-text"><span>Bratislava</span></p>
</div>
<div class="marquee-row-data">
<p class="marquee-row-data-text"><span>Das ist ein cooler und langer Test</span></p>
</div>
</div>
<div class="marquee-row" data-position="end">
<div class="marquee-row-data">
<p class="marquee-row-data-text"><span>Günzburg</span></p>
</div>
<div class="marquee-row-data">
<p class="marquee-row-data-text"><span>Wroclaw</span></p>
</div>
<div class="marquee-row-data">
<p class="marquee-row-data-text"><span>Opole</span></p>
</div>
<div class="marquee-row-data">
<p class="marquee-row-data-text"><span>Hanoi</span></p>
</div>
</div>
</div>
body {
padding: 30rem 0;
}
.marquee {
overflow: hidden;
background-color: green;
}
.marquee-row {
position: relative;
display: flex;
width: fit-content;
}
.marquee-row[data-position="end"] {
float: right;
}
.marquee-row-data {
display: flex;
overflow: hidden;
padding: 0.5rem 0;
position: relative;
}
.marquee-row-data:not(:last-child)::after {
content: '/';
color: black;
padding: 0 0.5rem;
}
.marquee-row-data::after,
.marquee-row-data-text>* {
font-size: 4.5rem;
line-height: 5rem;
font-weight: 600;
}
.marquee-row-data-text {
position: relative;
white-space: nowrap;
overflow-x: clip;
}
.marquee-row-data-text span {
color: black;
cursor: default;
}
.marquee-row-data-text a {
color: red;
}
function run() {
const marquees = $('.marquee');
if (marquees.length === 0) return;
const handleSliding = _ => {
$(marquees).each((_, marquee) => {
const rows = $(marquee).find('.marquee-row');
if (rows.length === 0) return;
const handler = entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
$(window).on('scroll.marquee', _ => {
$(rows).each((i, row) => {
const position = $(row).attr('data-position');
if (!position) return;
const elementPositionY = row.getBoundingClientRect().top;
const percentHeight = 100 / window.innerHeight * elementPositionY;
const startPos = 100 / window.innerWidth * $(row).innerWidth() * -1;
// percentHeight = percentHeight < 0 ? 0 : percentHeight > 100 ? 100 : percentHeight;
// fullWidth / window.innerHeight;
// 100 / (fullWidth / (100 / window.innerHeight * elementPositionY));
// 100 / ((fullWidth / 100) * (100 / window.innerHeight * elementPositionY));
// fullWidth / (window.innerHeight + $(marquee).outerHeight())
const fullWidth = window.innerWidth + $(row).innerWidth();
const percentWidth = fullWidth / window.innerHeight;
const percent = startPos + (percentWidth * percentHeight);
$(row).css(position === 'start' ? 'left' : 'right', `${percent}vw`);
});
}).scroll();
} else
$(window).off('scroll.marquee');
});
};
const observer = new IntersectionObserver(handler);
observer.observe(marquee);
});
};
handleSliding();
}
run();
重写完整的代码后,我设法修复它,如下所示:
const run = _ => {
const wrappers = document.querySelectorAll('.wrapper');
if (wrappers.length === 0) return;
document.addEventListener('scroll', _ => {
wrappers.forEach(wrapper => {
const items = wrapper.querySelectorAll('.item');
if (items.length === 0) return;
items.forEach((item, i) => {
if (wrapper.offsetTop > window.scrollY + window.innerHeight || wrapper.offsetTop + wrapper.offsetHeight < window.scrollY) return;
const position = item.getAttribute('data-position');
if (!position) return;
const faktor = 100 / window.innerWidth * ((window.innerWidth + item.offsetWidth) / 100);
const screenHeight = window.innerHeight - item.offsetHeight;
let scrollProgress = 100 - (100 / screenHeight * (item.offsetTop - window.scrollY));
if (scrollProgress > 100) scrollProgress = 100;
if (scrollProgress < 0) scrollProgress = 0;
let startPos = 100 - 100 * faktor;
if (position === 'right')
startPos = 100 * faktor - (100 + (100 * faktor));
const progress = startPos + scrollProgress * faktor;
item.style = `${position}: ${progress}vw`;
});
});
});
};
run();
body {
padding: 1500px 0;
background: #222;
}
.wrapper {
background: orange;
overflow: hidden;
padding: 200px 0;
}
.item {
background: green;
height: 100px;
position: relative;
}
.item:nth-child(1) {
width: 500px;
}
.item:nth-child(2) {
width: 2500px;
}
.item:nth-child(3) {
width: 1000px;
}
.item:nth-child(4) {
width: 750px;
}
.item:nth-child(5) {
width: 1800px;
}
.item:nth-child(6) {
width: 900px;
}
<div class="wrapper">
<div class="item" data-position="left"></div>
<div class="item" data-position="right"></div>
<div class="item" data-position="left"></div>
<div class="item" data-position="left"></div>
<div class="item" data-position="right"></div>
<div class="item" data-position="right"></div>
</div>