笔记:Vue3 + arco slider 封装的音视频进度条,不受timeupdate更新影响的进度条组件

235 阅读1分钟

Vue3 + arco slider 封装的音视频进度条,不受timeupdate更新影响的进度条组件

<template>
	<div class="Progress">
		<h-slider class="bar" v-model="_modelValue" v-bind="sliderProps" />
	</div>
</template>

<script setup>
import { ref, onMounted, watch } from "vue";

const props = defineProps({
	modelValue: {
		type: Number,
		default: 0,
	},
	// 所有 slider 的 props
	sliderProps: {
		type: Object,
		default: {},
	},
});

const emits = defineEmits(["update:modelValue", "changeEnd"]);

const mousedown = ref(false);
const _modelValue = ref(props.modelValue);

watch(
	() => props.modelValue,
	(val) => {
		if (!mousedown.value) {
			_modelValue.value = val;
		}
	}
);

onMounted(() => {
	mouseListener();
});
// 鼠标按下抬起监听器
const mouseListener = () => {
	document.addEventListener("mousedown", (e) => {
		const passClassNameList = ["h-slider-bar", "h-slider-btn", "h-slider-track"];
		if (passClassNameList.includes(e.target.className)) {
			mousedown.value = true;
		}
	});
	document.addEventListener("mouseup", () => {
		if (mousedown.value) {
			setTimeout(() => {
				emits("changeEnd", _modelValue.value);
				emits("update:modelValue", _modelValue.value);
			}, 0);
		}
		mousedown.value = false;
	});
};
</script>

<style lang="scss" scoped>
.Progress {
	&:deep(.h-slider-track::before) {
		height: 4px;
	}
	&:deep(.h-slider-bar) {
		height: 4px;
		background: var(--color-theme);
	}
	&:deep(.h-slider-btn::after) {
		border-color: var(--color-theme);
		background: var(--color-theme);
		box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
	}
}
</style>