|
@@ -0,0 +1,163 @@
|
|
|
+import { defineComponent, onMounted, reactive, toRefs, watch } from 'vue';
|
|
|
+import { ref } from 'vue';
|
|
|
+import styles from './index.module.less';
|
|
|
+
|
|
|
+import iconLoop from '../../image/icon-loop.svg';
|
|
|
+import iconLoopActive from '../../image/icon-loop-active.svg';
|
|
|
+import iconplay from '../../image/icon-play.svg';
|
|
|
+import iconpause from '../../image/icon-pause.svg';
|
|
|
+import { NSlider } from 'naive-ui';
|
|
|
+import { getSecondRPM } from '@/helpers/utils';
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'video-play',
|
|
|
+ props: {
|
|
|
+ item: {
|
|
|
+ type: Object,
|
|
|
+ default: () => {
|
|
|
+ return {};
|
|
|
+ }
|
|
|
+ },
|
|
|
+ pageVisibility: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ show: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ showModel: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ isEmtry: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ emits: ['loadedmetadata', 'togglePlay', 'ended', 'reset'],
|
|
|
+ setup(props, { emit }) {
|
|
|
+ const { item, isEmtry } = toRefs(props);
|
|
|
+ const data = reactive({
|
|
|
+ timer: null as any,
|
|
|
+ currentTime: 0,
|
|
|
+ duration: 0,
|
|
|
+ loop: false,
|
|
|
+ playState: 'pause' as 'play' | 'pause',
|
|
|
+ vudio: null as any
|
|
|
+ });
|
|
|
+ const canvasRef: any = ref();
|
|
|
+ const elRef: any = ref();
|
|
|
+ const contetRef = ref();
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => props.show,
|
|
|
+ val => {
|
|
|
+ onToggleAudio('pause');
|
|
|
+ }
|
|
|
+ );
|
|
|
+ watch(
|
|
|
+ () => props.pageVisibility,
|
|
|
+ val => {
|
|
|
+ if (val === 'hidden' && props.show) {
|
|
|
+ onToggleAudio('pause');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ let playTimer = null as any;
|
|
|
+ // 切换音频播放
|
|
|
+ const onToggleAudio = (state: 'play' | 'pause') => {
|
|
|
+ clearTimeout(playTimer);
|
|
|
+ if (state === 'play') {
|
|
|
+ playTimer = setTimeout(() => {
|
|
|
+ elRef.value.play();
|
|
|
+ data.playState = 'play';
|
|
|
+ }, 100);
|
|
|
+ } else {
|
|
|
+ elRef.value.pause();
|
|
|
+ data.playState = 'pause';
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 加载成功 */
|
|
|
+ const onLoadedmetadata = () => {
|
|
|
+ data.duration = elRef.value.duration;
|
|
|
+ // // 加载成功后台, 如果是第一次加载, 且是show状态, 则播放
|
|
|
+ // if (props.show) {
|
|
|
+ // onToggleAudio('play');
|
|
|
+ // }
|
|
|
+ emit('loadedmetadata');
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 改变播放时间 */
|
|
|
+ const handleChangeTime = (val: number) => {
|
|
|
+ data.currentTime = val;
|
|
|
+ clearTimeout(data.timer);
|
|
|
+ data.timer = setTimeout(() => {
|
|
|
+ elRef.value.currentTime = val;
|
|
|
+ data.timer = null;
|
|
|
+ }, 300);
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 播放结束 */
|
|
|
+ const onEnded = () => {
|
|
|
+ data.playState = 'pause';
|
|
|
+ // emit('ended');
|
|
|
+ };
|
|
|
+ onMounted(() => {
|
|
|
+ console.log('加载');
|
|
|
+ });
|
|
|
+ return () => (
|
|
|
+ <div class={styles.videoWrap}>
|
|
|
+ <div class={styles.content}>
|
|
|
+ <div ref={contetRef} class={styles.contentWrap}>
|
|
|
+ <video
|
|
|
+ poster={props.item.coverImg}
|
|
|
+ src={isEmtry.value ? '' : item.value.content}
|
|
|
+ ref={elRef}
|
|
|
+ loop={data.loop}
|
|
|
+ onLoadedmetadata={onLoadedmetadata}
|
|
|
+ onTimeupdate={() => {
|
|
|
+ if (data.timer) return;
|
|
|
+ data.currentTime = elRef.value.currentTime;
|
|
|
+ }}
|
|
|
+ onEnded={onEnded}
|
|
|
+ playsinline="false"></video>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class={[styles.controls, props.showModel ? '' : styles.hide]}>
|
|
|
+ <div class={styles.time}>
|
|
|
+ <div>{getSecondRPM(data.currentTime)}</div>
|
|
|
+ <div>{getSecondRPM(data.duration)}</div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.slider}>
|
|
|
+ <NSlider
|
|
|
+ tooltip={false}
|
|
|
+ step={0.01}
|
|
|
+ class={styles.timeProgress}
|
|
|
+ value={data.currentTime}
|
|
|
+ max={data.duration}
|
|
|
+ onUpdate:value={val => handleChangeTime(val)}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class={styles.actions}>
|
|
|
+ <div
|
|
|
+ class={styles.actionBtn}
|
|
|
+ onClick={() =>
|
|
|
+ onToggleAudio(data.playState === 'pause' ? 'play' : 'pause')
|
|
|
+ }>
|
|
|
+ <img src={data.playState === 'pause' ? iconplay : iconpause} />
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class={styles.actionBtn}
|
|
|
+ onClick={() => (data.loop = !data.loop)}>
|
|
|
+ <img src={data.loop ? iconLoopActive : iconLoop} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|