@cqmcui/cqmcui
Version:
轻量级移动端 Vue2、Vue3 组件库(支持小程序开发)
409 lines (408 loc) • 13.6 kB
JavaScript
import { reactive, ref, computed, watch, nextTick, onMounted, toRefs, openBlock, createElementBlock, createElementVNode, createCommentVNode, withDirectives, vShow, normalizeClass, toDisplayString, normalizeStyle, withModifiers } from "vue";
import { c as createComponent } from "./component-81a4c1d0.js";
import { _ as _export_sfc } from "./_plugin-vue_export-helper-cc2b3d55.js";
import "../locale/lang";
function throttle(fn, delay) {
let timer = null;
let startTime = Date.now();
return function() {
let now = Date.now();
let remaining = delay - (now - startTime);
if (timer)
clearTimeout(timer);
if (remaining <= 0) {
fn.apply(null, arguments);
startTime = Date.now();
} else {
timer = setTimeout(fn, remaining);
}
};
}
const { create, translate } = createComponent("video");
const _sfc_main = create({
props: {
source: {
type: Object,
default: {}
},
options: {
type: Object,
default: {
autoplay: false,
//是否自动播放
volume: 0.5,
poster: "",
loop: false,
controls: true,
muted: false,
//是否静音
disabled: false,
//禁止操作
playsinline: false,
//行内展示
touchPlay: false,
preload: ""
},
required: true
},
model: {
type: String,
default: ""
}
},
components: {},
emits: ["click", "play", "pause", "playend", "time"],
setup(props, { emit }) {
const state = reactive({
videoElm: null,
initial: true,
//控制封面的显示
showToolbox: false,
//控制控制器和标题的显示
// 视频容器元素
player: {
$player: null,
pos: null
},
// progress进度条元素
progressBar: {
progressElm: null,
// 进度条DOM对象
pos: null
},
// video控制显示设置
videoSet: {
loaded: 0,
// 缓存长度
displayTime: "00:00",
// 进度时间
totalTime: "00:00",
// 总时间
progress: {
width: 0,
// 进度条长度
current: 0
// 进度条当前位置
}
},
state: {
controlShow: true,
vol: 0.5,
//音量
currentTime: 0,
//当前时间
fullScreen: false,
playing: false,
//是否正在播放
isLoading: false,
isEnd: false,
isError: false,
isMuted: false
},
showTouchMask: false
});
const root = ref(null);
const isDisabled = computed(() => {
return props.options.disabled;
});
watch(
() => props.source,
(newValue) => {
if (newValue.src) {
nextTick(() => {
state.videoElm.load();
});
}
},
{ immediate: true, deep: true }
);
watch(
() => props.options,
(newValue) => {
state.state.isMuted = newValue ? newValue.muted : false;
},
{ immediate: true }
);
const init = () => {
state.videoElm = root.value;
if (props.options.autoplay) {
setTimeout(() => {
state.videoElm.play();
}, 200);
}
if (props.options.touchPlay) {
state.showTouchMask = true;
}
if (props.options.playsinline) {
state.videoElm.setAttribute("playsinline", props.options.playsinline);
state.videoElm.setAttribute("webkit-playsinline", props.options.playsinline);
state.videoElm.setAttribute("x5-video-player-type", "h5-page");
state.videoElm.setAttribute("x5-video-player-fullscreen", false);
}
volumeHandle();
if (state.showToolbox) {
customerInit();
} else {
state.videoElm.addEventListener("play", () => {
state.state.playing = true;
emit("play", state.videoElm);
});
state.videoElm.addEventListener("pause", () => {
state.state.playing = false;
emit("pause", state.videoElm);
});
state.videoElm.addEventListener("ended", playEnded);
state.videoElm.addEventListener("timeupdate", throttle(getPlayTime, 1e3));
}
};
const customerInit = () => {
const $player = root.value;
const $progress = root.value.getElementsByClassName("cqmc-video-controller__progress-value")[0];
state.player.$player = $player;
state.progressBar.progressElm = $progress;
state.progressBar.pos = $progress.getBoundingClientRect();
state.videoSet.progress.width = Math.round($progress.getBoundingClientRect().width);
};
const play = () => {
if (props.options.autoplay && props.options.disabled) {
state.state.playing = true;
return false;
}
state.state.playing = !state.state.playing;
if (state.videoElm) {
if (state.state.playing) {
try {
setTimeout(() => {
state.videoElm.play();
}, 200);
state.videoElm.addEventListener("progress", () => {
getLoadTime();
});
state.videoElm.addEventListener("timeupdate", throttle(getPlayTime, 1e3));
state.videoElm.addEventListener("ended", playEnded);
emit("play", state.videoElm);
} catch (e) {
handleError();
}
} else {
state.videoElm.pause();
emit("pause", state.videoElm);
}
}
};
const timeFormat = (t) => {
var h = Math.floor(t / 3600);
if (h < 10) {
h = "0" + h;
}
var m = Math.floor(t % 3600 / 60);
if (m < 10) {
m = "0" + m;
}
var s = Math.round(t % 3600 % 60);
if (s < 10) {
s = "0" + s;
}
var str = "";
if (h != 0) {
str = h + ":" + m + ":" + s;
} else {
str = m + ":" + s;
}
return str;
};
const getLoadTime = () => {
if (state.videoSet.loaded)
state.videoSet.loaded = state.videoElm.buffered.end(0) / state.videoElm.duration * 100;
};
const getPlayTime = () => {
const percent = state.videoElm.currentTime / state.videoElm.duration;
state.videoSet.progress.current = Math.round(state.videoSet.progress.width * percent);
state.videoSet.totalTime = timeFormat(state.videoElm.duration);
state.videoSet.displayTime = timeFormat(state.videoElm.currentTime);
emit("time", state.videoSet.displayTime, state.videoSet.totalTime);
};
const playEnded = () => {
state.state.playing = false;
state.state.isEnd = true;
state.videoSet.displayTime = "00:00";
state.videoSet.progress.current = 0;
state.videoElm.currentTime = 0;
emit("playend", state.videoElm);
};
const handleError = () => {
state.state.isError = true;
};
const volumeHandle = () => {
state.state.vol = props.options.volume;
};
const handleMuted = () => {
state.state.isMuted = !state.state.isMuted;
state.videoElm.muted = state.state.isMuted;
};
const touchSlidSrart = () => {
};
const touchSlidMove = (e) => {
let currentX = e.targetTouches[0].pageX;
let offsetX = currentX - state.progressBar.pos.left;
if (offsetX <= 0) {
offsetX = 0;
}
if (offsetX >= state.videoSet.progress.width) {
offsetX = state.videoSet.progress.width;
}
state.videoSet.progress.current = offsetX;
let percent = state.videoSet.progress.current / state.videoSet.progress.width;
state.videoElm.duration && setPlayTime(percent, state.videoElm.duration);
};
const touchSlidEnd = (e) => {
let currentX = e.changedTouches[0].pageX;
let offsetX = currentX - state.progressBar.pos.left;
state.videoSet.progress.current = offsetX;
let percent = offsetX / state.videoSet.progress.width;
state.videoElm.duration && setPlayTime(percent, state.videoElm.duration);
};
const setPlayTime = (percent, totalTime) => {
state.videoElm.currentTime = Math.floor(percent * totalTime);
};
const retry = () => {
state.state.isError = false;
init();
};
const fullScreen = () => {
if (!state.state.fullScreen) {
state.state.fullScreen = true;
state.videoElm.webkitRequestFullScreen();
} else {
state.state.fullScreen = false;
document.webkitCancelFullScreen();
}
};
onMounted(() => {
init();
});
return {
root,
...toRefs(props),
...toRefs(state),
handleError,
isDisabled,
play,
handleMuted,
touchSlidSrart,
touchSlidMove,
touchSlidEnd,
retry,
fullScreen,
translate
};
}
});
const _hoisted_1 = {
class: "cqmc-video",
ref: "videocon"
};
const _hoisted_2 = ["muted", "autoplay", "loop", "poster", "controls", "preload"];
const _hoisted_3 = ["src", "type"];
const _hoisted_4 = { class: "cqmc-video-controller__now" };
const _hoisted_5 = { class: "cqmc-video-controller__progress" };
const _hoisted_6 = {
class: "cqmc-video-controller__progress-value",
ref: "progressBar"
};
const _hoisted_7 = /* @__PURE__ */ createElementVNode("div", { class: "cqmc-video-controller__ball-move" }, null, -1);
const _hoisted_8 = [
_hoisted_7
];
const _hoisted_9 = {
class: "cqmc-video-controller__played",
ref: "playedBar"
};
const _hoisted_10 = { class: "cqmc-video-controller__total" };
const _hoisted_11 = { class: "cqmc-video-error" };
const _hoisted_12 = { class: "cqmc-video-error-tip" };
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return openBlock(), createElementBlock("div", _hoisted_1, [
createElementVNode("video", {
ref: "root",
class: "cqmc-video-player",
muted: _ctx.options.muted,
autoplay: _ctx.options.autoplay,
loop: _ctx.options.loop,
poster: _ctx.options.poster,
controls: _ctx.options.controls,
preload: _ctx.options.preload,
onError: _cache[0] || (_cache[0] = (...args) => _ctx.handleError && _ctx.handleError(...args))
}, [
createElementVNode("source", {
src: _ctx.source.src,
type: _ctx.source.type
}, null, 8, _hoisted_3)
], 40, _hoisted_2),
_ctx.showToolbox && !_ctx.isDisabled ? (openBlock(), createElementBlock("div", {
key: 0,
class: "cqmc-video-mask",
ref: "touchMask",
onClick: _cache[1] || (_cache[1] = (...args) => _ctx.play && _ctx.play(...args))
}, null, 512)) : createCommentVNode("", true),
_ctx.showToolbox && !_ctx.isDisabled ? withDirectives((openBlock(), createElementBlock("div", {
key: 1,
class: "cqmc-video-play-btn",
ref: "palyBtn",
onClick: _cache[2] || (_cache[2] = (...args) => _ctx.play && _ctx.play(...args))
}, null, 512)), [
[vShow, !_ctx.state.playing]
]) : createCommentVNode("", true),
withDirectives(createElementVNode("div", {
class: normalizeClass(["cqmc-video-controller", { "cqmc-video-controller--show": !_ctx.state.playing, "cqmc-video-controller--hide": _ctx.state.playing }])
}, [
createElementVNode("div", {
class: "cqmc-video-controller__playbtn",
onClick: _cache[3] || (_cache[3] = (...args) => _ctx.play && _ctx.play(...args))
}),
createElementVNode("div", _hoisted_4, toDisplayString(_ctx.videoSet.displayTime), 1),
createElementVNode("div", _hoisted_5, [
createElementVNode("div", _hoisted_6, [
createElementVNode("div", {
class: "buffered",
style: normalizeStyle({ width: `${_ctx.videoSet.loaded}%` })
}, null, 4),
createElementVNode("div", {
class: "cqmc-video-controller__ball",
style: normalizeStyle({
transform: `translate3d(${_ctx.videoSet.progress.current}px, -50%, 0)`
}),
onTouchmove: _cache[4] || (_cache[4] = withModifiers(($event) => _ctx.touchSlidMove($event), ["stop", "prevent"])),
onTouchstart: _cache[5] || (_cache[5] = withModifiers(($event) => _ctx.touchSlidSrart(), ["stop"])),
onTouchend: _cache[6] || (_cache[6] = withModifiers(($event) => _ctx.touchSlidEnd($event), ["stop"]))
}, _hoisted_8, 36),
createElementVNode("div", _hoisted_9, null, 512)
], 512)
]),
createElementVNode("div", _hoisted_10, toDisplayString(_ctx.videoSet.totalTime), 1),
createElementVNode("div", {
class: normalizeClass(["cqmc-video-controller__volume", { muted: _ctx.state.isMuted }]),
onClick: _cache[7] || (_cache[7] = (...args) => _ctx.handleMuted && _ctx.handleMuted(...args))
}, null, 2),
createElementVNode("div", {
class: "cqmc-video-controller__full",
onClick: _cache[8] || (_cache[8] = (...args) => _ctx.fullScreen && _ctx.fullScreen(...args))
})
], 2), [
[vShow, _ctx.showToolbox && !_ctx.isDisabled]
]),
withDirectives(createElementVNode("div", _hoisted_11, [
createElementVNode("p", _hoisted_12, toDisplayString(_ctx.translate("errorTip")), 1),
createElementVNode("p", {
class: "cqmc-video-error-retry",
onClick: _cache[9] || (_cache[9] = (...args) => _ctx.retry && _ctx.retry(...args))
}, toDisplayString(_ctx.translate("clickRetry")), 1)
], 512), [
[vShow, _ctx.state.isError]
])
], 512);
}
const Video = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
export {
Video as default
};