@extclp/vexip-ui
Version:
A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good
1 lines • 15.2 kB
Source Map (JSON)
{"version":3,"file":"video-progress.vue2.mjs","sources":["../../../components/video/video-progress.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { ResizeObserver } from '@/components/resize-observer'\r\nimport { Slider } from '@/components/slider'\r\n\r\nimport { computed, ref } from 'vue'\r\n\r\nimport { getStepByWord, useLocale, useNameHelper } from '@vexip-ui/config'\r\nimport { useListener, useSetTimeout } from '@vexip-ui/hooks'\r\nimport { boundRange, throttle } from '@vexip-ui/utils'\r\nimport { formatSeconds } from './helper'\r\n\r\nimport type { PropType } from 'vue'\r\nimport type { SliderExposed } from '@/components/slider'\r\nimport type { VideoSegment } from './symbol'\r\n\r\ninterface PointState {\r\n start: number,\r\n startPercent: number,\r\n end: number,\r\n endPercent: number,\r\n duration: number,\r\n durationPercent: number,\r\n width: number,\r\n}\r\n\r\ndefineOptions({ name: 'VideoProgress' })\r\n\r\nconst props = defineProps({\r\n time: {\r\n type: Number,\r\n default: 0,\r\n },\r\n duration: {\r\n type: Number,\r\n default: 0,\r\n },\r\n segments: {\r\n type: Array as PropType<VideoSegment[]>,\r\n default: () => [],\r\n },\r\n noPreview: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n previewSrc: {\r\n type: String,\r\n default: '',\r\n },\r\n})\r\n\r\nconst emit = defineEmits(['change'])\r\n\r\nconst nh = useNameHelper('video')\r\nconst locale = useLocale('video')\r\n\r\nconst { timer } = useSetTimeout()\r\n\r\nconst slidTime = ref(0)\r\nconst hovered = ref(false)\r\nconst hoveredTime = ref(0)\r\nconst indicatorLeft = ref(0)\r\nconst previewLeft = ref(0)\r\n\r\nlet paddingX = [0, 0]\r\nlet sliderWidth = 100\r\nlet previewWidth = 60\r\n\r\nconst wrapper = ref<HTMLElement>()\r\nconst slider = ref<SliderExposed>()\r\nconst sliderEl = computed(() => slider.value?.$el as HTMLElement | undefined)\r\nconst preview = ref<HTMLElement>()\r\n\r\nconst sliding = computed(() => !!slider.value?.sliding[1])\r\nconst percent = computed(() => {\r\n return props.duration ? ((sliding.value ? slidTime.value : props.time) / props.duration) * 100 : 0\r\n})\r\nconst className = computed(() => {\r\n return {\r\n [nh.be('progress')]: true,\r\n [nh.bem('progress', 'sliding')]: sliding.value,\r\n [nh.bem('progress', 'disabled')]: props.duration <= 0,\r\n }\r\n})\r\nconst points = computed<PointState[]>(() => {\r\n const duration = Math.max(1, props.duration)\r\n\r\n let times = props.segments.map(segment => segment.time)\r\n\r\n if (!times.length) times = [0, duration]\r\n\r\n times = times.at(-1) === duration ? times : [...times, duration]\r\n times = times[0] === 0 ? times : [0, ...times]\r\n\r\n const points: PointState[] = []\r\n\r\n for (let i = 0, len = times.length - 1; i < len; ++i) {\r\n const start = times[i]\r\n const end = times[i + 1]\r\n const pointDuration = end - start\r\n\r\n points.push({\r\n start,\r\n startPercent: (start / duration) * 100,\r\n end,\r\n endPercent: (end / duration) * 100,\r\n duration: pointDuration,\r\n durationPercent: (pointDuration / duration) * 100,\r\n width: ((end - start) / duration) * 100,\r\n })\r\n }\r\n\r\n return points\r\n})\r\nconst segmentLabel = computed(() => {\r\n const time = hoveredTime.value\r\n const segments = props.segments\r\n\r\n if (!segments.length) return ''\r\n\r\n let index = -1\r\n\r\n if (time <= 0) {\r\n index = 0\r\n } else {\r\n for (let i = 1, len = segments.length; i < len; ++i) {\r\n if (segments[i].time > time) {\r\n index = i - 1\r\n break\r\n }\r\n }\r\n }\r\n\r\n if (index < 0) {\r\n index = segments.length - 1\r\n }\r\n\r\n const title = segments[index]?.title || getStepByWord(locale.value.chapterCount, index + 1)\r\n\r\n return title && ` (${title})`\r\n})\r\n\r\nuseListener(sliderEl, 'pointerenter', () => {\r\n clearTimeout(timer.hover)\r\n\r\n timer.hover = setTimeout(() => {\r\n hovered.value = true\r\n }, 100)\r\n})\r\nuseListener(sliderEl, 'pointerleave', () => {\r\n clearTimeout(timer.hover)\r\n\r\n timer.hover = setTimeout(() => {\r\n hovered.value = false\r\n }, 100)\r\n})\r\nuseListener(\r\n sliderEl,\r\n 'pointermove',\r\n throttle((event: PointerEvent) => {\r\n if (!sliding.value) {\r\n processMoveOnTrack(event)\r\n }\r\n }),\r\n)\r\n\r\nfunction processMoveOnTrack(event: PointerEvent) {\r\n if (!sliderEl.value) return\r\n\r\n const offsetX = boundRange(\r\n event.clientX - sliderEl.value.getBoundingClientRect().left,\r\n 0,\r\n sliderWidth,\r\n )\r\n\r\n hoveredTime.value = (offsetX / sliderWidth) * props.duration\r\n indicatorLeft.value = offsetX + paddingX[0]\r\n previewLeft.value = boundRange(\r\n offsetX - previewWidth * 0.5 + paddingX[0],\r\n 0,\r\n sliderWidth - previewWidth + paddingX[0] + paddingX[1],\r\n )\r\n}\r\n\r\nfunction onSliderResize(entry: ResizeObserverEntry) {\r\n if (!wrapper.value) return\r\n\r\n const style = getComputedStyle(wrapper.value)\r\n\r\n paddingX = [parseFloat(style.paddingLeft), parseFloat(style.paddingRight)]\r\n sliderWidth = entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width\r\n}\r\n\r\nfunction onPreviewResize(entry: ResizeObserverEntry) {\r\n previewWidth = entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width\r\n}\r\n\r\nfunction handleChange(permillage: number) {\r\n emit('change', (permillage / 1000) * props.duration)\r\n}\r\n\r\nconst onSlideMove = throttle(processMoveOnTrack)\r\n\r\nfunction onSlideStart() {\r\n slidTime.value = props.time\r\n\r\n document.addEventListener('pointermove', onSlideMove)\r\n document.addEventListener('pointerup', onSlideEnd)\r\n}\r\n\r\nfunction onSlideEnd() {\r\n document.removeEventListener('pointermove', onSlideMove)\r\n document.removeEventListener('pointerup', onSlideEnd)\r\n}\r\n</script>\r\n\r\n<template>\r\n <div ref=\"wrapper\" :class=\"className\">\r\n <ResizeObserver :on-resize=\"onSliderResize\">\r\n <Slider\r\n ref=\"slider\"\r\n :class=\"nh.be('progress-slider')\"\r\n :value=\"percent * 10\"\r\n :max=\"1000\"\r\n :vertical=\"false\"\r\n :range=\"false\"\r\n hide-tip\r\n trigger-fade\r\n flip-marker\r\n :disabled=\"duration <= 0\"\r\n @change=\"handleChange\"\r\n @pointerdown=\"onSlideStart\"\r\n >\r\n <template #filler=\"state\">\r\n <div\r\n v-for=\"(point, index) in points\"\r\n :key=\"index\"\r\n :class=\"nh.be('progress-segment')\"\r\n :style=\"{ width: `${point.width}%` }\"\r\n >\r\n <div :class=\"nh.be('progress-track')\">\r\n <div\r\n :class=\"nh.be('progress-filler')\"\r\n :style=\"{\r\n visibility: state.percent[1] < point.startPercent ? 'hidden' : undefined,\r\n transform: `translateX(${Math.min(\r\n (Math.max(state.percent[1] - point.startPercent, 0) / point.durationPercent) *\r\n 100 -\r\n 100,\r\n 0,\r\n )}%) translateZ(0)`,\r\n }\"\r\n ></div>\r\n </div>\r\n </div>\r\n </template>\r\n <template #trigger>\r\n <slot name=\"trigger\">\r\n <div :class=\"nh.be('progress-trigger')\"></div>\r\n </slot>\r\n </template>\r\n </Slider>\r\n </ResizeObserver>\r\n <div\r\n :class=\"{\r\n [nh.be('progress-indicator')]: true,\r\n [nh.bem('progress-indicator', 'active')]: hovered && !sliding,\r\n }\"\r\n :style=\"{ transform: `translateX(${indicatorLeft}px) translateZ(0)` }\"\r\n ></div>\r\n <ResizeObserver v-if=\"!noPreview\" :on-resize=\"onPreviewResize\">\r\n <div\r\n ref=\"preview\"\r\n :class=\"{\r\n [nh.be('preview')]: true,\r\n [nh.bem('preview', 'has-image')]: previewSrc,\r\n [nh.bem('preview', 'active')]: hovered || sliding,\r\n }\"\r\n :style=\"{ transform: `translateX(${previewLeft}px) translateZ(0)` }\"\r\n >\r\n <slot name=\"preview\">\r\n <div v-if=\"previewSrc\" :class=\"nh.be('preview-image')\">\r\n <img :src=\"previewSrc\" />\r\n </div>\r\n <div :class=\"nh.be('preview-time')\">\r\n {{ formatSeconds(hoveredTime) + segmentLabel }}\r\n </div>\r\n </slot>\r\n </div>\r\n </ResizeObserver>\r\n </div>\r\n</template>\r\n"],"names":["props","__props","emit","__emit","nh","useNameHelper","locale","useLocale","timer","useSetTimeout","slidTime","ref","hovered","hoveredTime","indicatorLeft","previewLeft","paddingX","sliderWidth","previewWidth","wrapper","slider","sliderEl","computed","_a","preview","sliding","percent","className","points","duration","times","segment","i","len","start","end","pointDuration","segmentLabel","time","segments","index","title","getStepByWord","useListener","throttle","event","processMoveOnTrack","offsetX","boundRange","onSliderResize","entry","style","_b","onPreviewResize","handleChange","permillage","onSlideMove","onSlideStart","onSlideEnd","_createElementBlock","_createVNode","_unref","ResizeObserver","Slider","_normalizeClass","_withCtx","state","_openBlock","_Fragment","_renderList","point","_normalizeStyle","_createElementVNode","_renderSlot","_ctx","_createBlock","_hoisted_1","formatSeconds"],"mappings":"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"}