|
@@ -15,7 +15,10 @@ import { ref } from 'vue';
|
|
|
import styles from './video.module.less';
|
|
|
import iconplay from '../image/icon-pause.png';
|
|
|
import iconpause from '../image/icon-play.png';
|
|
|
-import iconReplay from '../image/icon-replay.png';
|
|
|
+// import iconReplay from '../image/icon-replay.png';
|
|
|
+import iconLoop from '../image/icon-loop.svg';
|
|
|
+import iconLoopActive from '../image/icon-loop-active.svg';
|
|
|
+import iconSpeed from '../image/icon-speed.png';
|
|
|
import { NSlider } from 'naive-ui';
|
|
|
|
|
|
export default defineComponent({
|
|
@@ -55,11 +58,18 @@ export default defineComponent({
|
|
|
durationNum: 0,
|
|
|
duration: '00:00',
|
|
|
showBar: true,
|
|
|
- showAction: true
|
|
|
+ showAction: true,
|
|
|
+ loop: false,
|
|
|
+ speedControl: false,
|
|
|
+ speedStyle: {
|
|
|
+ left: '1px'
|
|
|
+ },
|
|
|
+ defaultSpeed: 1 // 默认速度
|
|
|
});
|
|
|
const videoRef = ref();
|
|
|
const videoItem = ref();
|
|
|
const videoID = ref('video' + Date.now() + Math.floor(Math.random() * 100));
|
|
|
+ const speedBtnId = 'speed' + Date.now() + Math.floor(Math.random() * 100);
|
|
|
|
|
|
// 对时间进行格式化
|
|
|
const timeFormat = (num: number) => {
|
|
@@ -86,6 +96,7 @@ export default defineComponent({
|
|
|
};
|
|
|
|
|
|
const onReplay = () => {
|
|
|
+ videoFroms.speedControl = false;
|
|
|
if (!videoItem.value) return;
|
|
|
videoItem.value.currentTime(0);
|
|
|
};
|
|
@@ -103,18 +114,15 @@ export default defineComponent({
|
|
|
emit('togglePlay', videoFroms.paused);
|
|
|
};
|
|
|
|
|
|
- onMounted(() => {
|
|
|
- videoItem.value = TCPlayer(videoID.value, {
|
|
|
- appID: '',
|
|
|
- controls: false
|
|
|
- }); // player-container-id 为播放器容器 ID,必须与 html 中一致
|
|
|
+ const __init = () => {
|
|
|
if (videoItem.value) {
|
|
|
videoItem.value.poster(props.item.coverImg); // 封面
|
|
|
videoItem.value.src(item.value.content); // url 播放地址
|
|
|
-
|
|
|
+ videoItem.value.playbackRate(videoFroms.defaultSpeed);
|
|
|
// 初步加载时
|
|
|
videoItem.value.one('loadedmetadata', () => {
|
|
|
- console.log(' Loading metadata');
|
|
|
+ // console.log(' Loading metadata');
|
|
|
+ videoItem.value.playbackRate(videoFroms.defaultSpeed);
|
|
|
|
|
|
// 获取时长
|
|
|
videoFroms.duration = timeFormat(
|
|
@@ -171,6 +179,20 @@ export default defineComponent({
|
|
|
console.log(e, 'error');
|
|
|
});
|
|
|
}
|
|
|
+ };
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
+ videoItem.value = TCPlayer(videoID.value, {
|
|
|
+ appID: '',
|
|
|
+ controls: false
|
|
|
+ }); // player-container-id 为播放器容器 ID,必须与 html 中一致
|
|
|
+
|
|
|
+ __init();
|
|
|
+
|
|
|
+ document.getElementById(speedBtnId)?.addEventListener('click', e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ videoFroms.speedControl = !videoFroms.speedControl;
|
|
|
+ });
|
|
|
});
|
|
|
const stop = () => {
|
|
|
videoItem.value.currentTime(0);
|
|
@@ -191,11 +213,13 @@ export default defineComponent({
|
|
|
|
|
|
watch(
|
|
|
() => props.item,
|
|
|
- (val, oldVal) => {
|
|
|
+ () => {
|
|
|
videoItem.value.pause();
|
|
|
videoItem.value.currentTime(0);
|
|
|
- videoItem.value.poster(props.item.coverImg); // 封面
|
|
|
- videoItem.value.src(item.value.content); // url 播放地址
|
|
|
+ // videoItem.value.poster(props.item.coverImg); // 封面
|
|
|
+ // videoItem.value.src(item.value.content); // url 播放地址
|
|
|
+ __init();
|
|
|
+
|
|
|
videoFroms.paused = true;
|
|
|
}
|
|
|
);
|
|
@@ -204,6 +228,7 @@ export default defineComponent({
|
|
|
() => {
|
|
|
// console.log(props.showModel, 'props.showModel')
|
|
|
videoFroms.showAction = props.showModel;
|
|
|
+ videoFroms.speedControl = false;
|
|
|
}
|
|
|
);
|
|
|
expose({
|
|
@@ -240,6 +265,7 @@ export default defineComponent({
|
|
|
<div
|
|
|
class={styles.actionBtn}
|
|
|
onClick={() => {
|
|
|
+ videoFroms.speedControl = false;
|
|
|
onToggleVideo();
|
|
|
}}>
|
|
|
{videoFroms.paused ? (
|
|
@@ -248,18 +274,13 @@ export default defineComponent({
|
|
|
<img class={styles.playIcon} src={iconpause} />
|
|
|
)}
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div class={styles.time}>
|
|
|
- <div
|
|
|
- class="plyr__time plyr__time--current"
|
|
|
- aria-label="Current time">
|
|
|
- {videoFroms.currentTime}
|
|
|
- </div>
|
|
|
- <span class={styles.line}>/</span>
|
|
|
- <div
|
|
|
- class="plyr__time plyr__time--duration"
|
|
|
- aria-label="Duration">
|
|
|
- {videoFroms.duration}
|
|
|
+
|
|
|
+ <button class={styles.iconReplay} onClick={onReplay}>
|
|
|
+ <img src={iconLoop} />
|
|
|
+ </button>
|
|
|
+
|
|
|
+ <div class={styles.actionBtnSpeed} id={speedBtnId}>
|
|
|
+ <img src={iconSpeed} />
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -271,6 +292,7 @@ export default defineComponent({
|
|
|
max={videoFroms.durationNum}
|
|
|
tooltip={false}
|
|
|
onUpdate:value={(val: number) => {
|
|
|
+ videoFroms.speedControl = false;
|
|
|
videoItem.value.currentTime(val);
|
|
|
videoFroms.currentTimeNum = val;
|
|
|
videoFroms.currentTime = timeFormat(Math.round(val || 0));
|
|
@@ -280,12 +302,82 @@ export default defineComponent({
|
|
|
|
|
|
<div class={styles.actions}>
|
|
|
<div class={styles.actionWrap}>
|
|
|
- <button class={styles.iconReplay} onClick={onReplay}>
|
|
|
- <img src={iconReplay} />
|
|
|
- </button>
|
|
|
+ <div class={styles.time}>
|
|
|
+ <div
|
|
|
+ class="plyr__time plyr__time--current"
|
|
|
+ aria-label="Current time">
|
|
|
+ {videoFroms.currentTime}
|
|
|
+ </div>
|
|
|
+ <span class={styles.line}>/</span>
|
|
|
+ <div
|
|
|
+ class="plyr__time plyr__time--duration"
|
|
|
+ aria-label="Duration">
|
|
|
+ {videoFroms.duration}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ style={{
|
|
|
+ display: videoFroms.speedControl ? 'block' : 'none'
|
|
|
+ }}>
|
|
|
+ <div
|
|
|
+ class={styles.sliderPopup}
|
|
|
+ onClick={(e: Event) => {
|
|
|
+ e.stopPropagation();
|
|
|
+ }}>
|
|
|
+ <i
|
|
|
+ class={styles.iconAdd}
|
|
|
+ onClick={() => {
|
|
|
+ if (videoFroms.defaultSpeed >= 1.5) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (videoItem.value) {
|
|
|
+ videoFroms.defaultSpeed =
|
|
|
+ (videoFroms.defaultSpeed * 10 + 1) / 10;
|
|
|
+ videoItem.value.playbackRate(videoFroms.defaultSpeed);
|
|
|
+ }
|
|
|
+ }}></i>
|
|
|
+ <NSlider
|
|
|
+ value={videoFroms.defaultSpeed}
|
|
|
+ step={0.1}
|
|
|
+ max={1.5}
|
|
|
+ min={0.6}
|
|
|
+ vertical
|
|
|
+ tooltip={false}
|
|
|
+ onUpdate:value={(val: number) => {
|
|
|
+ videoFroms.defaultSpeed = val;
|
|
|
+
|
|
|
+ if (videoItem.value) {
|
|
|
+ videoItem.value.playbackRate(videoFroms.defaultSpeed);
|
|
|
+ }
|
|
|
+ }}>
|
|
|
+ {{
|
|
|
+ thumb: () => (
|
|
|
+ <div class={styles.sliderPoint}>
|
|
|
+ {videoFroms.defaultSpeed}
|
|
|
+ <span>x</span>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </NSlider>
|
|
|
+ <i
|
|
|
+ class={[styles.iconCut]}
|
|
|
+ onClick={() => {
|
|
|
+ if (videoFroms.defaultSpeed <= 0.6) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (videoItem.value) {
|
|
|
+ videoFroms.defaultSpeed =
|
|
|
+ (videoFroms.defaultSpeed * 10 - 1) / 10;
|
|
|
+ videoItem.value.playbackRate(videoFroms.defaultSpeed);
|
|
|
+ }
|
|
|
+ }}></i>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
);
|
|
|
}
|