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

vue3范围选择组件封装

个人项目地址: SubTopH前端开发个人站

(自己开发的前端功能和UI组件,一些有趣的小功能,感兴趣的伙伴可以访问,欢迎提出更好的想法,私信沟通,网站属于静态页面)

SubTopH前端开发个人站https://subtop.gitee.io/subtoph.github.io/#/home

以上 👆 是个人前端项目,欢迎提出您的建议😊

以下是正文内容...............

实现效果

直接上代码

组件文件

<template><div class="swh-range-page" :id="onlyId" ref="rangeRef"><div class="swh-range-selection" :id="onlyId + '_selection'"><!-- 滑动槽 --><div class="swh-trough" @click="handleTroughClick"></div><!-- 选中范围高亮条 --><pclass="swh-drag-trough":id="onlyId + '_drag-trough'"@click="handleTroughClick"></p><!-- 拖拽按钮 --><p class="swh-drag-btn" :id="onlyId + '_drag-btn'"></p><p class="drag-value" :id="onlyId + '_drag-value'">{{ rangValue }}</p></div></div>
</template><script>
import { reactive, toRefs, onBeforeMount, onMounted, ref, nextTick } from 'vue';
import { findCloseNum, handleStepNumber } from '@/utils/common.js';
export default {name: '',props: {minValue: {type: Number,default: 0,explain: '范围最小值',otherVal: '---'},maxValue: {type: Number,default: 100,explain: '范围最大值',},// 初始值initValue: {type: Number,default: 0,explain: '设置初始值',},// 是否设置初始值setInitValue: {type: Boolean,default: true,explain: '是否使用初始值(true时initValue有效)',},getRangChange: {type: Function,explain: '数值发生变化'}},setup(props, ctx) {const data = reactive({dragEle: null, //推拽槽元素rangeEle: null, //推拽按钮元素dragTrough: null, //推拽的条元素clickPos: 0, //点击移动按钮时鼠标距离父级的位置moveLeft: 0, //移动的leftrangeWidth: 0, //范围盒子宽度btnWidth: 0, //拖拽按钮尺寸rangValue: 0, //选中值optionalRange: 0, //实际范围rangArr: [], //范围段数组onlyId: ''});const rangeRef = ref(null); // 获取当前组件中外层元素onBeforeMount(() => {});onMounted(() => {nextTick(() => {// 获取组件数量const ele = document.getElementsByClassName('swh-range-page');if (ele.length) {for (let i = 0; i < ele.length; i++) {// 组件和当前ref获取的组件本身相等就设置idif (rangeRef.value === ele[i]) {data.onlyId = `swhRangeRef_${i}`; //设置显示框id}}}nextTick(() => {init();});});});const init = () => {const { onlyId } = data;data.rangeCom = document.querySelector(`#${onlyId}`);data.dragEle = document.querySelector(`#${onlyId}_drag-btn`);data.dragValueEle = document.querySelector(`#${onlyId}_drag-value`);data.rangeEle = document.querySelector(`#${onlyId}_selection`);data.dragTrough = document.querySelector(`#${onlyId}_drag-trough`);data.btnWidth = data.dragEle.offsetWidth;data.rangeWidth = data.rangeEle.offsetWidth;data.dragEle.style.left = -data.btnWidth / 2 + 'px';// 设置默认值,没有就是最小值const { setInitValue, initValue, minValue, maxValue } = props;if (setInitValue) {// 设置默认值if (initValue >= minValue && initValue <= maxValue) {// 初始值在范围内data.rangValue = initValue;} else {console.error('未设置初始值或者初始值超出范围');data.rangValue = minValue;}} else {// 未设置默认值,默认最小值data.rangValue = props.minValue;}// 最大值减区最小值是 实际范围data.optionalRange = props.maxValue - props.minValue;// 获取分割范围数组data.rangArr = handleStepNumber(data.rangeWidth, data.optionalRange);initMovePosition();bindEvent();};// 初始化值所在的位置const initMovePosition = () => {const index = rangNumArr().indexOf(data.rangValue);if (index !== -1) {const proportion = index / data.optionalRange;const initLeft = data.rangeWidth * proportion;data.moveLeft = initLeft;moveLeft();}};// 范围数值数组const rangNumArr = () => {let rNumArr = [];for (let i = 0; i < data.optionalRange + 1; i++) {rNumArr.push(props.minValue + i);}return rNumArr;};// 事件监听const bindEvent = () => {data.dragEle.addEventListener('mousedown', handleMouseDown, false);};// 按下事件const handleMouseDown = (e) => {// 点击时鼠标距离父级left    减去已经实际移动的距离data.clickPos = e.clientX - data.rangeEle.offsetLeft - data.moveLeft;document.addEventListener('mousemove', handleMouseMove, false);document.addEventListener('mouseup', handleMouseUp, false);};// 移动处理const handleMouseMove = (e) => {// 获取实际移动的位置,移动后left减去点击时clickPos(left)是实际移动的leftconst inMoveleft = e.clientX - data.rangeEle.offsetLeft;// 移动的距离  -  开始点击的位置 = 实际移动距离data.moveLeft = inMoveleft - data.clickPos;moveLeft();};// 直接点击范围条,改变拖拽按钮选中位置const handleTroughClick = (e) => {// 鼠标点击位置减去元素距离body的left,获取点击在跳上的left距离const inMoveleft = e.clientX - data.rangeCom.getBoundingClientRect().left;// 距离减去按钮宽度未实际移动leftdata.moveLeft = inMoveleft - data.btnWidth;moveLeft();};// 移动位置const moveLeft = () => {// 调整实际移动的距离if (data.moveLeft > data.rangeWidth) {// 最大限制data.moveLeft = data.rangeWidth;} else if (data.moveLeft < 0) {// 最小限制data.moveLeft = 0;} else {// 移动至鼠标最接近的范围点上data.moveLeft = findCloseNum(data.rangArr, data.moveLeft);}//按键 移动的距离减去按键一半宽度data.dragEle.style.left = data.moveLeft - data.btnWidth / 2 + 'px';//设置选中范围条宽度data.dragTrough.style.width = data.moveLeft + 'px';// 移动的占比const proportion = data.moveLeft / data.rangeWidth;// 计算移动的值data.rangValue =parseInt(data.optionalRange * proportion) + props.minValue;// 计算提示数值的偏移位置const wc = (data.dragValueEle.offsetWidth - data.btnWidth) / 2;// 设置显示范围值的提示位置,设置按钮的位置即可data.dragValueEle.style.left =data.dragEle.offsetLeft - Math.abs(wc) + 'px';ctx.emit('getRangChange', data.rangValue);};// 移除事件监听const handleMouseUp = () => {document.removeEventListener('mousemove', handleMouseMove, false);document.removeEventListener('mouseup', handleMouseUp, false);};return {rangeRef,handleTroughClick,...toRefs(data)};}
};
</script>
<style scoped lang="less">
.swh-range-page {position: relative;min-width: 160px;width: 100%;display: flex;padding: 0 20px;justify-content: center;border-radius: 10px;.swh-range-selection {position: relative;width: 100%;height: 30px;z-index: 9;.swh-trough {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 100%;height: 5px;background: rgb(243, 243, 243);border-radius: 3px;cursor: pointer;}.swh-drag-btn {position: absolute;top: 50%;left: 0;width: 20px;height: 20px;background: #fff;border: 2px solid @TSB;transform: translateY(-50%);border-radius: 50%;z-index: 1;cursor: pointer;box-sizing: border-box;&:hover {transform: translateY(-50%) scale(1.1);transition: 0.3s;}}.swh-drag-trough {cursor: pointer;position: absolute;top: 50%;left: 0;transform: translateY(-50%);background: @TSB;height: 5px;border-radius: 3px;}.drag-value {position: absolute;top: -20px;left: 0px;border-radius: 5px;width: 30px;height: 20px;background: rgba(0, 0, 0, 0.8);font-size: 12px;line-height: 20px;color: #fff;text-align: center;}}
}
</style>

 组件使用到的findCloseNum方法

// 判断当前数字  最靠近数组中那个数字
export function findCloseNum(arr, num) {var index = 0; // 保存最接近数值在数组中的索引var old_value = Number.MAX_VALUE; // 保存差值绝对值,默认为最大数值for (var i = 0; i < arr.length; i++) {var new_value = Math.abs(arr[i] - num); // 新差值if (new_value <= old_value) { // 如果新差值绝对值小于等于旧差值绝对值,保存新差值绝对值和索引if (new_value === old_value && arr[i] < arr[index]) { // 如果数组中两个数值跟目标数值差值一样,取大continue;}index = i;old_value = new_value;}}return arr[index] // 返回最接近的数值
}

 组件使用到的handleStepNumber方法

export function handleStepNumber(w, r) {const itemPx = w / r;let rangArr = [];for (let i = 0; i < r+1; i++) {rangArr.push(Math.ceil(itemPx * i));}return rangArr;
};

1.组件可以实现最小值和最大值的设置

2.可初始化值

3.组件长度根据父组件自定义

4.滑动和点击会改变范围值

根据自己的需求可进行更多扩展

相关文章:

vue3范围选择组件封装

个人项目地址&#xff1a; SubTopH前端开发个人站 &#xff08;自己开发的前端功能和UI组件&#xff0c;一些有趣的小功能&#xff0c;感兴趣的伙伴可以访问&#xff0c;欢迎提出更好的想法&#xff0c;私信沟通&#xff0c;网站属于静态页面&#xff09; SubTopH前端开发个人站…...

能被整除的数(容斥原理)

思路&#xff1a; &#xff08;1&#xff09;需求&#xff1a;求对于1~n中至少能被p1~pm至少1个整除的数的个数&#xff0c;由于都是质数&#xff0c;彼此互质&#xff0c;不需要进行质因子分解&#xff0c;根据容斥原理&#xff0c; res n/p1 n/p2 ... n/pm - n /(p1p2) -…...

Modbus转Profinet网关与流量变送器兼容转ModbusTCP协议博图配置

首先&#xff0c;我们需要明确电磁流量计的通信协议是Modbus&#xff0c;而西门子1200PLC的通信协议是Profinet。这两种协议在功能和特性上存在一定的差异&#xff0c;因此需要使用兴达易控Modbus转Profinet网关设备进行转换。兴达易控的XD-MDPN100是Profinet转ModbusTCP的网关…...

HLS实现CORDIC算法计算正余弦并上板验证

硬件&#xff1a;ZYNQ7010 软件&#xff1a;MATLAB 2019b、Vivado 2017.4、HLS 2017.4、System Generator 2017.4 1、CORDIC算法计算正余弦 CORDIC算法详细分析网上有很多资料&#xff0c;它的原理是用一系列旋转去逼近目标角度&#xff0c;这一系列旋转的角度为 θ a r c t…...

高阶数据结构并查集

目录&#xff1a; 并查集的概念代码实现 LeetCode例题 并查集的概念 将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元元素集合&#xff0c;然后按一定的规律将归于同一组元素的集合合并。在此过程中反复遇到查询某一个元素属于那个集合的运算…...

WSL2连接不了外网怎么办?

某天忽然WLAN变成地球图标&#xff0c;上不了Internet&#xff0c;搞了半天网络适配器&#xff0c;仍然不行。回忆之前做过的操作&#xff0c;曾经运行过ZoogVPN&#xff0c;试着启动并连接&#xff0c;然后退出&#xff0c;WLAN神奇地恢复了连接&#xff0c;可以上Internet了。…...

【C/C++】探索内存对齐的奥秘与优势

目录 一&#xff0c;前言 二&#xff0c;什么是内存对齐&#xff1f; 三&#xff0c;内存对齐的原理 四&#xff0c;内存对齐的优势 五&#xff0c;如何实现内存对齐&#xff1f;&#xff08;看这节就行&#xff09; 1.使用 #pragma pack 来实现内存对齐的示例 七&#…...

leetcode分类刷题:滑动窗口(二、重复元素类型)

1、连续子数组、连续子串问题通常需要滑动窗口来求解&#xff0c;本篇文章对应的“二、重复元素类型”在此基础上对连续子数组、连续子串中重复元素个数、种类进行考察&#xff0c;此时&#xff0c;需要使用和维护哈希表进行左右指针的移动&#xff0c;因此这类题目对应的解法为…...

MySQL—buffer pool

一、buffer pool的介绍 Buffer pool是什么 一个内存区域&#xff0c;为了提⾼数据库的性能&#xff0c;数据库操作数据的时候&#xff0c;把硬盘上的数据加载到buffer pool&#xff0c;不直接和硬盘打交道&#xff0c;操作的是 buffer pool的数据&#xff0c;数据库的增删改查…...

《C和指针》笔记8: 枚举类型

枚举 (enumerated)类型就是指它的值为符号常量而不是字面值的类型&#xff0c;它们以下面这种形式声明&#xff1a; enum Jar_Type { CUP, PINT, QUART, HALF_GALLON, GALLON };这条语句声明了一个类型&#xff0c;称为Jar_Type。这种类型的变量按下列方式声明&#xff1a; e…...

Python爬虫框架之Selenium库入门:用Python实现网页自动化测试详解

概要 是否还在为网页测试而烦恼&#xff1f;是否还在为重复的点击、等待而劳累&#xff1f;试试强大的Selenium&#xff01;让你的网页自动化测试变得轻松有趣&#xff01; 一、Selenium库到底是什么&#xff1f; Selenium 是一个强大的自动化测试工具&#xff0c;它可以让你直…...

docker swarm 部署服务网络问题

docker swarm 服务部署问题 docker swarm 部署服务时可能会出现&#xff0c;启动服务特别慢的情况&#xff0c;甚至一个service 启动后&#xff0c;容器会长时间处于 preparing 状态&#xff0c;直到 状态切换成 running 状态后&#xff0c;才会启动下一个service。然后查询资…...

1.00001git源码clone后进行编译(带调试)

– 新建用户 useradd postgres passwd postgres – 用户加入sude组 先cd到/etc/sudoers目录下 由于sudoers文件为只读权限&#xff0c;所以需要添加写入权限&#xff0c;chmod uw sudoers vim sudoers 找到root ALL (ALL) ALL这一行&#xff0c;在下一行加入username ALL (A…...

使用StorageClass动态创建pv

rook-ceph安装部署到位后&#xff0c;就可以开始来尝试使用StorageClass来动态创建pv了。 有状态的中间件在kubernetes上落地基本上都会用到StorageClass来动态创建pv&#xff08;对于云上应用没有那么多烦恼&#xff0c;云硬盘很好用&#xff0c;但是对于自己学习和练习来说还…...

数据结构(Java实现)-ArrayList与顺序表

什么是List List是一个接口&#xff0c;继承自Collection。 List的使用 List是个接口&#xff0c;并不能直接用来实例化。 如果要使用&#xff0c;必须去实例化List的实现类。在集合框架中&#xff0c;ArrayList和LinkedList都实现了List接口。 线性表 线性表&#xff08;lin…...

性能优化维度

CPU 首先检查 cpu&#xff0c;cpu 使用率要提升而不是降低。其次CPU 空闲并不一定是没事做&#xff0c;也有可能是锁或者外部资源瓶颈。常用top、vmstat命令查看信息。 vmstat 命令: top: 命令 IO iostat 命令&#xff1a; Memory free 命令&#xff1a; 温馨提示&#xff1a…...

PMP P-06 Resource Management

...

【C++】map的奇葩用法:和函数结合

2023年8月26日&#xff0c;周六下午 今天才发现map居然还能这样用... #include <iostream> #include <map> #include <functional>void printOne() {std::cout << "已经打印出1" << std::endl; }void printTwo() {std::cout <<…...

关于JVM的参数类型

JVM参数类型&#xff0c;主要是可以分为三类。分别是&#xff1a; 标准参数 例如&#xff1a; -help-server-client-version-showversion-cp-classpath 等等&#xff0c;这类参数的特点是在jdk各版本里基本不会变的&#xff0c;相对稳定。 X参数 X参数也就是非标准化参数&am…...

HTTP协议中的Content-Type及其常见类型

什么是Content-Type&#xff1f; Content-Type是HTTP协议中的一个头部字段&#xff0c;用于指示请求或响应中所传输的实体的媒体类型。 为什么使用Content-Type&#xff1f; 使用Content-Type可以告知接收方如何解析和处理传输的数据&#xff0c;确保数据能够正确地被解析和…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...