拖动播放条
拖动播放条
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 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/GoodMemoryBlog/articles/18222408.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)