拖动播放条

拖动播放条

hook.ts

import { clamp, round } from "lodash-es"; import { getScaleMultiplesNumber } from "@/components/Adapter/utils"; export interface callBackResponse { type: 'moving' | 'moveEnd', percent: number } export function useProgress<T extends ReturnType<typeof defineEmits>>(emits: T) { const container = ref<HTMLDivElement | null>(); const thumb = ref<HTMLDivElement | null>(); const defaultInitLeft = ref(6); const curLeftValue = ref(defaultInitLeft.value) // 点击后添加事件 const mousedown = () => { window.addEventListener("mousemove", handleChange); window.addEventListener("mouseup", mouseup); }; // 移动滑块 const handleChange = (e: MouseEvent) => { const containerDom: NonNullable<typeof container.value> = container.value!; const thumbDom: NonNullable<typeof thumb.value> = thumb.value!; if (!thumbDom) return; const defaultLeft = defaultInitLeft.value; const containerWidth = containerDom.offsetWidth; const thumbWidth = thumbDom.offsetWidth; const RANG_LEFT_VALUE = [defaultLeft, containerWidth - defaultLeft - thumbWidth]; function moveAt(pageX: number) { let leftValue = pageX - containerDom.getBoundingClientRect().left; // * 适配不同分辨率情况下解决拖动时的偏移 // * 缩放情况下鼠标的获取坐标会发生偏移现象(导致鼠标实际移动的距离 = dom元素移动的距离 / 缩放倍数), // * 所以这里需要对其的x坐标进行转化到偏移前。 const { restore } = getScaleMultiplesNumber(); leftValue = leftValue * restore.x; leftValue = clamp(leftValue, RANG_LEFT_VALUE[0], RANG_LEFT_VALUE[1]); curLeftValue.value = leftValue containerDom.style.setProperty("--cur-init-left", `${curLeftValue.value}px`); emits('move', { type: 'moving', percent: getPercent() }) } moveAt(e.pageX); }; // 鼠标放开后移除事件 const mouseup = () => { window.removeEventListener("mousemove", handleChange); window.removeEventListener("mouseup", mouseup); emits('move', { type: 'moveEnd', percent: getPercent() }) }; const resetValue = () => { const containerDom: NonNullable<typeof container.value> = container.value!; curLeftValue.value = defaultInitLeft.value; containerDom.style.setProperty("--cur-init-left", `${curLeftValue.value}px`); } const getPercent = () => { const containerDom: NonNullable<typeof container.value> = container.value!; const thumbDom: NonNullable<typeof thumb.value> = thumb.value!; const defaultLeft = defaultInitLeft.value; const containerWidth = containerDom.offsetWidth; const thumbWidth = thumbDom.offsetWidth; const RANG_LEFT_VALUE = [defaultLeft, containerWidth - defaultLeft - thumbWidth]; const result = (curLeftValue.value - RANG_LEFT_VALUE[0]) / (RANG_LEFT_VALUE[1] - RANG_LEFT_VALUE[0]) const percent = round(result * 100, 0) return percent } onMounted(() => { resetValue() }); return { mousedown, container, thumb, resetValue, getPercent } }

vue

<template> <div relative ref="container"> <div class="progress"></div> <div ref="thumb" class="progress-control--trangle progress-control--position" @mousedown="mousedown" ></div> </div> </template> <script setup lang="ts"> import { useProgress } from "./hook"; import type { callBackResponse } from "./hook"; const emits = defineEmits<{ (eventName: "move", callback: callBackResponse): void; }>(); const { mousedown, container, thumb, resetValue, getPercent } = useProgress<typeof emits>( emits ); defineExpose({ resetValue, getPercent, }); </script> <style lang="scss" scoped> $--cur-init-left: var(--cur-init-left); .progress { width: 100%; height: 0; border: 1px solid rgba(63, 155, 190, 1); &-control { &--trangle { width: 0; height: 0; border: 6px solid transparent; border-left-color: rgba(16, 195, 220, 1); transform: translateY(-50%); cursor: pointer; } &--position { position: absolute; top: 0; bottom: 0; left: $--cur-init-left; } } } </style>

__EOF__

本文作者damarkday知识库
本文链接https://www.cnblogs.com/GoodMemoryBlog/articles/18222408.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   DAmarkday  阅读(6)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示