Files
lucky_shop/components-diy/diy-video.vue

189 lines
4.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="video-container" :style="containerStyle">
<!-- H5端使用原生video标签 -->
<!-- #ifdef H5 -->
<video
ref="videoRef"
data-component-name="diy-video"
class="diy-video h5-video"
:src="getVideoUrl()"
:poster="$util.img(value.imageUrl)"
:style="videoWarpCss"
controls
preload="auto"
@loadedmetadata="onVideoLoaded"
@click="handlerClick(getVideoUrl())"
></video>
<!-- #endif -->
<!-- 微信小程序端使用uni-app的video组件 -->
<!-- #ifdef MP-WEIXIN -->
<video
ref="videoRef"
data-component-name="diy-video"
class="diy-video mp-video"
:src="getVideoUrl()"
:poster="$util.img(value.imageUrl)"
:style="videoWarpCss"
objectFit="contain"
controls
@loadedmetadata="onVideoLoaded"
@tap="handlerClick(getVideoUrl())"
></video>
<!-- #endif -->
</view>
</template>
<script>
// 视频
import DiyMinx from './minx.js'
export default {
name: 'diy-video',
props: {
value: {
type: Object
}
},
data() {
return {
videoRatio: null // 视频比例:'landscape'(横屏)或 'portrait'(竖屏)
};
},
created() { },
mixins: [DiyMinx],
watch: {
// 组件刷新监听
componentRefresh: function (nval) { }
},
computed: {
videoWarpCss: function () {
var obj = '';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
return obj;
},
// 动态计算容器比例
containerStyle() {
let style = '';
if (this.videoRatio) {
// 已加载并识别出比例
if (this.videoRatio === 'portrait') {
// 竖屏视频:9/16比例
style += 'aspect-ratio: 9 / 16;';
} else {
// 横屏视频:16/9比例
style += 'aspect-ratio: 16 / 9;';
}
} else {
// 未加载完成 → 默认使用竖屏比例(适合短视频)
style += 'aspect-ratio: 9 / 16;';
}
return style;
}
},
methods: {
// 获取视频URL,根据格式决定是否使用$util.img()处理
getVideoUrl() {
if (!this.value || !this.value.videoUrl) return '';
const videoUrl = this.value.videoUrl;
// 如果是完整的http/https链接,直接使用
if (videoUrl.indexOf('http://') === 0 || videoUrl.indexOf('https://') === 0) {
return videoUrl;
}
// 否则使用$util.img()处理
return this.$util.img(videoUrl);
},
// 视频加载完成事件
onVideoLoaded(event) {
this.$nextTick(() => {
let width = 0;
let height = 0;
// H5端:通过video元素获取真实视频宽高
// #ifdef H5
const video = this.$refs.videoRef;
if (video) {
width = video.videoWidth || 0;
height = video.videoHeight || 0;
}
// #endif
// 微信小程序端:通过事件对象获取视频宽高
// #ifdef MP-WEIXIN
if (event && event.detail) {
width = event.detail.width || 0;
height = event.detail.height || 0;
}
// #endif
if (width && height) {
// 判断视频方向:宽度 >= 高度为横屏,否则为竖屏
this.videoRatio = width >= height ? 'landscape' : 'portrait';
console.log(`视频宽高比检测: ${width}x${height}, 比例: ${this.videoRatio}`);
} else {
// 获取失败,默认竖屏
this.videoRatio = 'portrait';
console.log('视频宽高比检测失败,默认使用竖屏比例');
}
});
},
async handlerClick(videoUrl) {
await this.__$emitEvent({
eventName: 'video-tap', data: videoUrl, promiseCallback: (event, handler, awaitedResult) => {
if (!awaitedResult) return;
}
})
}
}
};
</script>
<style scoped>
.video-container {
width: 100%;
position: relative;
overflow: hidden;
}
/* 基础样式 */
.diy-video {
width: 100%;
height: 100%;
}
/* H5端样式 */
/* #ifdef H5 */
.h5-video {
display: block;
object-fit: contain; /* 改为contain以保持视频比例 */
background-color: #000; /* 添加背景色 */
}
/* #endif */
/* 微信小程序端样式 */
/* #ifdef MP-WEIXIN */
.mp-video {
position: absolute;
top: 0;
left: 0;
background-color: #000; /* 添加背景色 */
}
.mp-video>>>.uni-video-container {
background-color: transparent;
height: 100%;
}
.mp-video>>>.uni-video-control {
display: flex;
}
/* #endif */
</style>