前端开发攻略---用Vue实现无限滚动的几种方法
目录
1、原理
2、使用CSS动画
代码:
3、使用JS实现
代码:
1、原理
复制内容:将需要滚动的内容复制一次,并将这些副本放置在原始内容的后面。这样,当用户滚动到内容的末尾时,就会无缝地切换回到内容的起始位置。
动画滚动:使用 CSS 或 JavaScript 动画来滚动内容。通常,通过改变元素的位置(例如使用
transform
属性的translate
函数)来实现滚动效果。无限循环:当滚动到最后一个复制的内容时,将滚动位置重新设置为内容的起始位置,以创建无限循环的效果。这通常需要检测滚动位置,并在必要时进行调整。
控制滚动:根据用户的交互(例如鼠标移入/移出、滚动等),控制滚动的开始和暂停。这通常涉及使用事件处理程序来监听用户的交互,并相应地调整滚动的状态。
2、使用CSS动画
优点:
- 性能优化: CSS 动画通常会通过浏览器的硬件加速来执行,因此在性能方面可能更有效率。
- 简单易用: 使用 CSS 实现无限滚动通常比使用 JavaScript 更简单,并且可以通过几行 CSS 代码就能实现基本的效果。
- 响应式设计: CSS 可以轻松实现响应式设计,使得滚动效果在不同设备上具有一致的表现。
- 动画流畅性: 使用 CSS 实现的动画通常更加平滑,因为浏览器会根据自身的渲染节奏来处理动画效果。
缺点:
- 功能受限: 使用 CSS 实现的滚动效果通常比较基础,功能上受到一定的限制,例如无法实现复杂的动态交互或逻辑控制。
- 浏览器兼容性: 某些高级的 CSS 特性可能不被一些旧版本的浏览器所支持,这可能会导致在一些浏览器上无法正常显示滚动效果。
- 难以调试: 对于复杂的 CSS 动画效果,调试起来可能相对困难,特别是涉及到交互逻辑时。
- 性能消耗: 虽然 CSS 动画通常有较好的性能,但对于复杂的动画效果,可能会引起页面的重绘和重排,导致性能下降。
难受的点:当滚动容器内的元素使用了margin值,动画每结束一次就会抖动一次
代码:
<template><div class="aaa"><div class="box"><ul><li v-for="item in 2"><div></div><div></div><div></div><div></div><div></div></li></ul></div></div> </template><script setup> import { ref, reactive } from 'vue'</script><style scoped lang="scss"> .aaa{display: flex;justify-content: center;align-items: center;height: 100vh;.box {width: 1050px;height: 300px;overflow: hidden;ul {width: 200%;height: 100%;animation: scroll 2s linear infinite;& > li {width: 1050px;background-color: rgb(255, 255, 255);height: 100%;float: left;list-style: none;display: flex;& > div {width: 200px;height: 100%;margin-right: 10px;}& > div:nth-child(1) {background-color: saddlebrown;}& > div:nth-child(2) {background-color: rgb(238, 254, 0);}& > div:nth-child(3) {background-color: rgb(34, 255, 5);}& > div:nth-child(4) {background-color: rgb(10, 194, 235);}& > div:nth-child(5) {background-color: rgb(50, 9, 215);}}}ul:hover {animation-play-state: paused;}@keyframes scroll {0% {transform: translateX(0);}100% {transform: translateX(-780px);}}} } </style>
3、使用JS实现
优点:
- 灵活性: 使用 JavaScript 实现无限滚动效果可以更灵活地控制动画的行为,包括速度、加速度、缓动效果等,以及根据用户交互进行动态调整。
- 功能丰富: JavaScript 提供了丰富的 API 和库,可以实现复杂的交互效果和逻辑控制,使得滚动效果更具创意和个性化。
- 兼容性: JavaScript 可以在几乎所有现代浏览器中运行,因此更具有跨浏览器兼容性。
- 调试方便: 使用 JavaScript 编写的动画代码通常更易于调试,因为可以通过控制台输出、断点调试等方式进行调试。
缺点:
- 性能消耗: JavaScript 动画可能会消耗更多的 CPU 和内存资源,尤其是对于复杂的动画效果或需要频繁计算的情况。
- 编码复杂度: 相对于使用 CSS 实现,使用 JavaScript 实现动画通常需要更多的编码工作,因为需要处理更多的逻辑和交互细节。
- 性能不稳定: 由于 JavaScript 是单线程执行的,当 JavaScript 代码执行时间过长或执行过程中阻塞了主线程,可能会导致页面卡顿或动画不流畅的问题。
- 兼容性问题: 某些低版本或旧版浏览器可能不支持或支持不完整某些 JavaScript 特性,导致在这些浏览器上无法正常运行动画效果。
代码:
<template><div class="aaa"><div class="box"><ul ref="ulDom" @mouseenter="pause" @mouseleave="resume"><li v-for="item in 2"><div></div><div></div><div></div><div></div><div></div></li></ul></div></div> </template><script setup> import { ref, onMounted } from 'vue' const ulDom = ref(null) let animationId = null let isPaused = falseonMounted(() => {animation() }) const pause = () => {cancelAnimationFrame(animationId)isPaused = true }const resume = () => {if (!isPaused) returnanimationId = requestAnimationFrame(animation)isPaused = false } let position = 0 const animation = () => {const ulWidth = ulDom.value.offsetWidthconst animate = () => {position -= 10if (position <= -(ulWidth / 2)) {position = 0}ulDom.value.style.transform = `translateX(${position}px)`animationId = requestAnimationFrame(animate)}animate() } </script><style scoped lang="scss"> .aaa{display: flex;justify-content: center;align-items: center;height: 100vh;.box {width: 1050px;height: 300px;overflow: hidden;ul {width: 200%;height: 100%;& > li {width: 1050px;background-color: rgb(255, 255, 255);height: 100%;float: left;list-style: none;display: flex;& > div {width: 200px;height: 100%;margin-right: 10px;}& > div:nth-child(1) {background-color: saddlebrown;}& > div:nth-child(2) {background-color: rgb(238, 254, 0);}& > div:nth-child(3) {background-color: rgb(34, 255, 5);}& > div:nth-child(4) {background-color: rgb(10, 194, 235);}& > div:nth-child(5) {background-color: rgb(50, 9, 215);}}}} } </style>
代码解释:
引入依赖:
- 使用了 Vue 3 的
ref
和onMounted
函数来创建响应式数据和在组件挂载后执行动画。初始化变量:
ulDom
:通过ref
创建的引用,指向<ul>
元素,用于获取其宽度以及控制动画。animationId
:用于存储动画帧的 ID,方便后续取消动画。isPaused
:用于记录动画是否处于暂停状态。初始化动画 (
onMounted
钩子):
- 调用
animation
函数启动动画。暂停和继续动画:
pause
方法:取消当前动画帧的执行,并将isPaused
标志设置为true
,表示动画暂停。resume
方法:如果动画没有处于暂停状态,则重新启动动画。动画逻辑 (
animation
函数):
- 获取
<ul>
元素的宽度,以便在动画中使用。- 定义
animate
函数,该函数负责实际的动画逻辑。- 在
animate
函数中,每帧向左移动 10px,直到移动到一半宽度的位置时,将位置重置为 0,从而实现无限滚动的效果。- 使用
requestAnimationFrame
来实现流畅的动画效果。