Vue中使用JavaScript中的requestAnimationFrame动画循环实现循环滚动效果-demo

效果

requestAnimationFrame是一个由浏览器提供的 JavaScript 方法,用于在下一次浏览器重绘之前执行指定的回调函数。它接受一个回调函数作为参数,并返回一个整数值,可以用于取消动画循环。

使用 requestAnimationFrame 可以创建平滑的动画效果,并且能够有效地控制动画的帧率,以适应不同的设备和浏览器性能。

与使用定时器(如 setTimeout 或 setInterval)相比,requestAnimationFrame 具有以下优势:

自动适应设备刷新率:requestAnimationFrame 会自动根据当前设备的刷新率来调整动画的帧率,以提供更平滑的动画效果。

避免资源浪费:当页面处于非激活状态时,requestAnimationFrame 会暂停动画循环,从而避免不必要的资源浪费。

与浏览器的绘制周期同步:requestAnimationFrame 会在浏览器的绘制周期内执行回调函数,以确保动画的更新和渲染在最佳时机进行。

function animate() {// 动画逻辑...requestAnimationFrame(animate);
}// 开始动画循环
requestAnimationFrame(animate);const animationId = requestAnimationFrame(animate);// 取消动画循环
cancelAnimationFrame(animationId);

实现代码

循环滚动

<template><div class="wrap" ref="wrapRef"><div v-for="item in items" :key="item" class="item">${{ item }}</div><template v-if="isShowItems"><div v-for="item in items" :key="item" class="item">${{ item }}</div></template></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue';const items = ref(Array.from({ length: 26 }, (_, index) => index + 1));const wrapRef = ref(null);
const isShowItems = ref(false);
const animationId = ref(null);// scrollWidth 总宽度,包括被隐藏的部分
// clientWidth 可视宽度,不包括被隐藏的部分 window.innerWidth
// scrollLeft 滚动距离const playAnimate = () => {const wrapElement = wrapRef.value;if (wrapElement === null) return;const maxScrollLeft = wrapElement.scrollWidth - wrapElement.clientWidth;if (maxScrollLeft) {console.log(maxScrollLeft,wrapElement.scrollWidth,wrapElement.clientWidth);isShowItems.value = true;if (wrapElement.scrollLeft >= maxScrollLeft - 2) {wrapElement.scrollLeft -= maxScrollLeft;}wrapElement.scrollLeft += 1;// 动画循环animationId.value = requestAnimationFrame(playAnimate);}
};onMounted(() => {console.log('总宽度', wrapRef.value.scrollWidth);console.log('可视宽度', wrapRef.value.clientWidth);//   playAnimate();// 开始动画循环requestAnimationFrame(playAnimate);
});
onUnmounted(() => {//   wrapRef.value = null;console.log('取消动画循环', animationId.value);// 在需要取消动画循环时cancelAnimationFrame(animationId);
});
</script>
<style lang="scss" scoped>
.wrap {background: linear-gradient(90deg, #9da0a0, #818181 138.82%);align-items: center;display: flex;height: 50px;white-space: nowrap;width: 100%;overflow: hidden;overflow: auto;&::-webkit-scrollbar {display: none;}.item {font-size: 18px;color: #fff;padding: 0 24px;}
}
</style>

来回滚动

<template><div class="wrap" ref="wrapRef"><div v-for="item in items" :key="item" class="item">${{ item }}</div></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue';const items = ref(Array.from({ length: 26 }, (_, index) => index + 1));const wrapRef = ref(null);
const isShowItems = ref(false);
const scrollLeftEnd = ref(false);
const animationId = ref(null);// scrollWidth 总宽度,包括被隐藏的部分
// clientWidth 可视宽度,不包括被隐藏的部分 window.innerWidth
// scrollLeft 滚动距离const playAnimate = () => {const wrapElement = wrapRef.value;if (wrapElement === null) return;const maxScrollLeft = wrapElement.scrollWidth - wrapElement.clientWidth;if (maxScrollLeft) {console.log(maxScrollLeft,wrapElement.scrollWidth,wrapElement.clientWidth);isShowItems.value = true;// 右到左// if (wrapElement.scrollLeft >= maxScrollLeft - 2) {//   wrapElement.scrollLeft -= maxScrollLeft;// }// wrapElement.scrollLeft += 1;// 来回滚动if (wrapElement.scrollLeft >= maxScrollLeft - 2) {scrollLeftEnd.value = true;}if (wrapElement.scrollLeft <= 1) {scrollLeftEnd.value = false;}if (scrollLeftEnd.value) {wrapElement.scrollLeft -= 1;} else {wrapElement.scrollLeft += 1;}// 动画循环animationId.value = requestAnimationFrame(playAnimate);}
};onMounted(() => {console.log('总宽度', wrapRef.value.scrollWidth);console.log('可视宽度', wrapRef.value.clientWidth);//   playAnimate();// 开始动画循环requestAnimationFrame(playAnimate);
});
onUnmounted(() => {//   wrapRef.value = null;console.log('取消动画循环', animationId.value);// 在需要取消动画循环时cancelAnimationFrame(animationId);
});
</script>
<style lang="scss" scoped>
.wrap {background: linear-gradient(90deg, #9da0a0, #818181 138.82%);align-items: center;display: flex;height: 50px;white-space: nowrap;width: 100%;overflow: hidden;overflow: auto;&::-webkit-scrollbar {display: none;}.item {font-size: 18px;color: #fff;padding: 0 24px;}
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/314279.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【UnityShader入门精要学习笔记】(1)了解渲染流水线

本系列为作者学习UnityShader入门精要而作的笔记&#xff0c;内容将包括&#xff1a; 书本中句子照抄 个人批注项目源码一堆新手会犯的错误潜在的太监断更&#xff0c;有始无终 总之适用于同样开始学习Shader的同学们进行有取舍的参考。 文章目录 渲染流水线什么是流水线什么…

不吹不黑,辩证看待开发者是否需要入坑鸿蒙

前言 自打华为2019年发布鸿蒙操作系统以来&#xff0c;网上各种声音百家争鸣。尤其是2023年发布会公布的鸿蒙4.0宣称不再支持Android&#xff0c;更激烈的讨论随之而来。 本文没有宏大的叙事&#xff0c;只有基于现实的考量。 通过本文&#xff0c;你将了解到&#xff1a; Har…

【力扣题解】P106-从中序与后序遍历序列构造二叉树-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P106-从中序与后序遍历序列构造二叉树-Java题解&#x1f30f;题目描述&#x1f4a1;题…

「网络编程」其他重要的协议或技术_ DNS协议 | ICMP协议 | NAT技术

「前言」文章内容是DNS协议、ICMP协议、NAT技术的讲解。 「归属专栏」网络编程 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、DNS协议1.1 背景1.2 域名简介1.3 域名解析的过程 二、ICMP协议2.1 ICMP简介2.2 ping命令2.3 traceroute命令 三、NAT技术3.1 NAT技术背景3.2 …

一起学Elasticsearch系列-写入原理

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 微信公众号&#xff1a;Java随想录 文章目录 写入过程写操作写流程写一致性策略 写入原理RefreshMergeFlushTranslog图解写入流程 ES作为一款开源的分布式搜索和分析引擎&#xff0c;以其卓越的性能和灵活的扩…

跳跃表原理及实现

一、跳表数据结构 跳表是有序表的一种&#xff0c;其底层是通过链表实现的。链表的特点是插入删除效率高&#xff0c;但是查找节点效率很低&#xff0c;最坏的时间复杂度是O(N)&#xff0c;那么跳表就是解决这一痛点而生的。 为了提高查询效率&#xff0c;我们可以给链表加上索…

Java EE Servlet之Cookie 和 Session

文章目录 1. Cookie 和 Session1.1 Cookie1.2 理解会话机制 (Session)1.2.1 核心方法 2. 用户登录2.1 准备工作2.2 登录页面2.3 写一个 Servlet 处理上述登录请求2.4 实现登录后的主页 3. 总结 1. Cookie 和 Session 1.1 Cookie cookie 是 http 请求 header 中的一个属性 浏…

JVM工作原理与实战(三):字节码文件的组成

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、基础信息 1.Magic魔数 2.主副版本号 3.其他信息 二、常量池 1.案例解析 三、方法 1.方法介绍 2.案例解析 四、字段 五、属性 总结 前言 JVM作为Java程序的运行环境&…

什么是JavaScript

文章目录 一、❄️什么是JavaScript&#xff1f;二、❄️JavaScript的特点三、❄️JavaScript的组成&#x1f9eb;1、核心&#xff08;ECMAScript&#xff09;&#x1f9ff;2、文档对象模型&#xff08;DOM&#xff09;&#x1f94f;3、浏览器对象模型&#xff08;BOM&#xff…

linux 中 ext2文件系统实现

ext2文件系统结构 图片的svg下载链接&#xff08;图中关于buffer的部分&#xff0c;上下两部分是重复的&#xff0c;是从不同维度下看的buffer结构&#xff09; linux内核本身不提供ext2文件系统的格式化功能&#xff0c;可以参考busybox中对mkfs.ext2的实现&#xff08;mkfs.…

msvcp140_1.dll丢失怎样修复,缺失msvcp140_1.dll是什么原因

在日常使用电脑的过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp140_1.dll丢失”。那么&#xff0c;msvcp140_1.dll究竟是什么文件&#xff1f;为什么会出现丢失的情况&#xff1f;又该如何解决这个问题呢&#xff1f;本文将详细介绍msvcp140_1…

浅谈技术架构的演进过程

前言 最近在学习Redis、Doctor相关技术知识&#xff0c;它们与分布式系统有着很大的关系。 而对于分布式系统&#xff0c;它本身就是随着业务的不断推进&#xff0c;技术架构不断演进而得到发展和实现的。而所谓的分布式系统&#xff0c;实际上就是想办法引入更多的硬件资源&am…