我的无限选取框动画遇到问题。每当到达终点时,它都不会平滑地过渡回起点,而是突然重新开始。
const scrollers = document.querySelectorAll(".services-brand");
if (!window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
addScrolling();
}
function addScrolling() {
scrollers.forEach((scroller) => {
scroller.setAttribute("data-animated", true);
const scrollerInner = scroller.querySelector('.scroller__inner')
const scrollerContent = Array.from(scrollerInner.children);
scrollerContent.forEach((item) => {
const duplicatedItem = item.cloneNode(true);
duplicatedItem.setAttribute("aria-hidden", true);
scrollerInner.appendChild(duplicatedItem);
})
});
}
section.services-brand {
width: 100%;
background: white;
position: relative;
margin-top: -100px;
}
.services-brand[data-animated="true"] {
overflow: hidden;
}
.services-brand[data-animated="true"] .s-brand-wrapper {
flex-wrap: nowrap;
}
.s-brand-wrapper {
display: flex;
flex-wrap: wrap;
align-items: center;
padding: 20px 0px;
animation: brandScroller 5s linear infinite;
}
.s-brand-block span {
font-size: 20px;
font-family: var(--main-hard-font);
font-weight: 800;
color: var(--black-main-clr);
}
@keyframes brandScroller {
0% {
transform: translateX(0%);
}
100% {
transform: translateX(-100%);
}
}
.s-brand-block {
display: flex;
align-items: center;
gap: 5px;
justify-content: center;
min-width: fit-content;
margin-right: 50px;
padding-right: 10px;
}
.s-brand-block img {
height: 50px;
}
<section class="services-brand">
<div class="s-brand-wrapper scroller__inner">
<div class="s-brand-block">
<img src="{{ asset('images/3d-icons/web-development.png') }}" alt="web development">
<span>Web Development</span>
</div>
<div class="s-brand-block">
<img src="{{ asset('images/3d-icons/marketing.png') }}" alt="Digital Marketing">
<span>Digital Marketing</span>
</div>
<div class="s-brand-block">
<img src="{{ asset('images/3d-icons/content-creation.png') }}" alt="Content Creation">
<span>Content Creation</span>
</div>
<div class="s-brand-block">
<img src="{{ asset('images/3d-icons/design.png') }}" alt="Design/Brending">
<span>Design/Brending</span>
</div>
<div class="s-brand-block">
<img src="{{ asset('images/3d-icons/seo.png') }}" alt="Seo">
<span>SEO</span>
</div>
<div class="s-brand-block">
<img src="{{ asset('images/3d-icons/ux-ui.png') }}" alt="UX/UI">
<span>UX/UI</span>
</div>
</div>
</section>
我尝试调整动画属性,例如
animation-direction
,以在选取框动画的结束和开始之间创建更平滑的过渡。然而,尽管我做出了努力,动画仍然突然重新启动,没有达到预期的无缝循环。
添加的
s-brand-block
并不完全是 s-brand-wrapper
宽度的两倍(我不明白为什么) - 您可以通过添加添加的 div 的宽度,然后计算动画结束的百分比来解决这个问题翻译值 - 我为此使用了一个名为 --perc
的 CSS 变量
但是,您必须等待图像加载后才能执行此操作。另外,执行此计算时需要考虑右边距
注意:我根据 Mehdi 对您问题的编辑使用了外部图像(尽管他的编辑已损坏)
另请注意
margin-top:-100px
阻止输出在代码片段中可见
const scrollers = document.querySelectorAll(".services-brand");
if (!window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
addScrolling();
}
function imagePromise(item) {
const img = item.querySelector('img')
return new Promise((resolve, reject) => {
img.addEventListener('load', () => resolve(item.getBoundingClientRect().width));
img.addEventListener('error', reject);
});
}
function addScrolling() {
scrollers.forEach((scroller) => {
scroller.setAttribute("data-animated", true);
const scrollerInner = scroller.querySelector('.scroller__inner')
const scrollerContent = Array.from(scrollerInner.children);
const promises = scrollerContent.map((item) => {
const duplicatedItem = item.cloneNode(true);
duplicatedItem.setAttribute("aria-hidden", true);
scrollerInner.appendChild(duplicatedItem);
return imagePromise(duplicatedItem);
});
Promise.all(promises).then((v) => {
// the `50` below is your margin-right in .s-brand-block
const tot = v.reduce((acc, width) => acc + width + 50, 0);
const perc = tot/scrollerInner.getBoundingClientRect().width * 100;
scroller.style.setProperty("--perc", `-${perc}%`);
})
});
}
section.services-brand {
width: 100%;
background: white;
position: relative;
margin-top: 0px;
}
.services-brand[data-animated="true"] {
overflow: hidden;
}
.services-brand[data-animated="true"] .s-brand-wrapper {
flex-wrap: nowrap;
}
.s-brand-wrapper {
display: flex;
flex-wrap: wrap;
align-items: center;
padding: 20px 0px;
animation: brandScroller 5s linear infinite;
}
.s-brand-block span {
font-size: 20px;
font-family: var(--main-hard-font);
font-weight: 800;
color: var(--black-main-clr);
}
@keyframes brandScroller {
0% {
transform: translateX(0%);
}
100% {
transform: translateX(var(--perc));
}
}
.s-brand-block {
display: flex;
align-items: center;
gap: 5px;
justify-content: center;
min-width: fit-content;
margin-right: 50px;
padding-right: 10px;
}
.s-brand-block img {
height: 50px;
}
<section class="services-brand">
<div class="s-brand-wrapper scroller__inner">
<div class="s-brand-block">
<img src="https://picsum.photos/id/9/5000/3269.jpg" alt="web development">
<span>Web Development</span>
</div>
<div class="s-brand-block">
<img src="https://picsum.photos/id/7/4728/3168.jpg" alt="Digital Marketing">
<span>Digital Marketing</span>
</div>
<div class="s-brand-block">
<img src="https://picsum.photos/id/4/5000/3333.jpg" alt="Content Creation">
<span>Content Creation</span>
</div>
<div class="s-brand-block">
<img src="https://picsum.photos/id/20/3670/2462.jpg" alt="Design/Brending">
<span>Design/Brending</span>
</div>
<div class="s-brand-block">
<img src="https://picsum.photos/id/1/5000/3333.jpg" alt="Seo">
<span>SEO</span>
</div>
<div class="s-brand-block">
<img src="https://picsum.photos/id/48/5000/3333.jpg" alt="UX/UI">
<span>UX/UI</span>
</div>
</div>
</section>