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

【vue】NoticeBar:滚动通知栏组件手动实现(内容、速度、循环间隔可配置)

文章目录

    • 背景
    • 效果
    • 逻辑
    • 代码
      • 初始化
      • 滚动逻辑
      • 完整代码
    • 心得

背景

之前做了一个需求,里面有一个滚动通知栏
由于是活动页面,逻辑不复杂,使用技术栈为svelte,没有UI组件库。原生实现的通知栏,它的滚动有点问题。由于时间紧张,使用了不够好的方法实现:
【IOS webview】css动画,首次进入异常(滚动很缓慢),息屏后重新进入才正常_css3 animation scroll动画在ios中需要切一下屏幕才会运行-CSDN博客

目的:手动实现一个滚动通知栏。了解循环滚动逻辑。

参考: NoticeBar 通知栏 - Vant4

效果

在这里插入图片描述

<NoticeBarVue :content="content" :speed="speed" :loopWait="loopWait"></NoticeBarVue>

可配置:

  • content:内容,一般为长文本。需要大于容器距离才会滚动
  • speed:移动速度。每秒移动多少px
  • loopWait:循环间隔。循环完成后等待多少秒后进行下一次循环。

由于容器的宽度、背景色等配置不是本次代码的重点,直接写死了。如有需要可以自己改为可配置的。

逻辑

初始状态下,内容位置:

在这里插入图片描述
滚动逻辑:

在这里插入图片描述

代码

初始化

  <div class="scroll-bar" ref="scrollBarRef"><div class="content" ref="contentRef">{{ props.content }}</div></div>

获取容器宽度(offsetWidth)和内容实际宽度(scrollWidth )。

  containerWidth.value = scrollBarRef.value.offsetWidthcontentWidth.value = contentRef.value.scrollWidth // scrollWidth 内容的实际宽度

滚动逻辑

position 表示当前内容偏移位置:

  • 0:相当于初始状态
  • -contentWidth:向左移动距离为内容距离,即向左滚动完毕的距离
  • containerWidth:向右距离为容器距离,即循环刚开始的距离
  • containerWidth.value + props.loopWait * props.speed:加上了循环间隔的距离。
    • 如果不想循环完成后立马开始循环,可以增加一个等待时间。这里定义为loopWait
    • loopWait*speed 就是多走的距离,即循环间隔的距离
const handleScroll = () => {if (!scrollBarRef.value || !contentRef.value) {return}//   滚动完时,重置位置。循环的开始位置是容器最右边if (position.value < -contentWidth.value) {position.value = containerWidth.value + props.loopWait * props.speed}position.value -= props.speed // 速度:每秒向左移动的距离contentRef.value.style.transform = `translateX(${position.value}px)`//   平滑滚动。告诉浏览器,在下次重绘之前,调用此回调scrollId.value = requestAnimationFrame(() => handleScroll())
}

设置contentRef的偏移距离。

调用requestAnimationFrame:效果是很平滑地滚动。

告诉浏览器你希望执行一个动画。它要求浏览器在下一次重绘之前,调用用户提供的回调函数。
Window:requestAnimationFrame() 方法 - Web API | MDN

完整代码

组件:

<template><div class="scroll-bar" ref="scrollBarRef"><div class="content" ref="contentRef">{{ props.content }}</div></div>
</template><script setup lang="ts">
import { defineProps, ref, onMounted } from 'vue'
interface NOTICEBAR {content: stringspeed: number // 每秒移动距离loopWait: number // 循环间隔
}const props = defineProps<NOTICEBAR>()
const scrollBarRef = ref()
const contentRef = ref()
const scrollId = ref()onMounted(() => {initScroll()
})const position = ref(0)
const containerWidth = ref(0)
const contentWidth = ref(0)// 初始化滚动
const initScroll = () => {if (!scrollBarRef.value || !contentRef.value) {return}containerWidth.value = scrollBarRef.value.offsetWidthcontentWidth.value = contentRef.value.scrollWidth // scrollWidth 内容的实际宽度// 容器>内容,无需滚动if (containerWidth.value > contentWidth.value) {contentRef.value.style.transform = 'translateX(0)'return}handleScroll()
}const handleScroll = () => {if (!scrollBarRef.value || !contentRef.value) {return}//   滚动完时,重置位置。循环的开始位置是容器最右边if (position.value < -contentWidth.value) {position.value = containerWidth.value + props.loopWait * props.speed}position.value -= props.speed // 速度contentRef.value.style.transform = `translateX(${position.value}px)`//   平滑滚动。告诉浏览器,在下次重绘之前,调用此回调scrollId.value = requestAnimationFrame(() => handleScroll())
}
</script><style lang="less" scoped>
.scroll-bar {width: 400px;overflow: hidden;
}
</style>

调用:

<template><div><a href="https://vant4.ylhtest.com/#/zh-CN/notice-bar">参考vant</a><div class="container"><NoticeBarVue :content="content" :speed="speed" :loopWait="loopWait"></NoticeBarVue></div></div>
</template><script setup lang="ts">
import NoticeBarVue from '@/components/notice-bar.vue'const content = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz1234567890'
const speed = 1
const loopWait = 50
</script><style lang="less" scoped>
.container {background-color: #fffbe8;margin: 10px 0;
}
</style>

心得

理解了滚动通知栏、循环滚动。

【IOS webview】css动画,首次进入异常(滚动很缓慢),息屏后重新进入才正常_css3 animation scroll动画在ios中需要切一下屏幕才会运行-CSDN博客的问题是,没有显示地计算宽度。所以页面自适应地渲染的时候,会出问题(默认为0,渲染出来后才有宽度)。
当时把宽度写死了,相当于替代了 动态计算 的步骤。

http://www.dtcms.com/a/483894.html

相关文章:

  • 绘制网站地图施工企业的施工生产计划与建设
  • 电子商务平台网站建造温州网站开发定制
  • 永康市网站建设关键词排名优化网站建设公司哪家好
  • 花卉网站建设的总结与杂志制作 wordpress主题
  • 外卖网站那家做的好个人网站设计论文范文
  • 【数位dp】3704. 统计和为 N 的无零数对|2419
  • 快速学制作网站株洲seo优化公司
  • 【Datawhale组队学习】math-for-ai TASK01
  • 个人网站主页模板wp用户前端化专业版wordpress插件[中英双语]
  • 看设计比较好的网站在线装修设计平台
  • 网站建设目标分析学校网站建设工作方案
  • 【Linux】Linux驱动开发与BSP开发:嵌入式系统的两大基石
  • 郑州机械网站建设张家港网站制作服务
  • 动叫建个网站刷排名郑州高端做网站
  • 波矢 行波 和 相速度推导
  • LeetCode算法日记 - Day 72: 下降路径最小和、珠宝的最高价值
  • 天津专业智能建站wordpress 转换app
  • 周口市住房和城乡建设局门户网站wordpress邮件服务器怎么设置
  • 新版 网站在建设中...工信部 网站 备案
  • Flutter---showCupertinoDialog
  • 万州做网站seo优化一般包括哪些
  • 网站建设优化兼职在家漯河网站建设费用
  • 学校网站的英文一个人如何注册公司
  • 哪些网站用php余姚网站建设设计服务
  • PS成长之路⑧:如何判断生成何种需求类型满足场景需求
  • 如何把资料上传到网站威海城乡建设局网站
  • 专业制作网站 上海模版做网站多少钱
  • 快速掌握【Redis】Set:从基础命令到内部编码
  • [Linux系统编程——Lesson13.自定义shell(讲解原理)]
  • 微信开放平台官方网站家电电商平台排名