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

vue3项目移动端实现进度条可手动滑动控制进度和点击控制进度

最终效果
在这里插入图片描述
完整代码:

<template><div class="slider-container"><div class="slider-track" ref="trackRef"><div class="slider-thumb" ref="thumbRef"@touchstart="handleTouchStart"@touchmove="handleTouchMove"@touchend="handleTouchEnd":style="{ left: thumbPosition }"></div><div class="slider-progress" :style="{ width: progressWidth }"></div><div v-for="n in 10" :key="n" class="slider-mark":style="{ left: `${(n - 1) * 100 / 9}%` }"></div><!-- 添加单独的点击区域 --><div v-for="n in 10" :key="'click-' + n" class="slider-click-area":style="{ left: `${(n - 1) * 100 / 9}%` }"@click="jumpToValue(n)"@touchstart="jumpToValue(n)"></div><div v-for="n in 10" :key="'label-' + n" class="slider-label":style="{ left: `${(n - 1) * 100 / 9}%` }">{{ n }}</div></div><div class="slider-value">当前值: {{ currentValue }}</div></div></template><script lang="ts" setup>import { ref, computed } from 'vue'const trackRef = ref<HTMLDivElement | null>(null)const thumbRef = ref<HTMLDivElement | null>(null)const currentValue = ref(1)const isDragging = ref(false)const startX = ref(0)const thumbStartLeft = ref(0)const progressWidth = computed(() => {return `${(currentValue.value - 1) * 100 / 9}%`})const thumbPosition = computed(() => {return `${(currentValue.value - 1) * 100 / 9}%`})function handleTouchStart(e: TouchEvent) {isDragging.value = truestartX.value = e.touches[0].clientXconst thumbRect = thumbRef.value?.getBoundingClientRect()thumbStartLeft.value = thumbRect?.left || 0e.preventDefault()}function handleTouchMove(e: TouchEvent) {if (!isDragging.value) returnconst trackRect = trackRef.value?.getBoundingClientRect()const trackWidth = trackRect?.width || 0let moveX = e.touches[0].clientX - startX.valuelet newLeft = thumbStartLeft.value + moveX - (trackRect?.left || 0)// 限制在轨道范围内newLeft = Math.max(0, Math.min(newLeft, trackWidth))// 计算最接近的刻度位置const percent = newLeft / trackWidthconst closestValue = Math.round(percent * 9) + 1// 只有当移动距离足够大时才更新值,避免抖动if (Math.abs(percent - (currentValue.value - 1)/9) > 0.03) {currentValue.value = Math.max(1, Math.min(10, closestValue))}e.preventDefault()}function handleTouchEnd() {// 滑动结束时确保对准最近的刻度currentValue.value = Math.round(currentValue.value)isDragging.value = false}function jumpToValue(value: number) {currentValue.value = value;}</script><style scoped>.slider-container {/* padding: 20px; */width: 85%;max-width: 500px;margin: 0 auto;}.slider-track {position: relative;height: 4px;background-color: #e0e0e0;border-radius: 2px;margin: 30px 0 40px;}.slider-progress {position: absolute;height: 100%;background-color: #42b983;border-radius: 2px;pointer-events: none;}.slider-thumb {position: absolute;width: 24px;height: 24px;background-color: #42b983;border-radius: 50%;top: 50%;transform: translate(-50%, -50%);cursor: pointer;z-index: 4; /* 确保在最上层 */touch-action: none;}.slider-mark {position: absolute;width: 8px;height: 8px;background-color: #fff;border: 2px solid #e0e0e0;border-radius: 50%;top: 50%;transform: translate(-50%, -50%);pointer-events: none;z-index: 1;}.slider-label {position: absolute;top: 20px;transform: translateX(-50%);font-size: 12px;color: #666;pointer-events: none; /* 标签本身不接受事件 */z-index: 2;user-select: none;}/* 新增的点击区域 */.slider-click-area {position: absolute;width: 30px;height: 40px;top: -10px;transform: translateX(-50%);z-index: 3; /* 在标签和滑块之间 */cursor: pointer;}</style>

使用:

<NumberSlider />import NumberSlider from '@/components/m/numberSlider.vue';
http://www.xdnf.cn/news/13748.html

相关文章:

  • Docker入门篇--从安装到使用
  • 【Linux手册】从「程序」到「进程」:计算机世界的运行机制
  • 智慧养老与数字健康:科技赋能老年生活,构建全方位养老体系
  • Redis核心数据结构详解与应用
  • arduino通过控制器,精准控制24V电动轮毂转动
  • 解锁Scrapy爬虫:从入门到实战的Python秘籍
  • 图像分割技术:像素级的精准识别(superior哥深度学习系列第12期)
  • 关于MySql深分页的问题及优化方案
  • 软件测试的艺术与科学:构建商业级产品的优雅草卓伊凡
  • 微信小程序渗透测试指北(附案例)
  • ATM 模拟器 Golang 程序--示例
  • 【二分答案1-----切木棒】
  • 基于YOLOv11与单目测距的实战教程:从目标检测到距离估算
  • 嵌入式通信模块实战新范式:基于虚拟仿真平台的NB-IoT核心技能训练——零硬件损耗的全栈式实验方案,重构物联网通信教学逻辑
  • 基于多面体模型的编译优化技术
  • Ubuntu 绑定Conda
  • 在 Vue 3 中修改 el-select 组件接收的 prop 值
  • Parasoft C++Test软件集成测试(部件测试)_操作指南
  • 【3D插件推荐】PolyCloth v2.07 超强布料模拟工具(附图文安装教程与下载)
  • 力扣面试150题--单词接龙
  • stm32cubeide中编译非flash起始地址开始的程序
  • 解决vscode中使用debuger运行app.py但是报错No module named app的方法
  • kali2024 由于没有公钥,无法验证下列签名---解决方案
  • docker compose搭建elk 8.6.2
  • AS610x奇力科技电池管理系统(BMS)模拟前端(AFE)
  • Linux 与 Windows 系统挖矿程序清理
  • nt!CcGetDirtyPages函数分析
  • 如何将 iPhone 中的短信导出为 PDF
  • [vela os_5] 中断系统 | 任务调度 | 日志系统
  • C++代码随想录刷题知识分享-----替换数字字符 —— 字符串空间扩展与逆向填充技巧