当前位置: 首页 > news >正文

vue实现数据栏无缝滚动实现方式-demo

效果 

 方式一

通过实现两个item 进行循环

<!--* @Author: Jackie* @Date: 2023-08-16 21:27:42* @LastEditTime: 2023-08-16 21:41:51* @LastEditors: Jackie* @Description: scroll  水平滚动 - 效果基本满足需求* @FilePath: /vue3-swiper-demo/src/components/scroll/Scroll12.vue* @version: 
-->
<template><div class="ticker-container"><div class="ticker-viewer"><div class="ticker-scroll"><divclass="ticker-scroll-item":key="index"v-for="(item, index) in items"><span v-if="item">{{ item }} ${{ item }}</span></div></div><div class="ticker-scroll"><divclass="ticker-scroll-item":key="index"v-for="(item, index) in items"><span v-if="item">{{ item }} ${{ item }}</span></div></div></div></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const items = ref(Array.from({ length: 26 }, (_, index) => index + 1));
</script><style lang="scss" scoped>
.ticker-container {align-items: center;background: linear-gradient(90deg, #86eef1, #bcff2f 138.82%);display: flex;height: 50px;white-space: nowrap;width: 100%;.ticker-viewer {align-items: center;cursor: pointer;display: flex;height: 100%;overflow: hidden;position: relative;width: 100%;.ticker-scroll {animation-delay: 8s;opacity: 0;animation: tickerScroll 240s linear infinite normal;transform: translateX(0);transition: all linear;will-change: transform, opacity;.ticker-scroll-item {display: inline-block;font-size: 18px;line-height: 22px;color: #fff;padding: 0 24px;}}}
}@keyframes tickerScroll {0% {opacity: 1;transform: translateX(0);}to {opacity: 1;transform: translateX(-100%);}
}@keyframes positionScroll {0% {transform: translateX(3.33333333%);}to {transform: translateX(0);}
}
</style>

方式二

通过实现两个item 进行循环

<!--* @Author: Jackie* @Date: 2023-08-16 21:02:42* @LastEditTime: 2023-08-16 21:42:04* @LastEditors: Jackie* @Description: 过渡 - 通过两次滚动实现 flex  - 效果基本满足需求* @FilePath: /vue3-swiper-demo/src/components/scroll/Scroll11.vue* @version: 
-->
<template><div class="scroll"><div class="price-band-group" ref="group"><divclass="price-band-item DIN-medium":key="index"v-for="(item, index) in items"><span v-if="item">{{ item }} ${{ item }}</span></div></div><div class="price-band-group" ref="group"><divclass="price-band-item DIN-medium":key="index"v-for="(item, index) in items"><span v-if="item">{{ item }} ${{ item }}</span></div></div></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue';const scroller = ref(null);
const group = ref(null);
const timerId = ref(null);
const items = ref(Array.from({ length: 26 }, (_, index) => index + 1));
</script><style lang="scss" scoped>
.scroll {display: flex;overflow: hidden;width: 100%;height: 48px;background: linear-gradient(90deg, #31daff 0.47%, #316bff 100%);padding: 13px 0;box-sizing: border-box;overflow: auto;.price-band-group {display: flex;white-space: nowrap;/* animation: index_loop 100s linear infinite normal;animation-delay: 0.5s; */animation: tickerScroll 240s linear infinite normal;transform: translateX(0);.price-band-item {display: inline-block;font-size: 18px;line-height: 22px;color: #fff;padding: 0 24px;}}&::-webkit-scrollbar {display: none;}
}@keyframes index_loop {0% {transform: translateZ(0);}to {transform: translate3d(-50%, 0, 0);}
}@keyframes tickerScroll {0% {opacity: 1;transform: translateX(0);}to {opacity: 1;transform: translateX(-100%);}
}
</style>

方式三

通过尾部填充重复数据实现

<template><div class="scroll" ref="scroller" :style="style"><div class="price-band-group" v-if="items.length"><divclass="price-band-item DIN-medium"v-for="(item, index) in itemsWithTail":key="index"><span v-if="item !== null"> {{ item }} ${{ item }} </span></div></div></div>
</template><script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue';
const scroller = ref(null);
const timerId = ref(null);
const items = ref(Array.from({ length: 12 }, (_, index) => index + 1));
const pauseAnimate = () => {timerId.value && clearInterval(timerId.value);timerId.value = null;
};
const playAnimate = () => {pauseAnimate();const maxScrollLeft = scroller.value.scrollWidth - scroller.value.clientWidth;console.log(maxScrollLeft);timerId.value = setInterval(() => {if (scroller.value.scrollLeft >= maxScrollLeft) {scroller.value.scrollLeft -= maxScrollLeft;}scroller.value.scrollLeft += 1;}, 33);
};const itemsWithTail = computed(() =>items.value.length >= 10 ? items.value.concat(items.value) : items.value//   items.value.concat(items.value.slice(0, 4))
);onMounted(() => {setTimeout(() => {scroller.value.scrollLeft = 0;playAnimate();}, 100);
});onUnmounted(() => {pauseAnimate();
});
</script><style lang="scss" scoped>
.scroll {width: 100%;height: 48px;background: linear-gradient(90deg, #31daff 0.47%, #316bff 100%);padding: 13px 0;box-sizing: border-box;overflow: hidden;transition: scroll-left 1s ease-in-out; /* 添加过渡效果 */.price-band-group {display: inline-block;white-space: nowrap;.price-band-item {display: inline-block;font-size: 18px;line-height: 22px;color: #fff;padding: 0 24px;}}&::-webkit-scrollbar {display: none;}
}
</style>

方式四

滚动到头后,直接归0

<template><div class="scroll" ref="scroller" :style="style"><div class="price-band-group"><div class="price-band-item DIN-medium" v-for="item in items" :key="item"><span v-if="item"> {{ item }} ${{ item }} </span></div></div></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const scroller = ref(null);
const timerId = ref(null);
const scrollLeftEnd = ref(false);
const items = ref(Array.from({ length: 22 }, (_, index) => index + 1));
const pauseAnimate = () => {timerId.value && clearInterval(timerId.value);timerId.value = null;
};
const playAnimate = () => {pauseAnimate();const maxScrollLeft = scroller.value.scrollWidth - scroller.value.clientWidth;console.log(maxScrollLeft);timerId.value = setInterval(() => {if (scroller.value.scrollLeft >= maxScrollLeft) {scroller.value.scrollLeft -= maxScrollLeft;}scroller.value.scrollLeft += 1;}, 33);
};onMounted(() => {console.log(111);// 必须在100ms后进行,否则计算不准确setTimeout(() => {scroller.value.scrollLeft = 0;playAnimate();}, 100);
});
onUnmounted(() => {pauseAnimate();
});
</script><style lang="scss" scoped>
.scroll {width: 100%;height: 48px;background: linear-gradient(90deg, #31daff 0.47%, #316bff 100%);padding: 13px 0;box-sizing: border-box;overflow: auto;.price-band-group {display: inline-block;white-space: nowrap;.price-band-item {display: inline-block;font-size: 18px;line-height: 22px;color: #fff;padding: 0 24px;}}&::-webkit-scrollbar {display: none;}
}
</style>

方式五

来回滚动方式

<template><div class="scroll" ref="scroller" :style="style"><div class="price-band-group"><div class="price-band-item DIN-medium" v-for="item in 26" :key="item"><span v-if="item"> {{ item.item }} ${{ item }} </span></div></div></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const scroller = ref(null);
const timerId = ref(null);
const scrollLeftEnd = ref(false);
const pauseAnimate = () => {timerId.value && clearInterval(timerId.value);timerId.value = null;
};
const playAnimate = () => {pauseAnimate();const maxScrollLeft = scroller.value.scrollWidth - scroller.value.clientWidth;console.log(maxScrollLeft);timerId.value = setInterval(() => {if (scroller.value.scrollLeft >= maxScrollLeft - 1) {scrollLeftEnd.value = true;}if (scroller.value.scrollLeft <= 1) {scrollLeftEnd.value = false;}if (scrollLeftEnd.value) {scroller.value.scrollTo({top: 0,left: (scroller.value.scrollLeft -= 1),behavior: 'smooth'}); //scrollLeft -= 1;} else {scroller.value.scrollTo({top: 0,left: (scroller.value.scrollLeft += 1),behavior: 'smooth'}); //scrollLeft += 1;}}, 33);
};onMounted(() => {console.log(111);// 必须在100ms后进行,否则计算不准确setTimeout(() => {scroller.value.scrollLeft = 0;playAnimate();}, 100);
});
onUnmounted(() => {pauseAnimate();
});
</script><style lang="scss" scoped>
.scroll {width: 100%;height: 48px;background: linear-gradient(90deg, #31daff 0.47%, #316bff 100%);padding: 13px 0;box-sizing: border-box;overflow: auto;.price-band-group {display: inline-block;white-space: nowrap;.price-band-item {display: inline-block;font-size: 18px;line-height: 22px;color: #fff;padding: 0 24px;}}&::-webkit-scrollbar {display: none;}
}
</style>

方式六

scroll滚动 - 循环滚动,不超出不滚动

<!--* @Author: Jackie* @Date: 2023-08-17 10:55:21* @LastEditTime: 2023-08-17 11:39:17* @LastEditors: Jackie* @Description: scroll滚动 - 循环滚动,不超出不滚动* @FilePath: /vue3-swiper-demo/src/components/scroll/Scroll13.vue* @version: 
-->
<template><div class="ticker-container"><div class="ticker-viewer" ref="scrollWiewer"><divclass="ticker-scroll"ref="scrollContainer":class="{ 'scroll-animation': !shouldScroll }":style="{ animationDuration: animationDuration }"><divclass="ticker-scroll-item":key="index"v-for="(item, index) in items"><span v-if="item">{{ item }} ${{ item }}</span></div></div><divclass="ticker-scroll"v-if="shouldScroll":style="{ animationDuration: animationDuration }"><divclass="ticker-scroll-item":key="index"v-for="(item, index) in items"><span v-if="item">{{ item }} ${{ item }}</span></div></div></div></div>
</template><script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue';const items = ref(Array.from({ length: 26 }, (_, index) => index + 1));
const shouldScroll = ref(false);
const scrollContainer = ref(null);
const scrollWiewer = ref(null);// 计算动画持续时间
const animationDuration = computed(() => {const itemCount = items.value.length;// 根据元素数量调整倍数const durationMultiplier = 2; // 调整这个值以适应您的需求return `${itemCount * durationMultiplier}s`;
});onMounted(() => {const wiewerWidth = scrollWiewer.value.offsetWidth;const containerWidth = scrollContainer.value.offsetWidth;const contentWidth = scrollContainer.value.scrollWidth;console.log(containerWidth, wiewerWidth, containerWidth > wiewerWidth);shouldScroll.value = containerWidth > wiewerWidth;
});onUnmounted(() => {shouldScroll.value = false;
});
</script><style lang="scss" scoped>
.ticker-container {align-items: center;background: linear-gradient(90deg, #86eef1, #bcff2f 138.82%);display: flex;height: 50px;white-space: nowrap;width: 100%;.ticker-viewer {align-items: center;cursor: pointer;display: flex;height: 100%;overflow: hidden;position: relative;width: 100%;.ticker-scroll {/* opacity: 0; */transition: all linear;will-change: transform, opacity;/* animation: tickerScroll 20s linear infinite normal; */animation-name: tickerScroll;animation-timing-function: linear;animation-iteration-count: infinite;animation-direction: normal;transform: translateX(0);/* 没有超出不滚动 */&.scroll-animation {animation: none; // stopScroll 1s linear 1 normal;transform: translateX(0);}.ticker-scroll-item {display: inline-block;font-size: 18px;line-height: 22px;color: #fff;padding: 0 24px;}}}
}@keyframes tickerScroll {0% {opacity: 1;transform: translateX(0);}to {opacity: 1;transform: translateX(-100%);}
}@keyframes stopScroll {0% {transform: translateX(0);}
}@keyframes positionScroll {0% {transform: translateX(3.33333333%);}to {transform: translateX(0);}
}
</style>


http://www.mrgr.cn/news/33995.html

相关文章:

  • Springboot 日志使用
  • Python 生态与社区动态
  • spring boot中虚拟线程性能探讨
  • 如何选购笔记本电脑?要看哪些参数?
  • 【测试】软件测试和开发的区别
  • (11)(2.1.2) DShot ESCs(三)
  • VLDB 2024 圆桌会议回顾:展望物联网与 AI 时代的时序数据库
  • openstack中的rabbitmq
  • C# 路径算法之Dijkstra算法
  • 医疗医药随货清单打印软件下载 佳易王药品批发出库单打印管理系统操作教程
  • 【幸运数 / A】
  • react中解析markdown文本
  • 机器学习与深度学习的区别:深入理解与应用场景
  • 控糖新食尚,糖尿病患者的美味与健康同行!
  • 【MYSQL】聚合查询、分组查询、联合查询
  • 【OSS安全最佳实践】对OSS内身份证图片中身份证号进行脱敏
  • 了解你的GPU:深入探讨AMD SMI
  • 教师管理系统小程序+ssm论文源码调试讲解
  • MyBatis-Plus 实体类注解
  • 网站建设中,sitemap是什么,有什么作用