拖动播放条

拖动播放条

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>
posted @ 2024-05-30 15:04  DAmarkday  阅读(10)  评论(0)    收藏  举报
编辑推荐:
· 于是转身独立开发者
· C#.Net筑基-泛型T & 协变逆变
· dotnet 代码调试方法
· DbContext是如何识别出实体集合的
· 一次 .NET 性能优化之旅:将 GC 压力降低 99%
阅读排行:
· 我救了一个网站,性能提升了1500 多倍!
· .NET程序员的多语言笔记本:Polyglot Notebook
· 免费开源 .NET OpenCV 迷你运行时全平台发布
· 经验贴!万字总结网卡丢包及ping延迟等网络问题排查思路
· 用好索引的10条军规
点击右上角即可分享
微信分享提示