【Nova UI】十六、打造组件库之滚动条组件(中):探秘滑块的计算逻辑

序言

在上篇文章中,我们完成了滚动条组件开发的前期准备工作,包括理论推导、布局规划和基础设置。现在,我们将把这些准备转化为实际代码,开启滚动条组件的具体开发之旅🌟。我们会详细阐述如何实现各项功能,解决开发中的技术挑战,为用户带来更好的滚动体验🌐。

滚动条

在设计滚动条组件时,我们需要考虑横向和纵向两个方向的滚动条。这两个方向的滚动条在功能实现和表现形式上有诸多相似之处,但也存在一些细微的差异。为了提高代码的可维护性、可复用性和可扩展性,我们决定将滚动条单独提取出来,作为一个独立的组件进行开发。基于此,我们在 packages/components/scrollbar/src 目录下创建了 bar.ts 和 bar.vue 文件,它们将作为实现滚动条功能的核心文件,为后续的开发工作提供强有力的支撑 🏗️。

bar.ts

import { ExtractPropTypes } from 'vue'
import { useDirectionProp } from '@nova-ui/hooks'
import type bar from './bar.vue'export const barProps = {direction: useDirectionProp(),always: Boolean,
} as constexport type BarType = ExtractPropTypes<typeof barProps>export type BarInstance = InstanceType<typeof bar>

在 bar.ts 文件中,barProps 包含 direction 和 always 两个属性。direction 用于确定滚动条的方向,并且可以在其他组件中复用 🔄。always 这个属性用于控制滚动条是否始终显示,以此来满足不同的使用场景 🔧。通过 InstanceType<typeof bar> 导出的 BarInstance 类型,有助于在操作滚动条组件实例时确保类型的准确性,避免出现类型错误,而且会在 scrollbar 组件中使用 🌟。

bar.vue

<template><divv-show="visible"ref="barRef":class="[n.b(),n.m(direction),n.is('always', always)]"><divref="thumbRef":class="n.e('thumb')"></div></div>
</template><script lang="ts" setup>
const n = useNamespace('bar')
defineOptions({name: 'NBar',
})
const props = defineProps(barProps)
</script>

bar.vue 的基本 DOM 结构由两个 div 元素组成,一个作为轨道,另一个作为滑块。首先,我们会定义以下几个重要的变量:

  • size:用于存储滑块的长或宽,方便后续的样式调整 📏。
  • ratio:表示视图区域与可视区域的比例,这是计算滑块大小的关键数据 🔢。
  • visible:决定滚动条是否显示,会根据不同的情况进行调整 👁️。
  • distance:表示滑块滚动的距离,它会根据用户的操作而变化呢 📏。

滑块大小计算

我们需要获取视图区域和可视区域的 DOM 元素。在 scrollbar 组件中通过 provide 传递,在 bar 组件中通过 inject 获取,以下是以纵向滚动条为例的代码,完整代码可查看相应的仓库 🔍。

const scrollbar = inject(scrollbarInjectionKey)
const visible = ref(false)
const size = ref(0)
const ratio = ref(1)const updateHandler = () => {const wrap = scrollbar?.wrapElementif (!wrap) returnconst { offsetHeight, scrollHeight }  = wrapconst _ratio = offsetHeight / scrollHeightconst height = _ratio * offsetHeightsize.value = heightratio.value = _ratiovisible.value = offsetHeight < scrollHeight
}

通过上述计算,我们可以得到所需的数值,进而为滑块添加合适的样式 🌟。

const thumbStyle = computed(() => {return {[props.direction === 'vertical' ? 'height' : 'width']: size.value ? addUnit(size.value) : undefined} 
})

滑块滚动距离

在完成滑块大小的计算和相关属性的获取之后,我们要计算滑块滚动的距离 🔢。

const scrollHandler = () => {const wrap = scrollbar?.wrapElementif (!wrap) returndistance.value = wrap.scrollTop * ratio.value
}

这个计算很简单,就是将视图区域滚动的距离与比例相乘。根据这个结果,我们将修改滑块的样式:

const thumbStyle = computed(() => {return {[props.direction === 'vertical' ? 'height' : 'width']: size.value ? addUnit(size.value) : undefined,transform: `translate${ props.direction === 'vertical' ? 'Y' : 'X' }(${ distance.value }px)`}
})

至此,基本功能已成型 👏。接下来,我们来看看如何触发这些方法。

scrollbar 更新 bar的 滑块

在 VNode 更新之后,我们需要调用相应的方法,这里使用 onUpdated 生命周期来完成。为了更好地兼容不同的场景,当视图区域大小发生变化时,我们会使用 useResizeObserver 来监听 DOM 变化并调用 updateHandler 。

const update = () => {barUpdateHandler()barScrollHandler()
}let stopResizeObserver: (() => void) | undefined = undefined
watch(() => props.noresize, (noresize) => {if (noresize) {stopResizeObserver?.()} else {const { stop } = useResizeObserver(wrapRef as unknown as MaybeComputedElementRef, update)stopResizeObserver = stop}
}, { immediate: true })onUpdated(() => {update()
})

scrollbar 更新 bar的 滚动距离

在设置好滑块的大小之后,我们需要处理滚动距离。我们会对滚动区域进行监听,触发 bar 的相关函数。

const barScrollHandler = () => {barVerticalRef.value?.scroll()barHorizontalRef.value?.scroll()
}
const onScroll = () => {barScrollHandler()emits('scroll', {scrollTop: wrapRef.value?.scrollTop || 0,scrollLeft: wrapRef.value?.scrollLeft || 0,})
}

🦀🦀感谢看官看到这里,如果觉得文章不错的话🙌,点个关注不迷路⭐。
诚邀您加入我的微信技术交流群🎉,群里都是志同道合的开发者👨‍💻,大家能一起交流分享摸鱼🐟。期待与您在群里相见🚀,咱们携手在开发路上共同进步✨ !
👉点我

感谢各位大侠一路相伴,实在感激! 不瞒您说,在下还有几个开源项目 📦,它们就像精心培育的幼苗 🌱,急需您的浇灌。要是您瞧着还不错,麻烦动动手指,给它们点亮几颗 Star ⭐,您的支持就是它们成长的最大动力,在此谢过各位大侠啦!

  • Nova UI组件库:https://github.com/gmingchen/nova-ui
  • 基于 Vue3 + Element-plus 管理后台基础功能框架
  • 预览:https://admin.gumingchen.icu
    • Github:https://github.com/gmingchen/agile-admin
    • Gitee:https://gitee.com/shychen/agile-admin
    • 基础版后端:https://github.com/gmingchen/java-spring-boot-admin
    • 文档:http://admin.gumingchen.icu/doc/
  • 基于 Vue3 + Element-plus + websocket 即时聊天系统
    • 预览:https://chatterbox.gumingchen.icu/
    • Github:https://github.com/gmingchen/chatterbox
    • Gitee:https://gitee.com/shychen/chatterbox
  • 基于 node 开发的后端服务:https://github.com/gmingchen/node-server

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

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

相关文章

laravel 使用异步队列,context带的上下文造成反序列化出问题

2025年5月8日17:03:44 如果你是单个应用&#xff0c;异步递交任务&#xff0c;是在应用内部使用&#xff0c;一般不会发生这样的问题 但是现在app项目是 app是一个应用&#xff0c;admin是一个应用&#xff0c;app吧为了接口性能吧异步任务丢给admin去执行&#xff0c;如果两个…

深入剖析 MyBatis 位运算查询:从原理到最佳实践

深入剖析 MyBatis 位运算查询&#xff1a;从原理到最佳实践 引言 在数据库设计中&#xff0c;位运算是一种高效存储和查询多选字段的常用技术。然而&#xff0c;在实际开发中&#xff0c;特别是在使用 MyBatis 这样的 ORM 框架时&#xff0c;位运算查询往往会遇到一些意想不到…

01 | 大模型微调 | 从0学习到实战微调 | AI发展与模型技术介绍

一、导读 作为非AI专业技术开发者&#xff08;我是小小爬虫开发工程师&#x1f60b;&#xff09; 本系列文章将围绕《大模型微调》进行学习&#xff08;也是我个人学习的笔记&#xff0c;所以会持续更新&#xff09;&#xff0c;最后以上手实操模型微调的目的。 (本文如若有…

代码随想录算法训练营第三十八天|动态规划part6(完全背包2)

322. 零钱兑换 题目链接&#xff1a; 322. 零钱兑换 - 力扣&#xff08;LeetCode&#xff09; 文章讲解&#xff1a; 代码随想录 思路&#xff1a; 确定递推公式&#xff1a; dp[j]min(dp[j],dp[j-coins[i]]1); 由于是完全背包 &#xff0c;所以遍历顺序是正序 还存在另一…

使用 ECharts GL 实现交互式 3D 饼图:技术解析与实践

一、效果概览 本文基于 Vue 3 和 ECharts GL&#xff0c;实现了一个具有以下特性的 3D 饼图&#xff1a; 立体视觉效果&#xff1a;通过参数方程构建 3D 扇形与底座动态交互&#xff1a;支持点击选中&#xff08;位移效果&#xff09;和悬停高亮&#xff08;放大效果&#xff…

Transformer Decoder-Only 参数量计算

Transformer 的 Decoder-Only 架构&#xff08;如 GPT 系列模型&#xff09;是当前大语言模型的主流架构&#xff0c;其参数量主要由以下几个部分组成&#xff1a; 嵌入层&#xff08;Embedding Layer&#xff09;自注意力层&#xff08;Self-Attention Layers&#xff09;前馈…

(自用)Java学习-5.8(总结,springboot)

一、MySQL 数据库 表关系 一对一、一对多、多对多关系设计外键约束与级联操作 DML 操作 INSERT INTO table VALUES(...) DELETE FROM table WHERE... UPDATE table SET colval WHERE...DQL 查询 基础查询&#xff1a;SELECT * FROM table WHERE...聚合函数&#xff1a;COUNT()…

【日撸 Java 三百行】Day 11(顺序表(一))

目录 Day 11&#xff1a;顺序表&#xff08;一&#xff09; 一、关于顺序表 二、关于面向对象 三、代码模块分析 1. 顺序表的属性 2. 顺序表的方法 四、代码及测试 拓展&#xff1a; 小结 Day 11&#xff1a;顺序表&#xff08;一&#xff09; Task&#xff1a; 在《数…

Spring Boot动态配置修改全攻略

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 无需重启应用&#xff0c;实时更新配置的终极指南 在微服务架构中&#xff0c;动态配置管理是提高系统灵活性的关键技术。本文将通过4种主流方案&#xff0c…

精益数据分析(55/126):双边市场模式的挑战、策略与创业阶段关联

精益数据分析&#xff08;55/126&#xff09;&#xff1a;双边市场模式的挑战、策略与创业阶段关联 在创业和数据分析的学习旅程中&#xff0c;我们持续探索不同商业模式的奥秘。今天&#xff0c;依旧怀揣着与大家共同进步的想法&#xff0c;深入研读《精益数据分析》&#xf…

linux内核pinctrl/gpio子系统驱动笔记

目录 一、简单介绍二、主要源码文件和目录gpio子系统pinctrl子系统两个子系统之间的关系设备树例子 三、主要的数据结构gpio子系统pinctrl子系统 四、驱动初始化流程五、难点说明 一、简单介绍 GPIO子系统: Linux GPIO子系统是Linux内核中负责处理GPIO&#xff08;通用输入输出…

Vue 2 项目中配置 Tailwind CSS、Font Awesome和daisyUI

Vue 2 项目中配置 Tailwind CSS 和 安装 daisyUI 首先重点注意&#xff0c;Vue2中安装Tailwind和daisyui一定要注意版本。 最佳版本 使用 Vue 2 TailwindCSS v2 DaisyUI v1 的兼容版本 "tailwindcss": "npm:tailwindcss/postcss7-compat^2.2.17", &q…

5.11 - 5.12 JDBC+Mybatis+StringBoot项目配置文件

JDBC&#xff1a; 预编译SQL优点&#xff1a;安全&#xff0c;性能更高。 在cmd里面输入java-jar就可以运行jar包。 Mybatis&#xff1a; 持久层框架。用于简化JDBC的开发。 数据库连接池里面放置的是一个一个Connection连接对象。&#xff08;连接池中的连接可以复用&#…

探索科技的前沿动态:科技爱好者周刊

探索科技的前沿动态:科技爱好者周刊 在信息爆炸的时代,我们每时每刻都被新技术、新理念包围。而如何在这纷繁复杂的信息中找到对自己有价值的内容,成了一大挑战。今天,我们要介绍的是一个宝贵的资源——科技爱好者周刊,它致力于为科技爱好者提供优质的科技资讯,每周五发…

Vue3 官方宣布淘汰 Axios,拥抱Alova.js

过去十年,Axios 凭借其简洁的API设计和浏览器/Node.js双环境支持,成为前端开发者的首选请求库。但随着现代前端框架的演进和工程化需求的升级,Alova.js 以更轻量、更智能、更符合现代开发范式的姿态登场。 一、Axios的痛点 1,冗余的适配逻辑,比如Axios的通用配置(但实际…

Spring AI 与 Groq 的深度集成:解锁高效 AI 推理新体验

Spring AI 与 Groq 的深度集成&#xff1a;解锁高效 AI 推理新体验 前言 在人工智能飞速发展的当下&#xff0c;AI 推理的效率和性能成为开发者关注的焦点。Groq 作为一款基于 LPU™ 的超快速 AI 推理引擎&#xff0c;凭借其强大的性能&#xff0c;能够支持各类 AI 模型&…

风车OVF镜像:解放AI开发限制的Ubuntu精简系统

风车OVF镜像&#xff1a;解放AI开发限制的Ubuntu精简系统 AI白嫖续杯一站式-风车ovf AI白嫖续杯一站式解决-风车ovf 前言 作为一名AI开发者&#xff0c;我经常在Windows和Linux环境之间切换开发。然而&#xff0c;Windows平台上的各种免费版限制逐渐成为我工作效率的瓶颈。在寻…

第十部分:文件与动静态库

目录 1、文件系统 1.1、磁盘 1.2、文件系统 1.3、文件的增删查改 2、软硬链接 2.1、软链接 2.2、硬链接 3、物理内存与文件 4、动静态库 4.1、静态库 4.1.1、静态库的制作 4.1.2、静态库的使用 4.2、动态库 4.2.1、动态库的制作 4.2.2、动态库的使用 4.3、动静…

android14优化ntp时间同步

简介 网络时间协议NTP&#xff08;Network Time Protocol&#xff09;是TCP/IP协议族里面的一个应用层协议&#xff0c;用来使客户端和服务器之间进行时钟同步&#xff0c;提供高精准度的时间校正。 当机器的ntp时间同步出现问题时&#xff0c;可以从ntp配置方面进行优化&…

ZYNQ笔记(二十):Clocking Wizard 动态配置

版本&#xff1a;Vivado2020.2&#xff08;Vitis&#xff09; 任务&#xff1a;ZYNQ PS端 通过 AXI4Lite 接口配置 Clocking Wizard IP核输出时钟频率 目录 一、介绍 二、寄存器定义 三、配置 四、PS端代码 一、介绍 Xilinx 的 Clock Wizard IP核 用于在 FPGA 中生成和管理…