1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- <template>
- <video id="mxVideo" :src="safeUrl" controls :poster="coverUrl" object-fit="contain"
- @error="handleError" @timeupdate="handlePlaying" @ended="handlePlayEnd"
- @fullscreenchange="handleFullscreenChange"
- class="w-full aspect-video" v-bind="$attrs"></video>
- <view class="bg-white fx-row items-center px-30 gap-30 h-80">
- <text class="text-tips text-sm">倍速播放</text>
- <view class="fx-row items-center gap-10">
- <uv-tags v-for="rate in supportRates" :type="videoCtx?'primary':'info'" :text="`x`+rate"
- :plain="currentRate!=rate" size="mini" class="rate-item" @click="handleRate(rate)">
- </uv-tags>
- </view>
- </view>
- <uv-line/>
- </template>
- <script setup>
- import {computed, onUnmounted, ref} from 'vue'
- import {useEnvStore} from "@/hooks/useEnvStore";
- import {useVideoPlay} from "@/components/mx-video/useVideoPlay";
- import {useVideoRecord} from "@/components/mx-video/useVideoRecord";
- import {createPropDefine} from "@/utils";
- const props = defineProps({
- aliIdType: createPropDefine('', [String, Number]),
- src: createPropDefine(''),
- // 某些场景下,不需要全屏控制,
- // 因为视频可能是纯为手机端录制的,不需要旋转
- disabledFullScreen: createPropDefine(false, Boolean)
- })
- const emits = defineEmits(['change', 'error'])
- const videoCtx = ref(null)
- const currentRate = ref(1)
- const {safeUrl, coverUrl, onSrcChange} = useVideoPlay(props)
- const {reset: resetRecord, commit: commitRecord, syncProgress} = useVideoRecord()
- const {isAndroid, isIOS} = useEnvStore()
- const supportRates = computed(() => isAndroid.value ? [0.5, 0.8, 1.0, 1.25, 1.5] : [0.5, 1.0, 1.25, 1.5, 2.0])
- // const rateCtrlStyle = computed(() => isIOS.value
- // ? {marginTop: '-5px', height: '39.5px',}
- // : {marginTop: '-5px', height: '40px'})
- onSrcChange(() => {
- // 切换时,创建速度控制
- videoCtx.value = uni.createVideoContext('mxVideo')
- currentRate.value = 1
- })
- onSrcChange(async (newVal, oldVal) => {
- // 切换时,试图提交前一个视频的观看记录
- await commitRecord(oldVal)
- // 之后,重置记录功能
- resetRecord()
- })
- // 预留事件,向外抛出change事件
- onSrcChange((newVal, oldVal) => emits('change', newVal, oldVal))
- // 退出时,试图提交观看记录
- onUnmounted(() => commitRecord(props))
- // 播放完毕时,强制提交
- const handlePlayEnd = () => commitRecord(props)
- // 播放过程中,本地同步播放进度
- const handlePlaying = (e) => syncProgress(e.detail)
- const handleFullscreenChange = (e) => {
- if (props.disabledFullScreen) return
- uni.webView.postMessage({
- data: {
- action: 'fullscreen',
- data: e.detail
- }
- });
- }
- const handleRate = (rate) => {
- if (!videoCtx.value) return
- videoCtx.value.playbackRate(rate)
- currentRate.value = rate
- }
- const handleError = (e) => {
- if (!safeUrl.value) return // 此时不算异常
- console.log('mx-video error happens', e)
- emits("error", e)
- }
- </script>
- <style scoped>
- .rate-item {
- min-width: 42px;
- }
- ::v-deep .uv-tags {
- justify-content: center;
- }
- </style>
|