fix: 完成视频组件,并支持属性实时控制video状态

This commit is contained in:
tnt group 2022-09-19 12:32:27 +08:00
parent a2e2373dfd
commit 4f55b881db
3 changed files with 83 additions and 81 deletions

View File

@ -3,15 +3,22 @@ import { CreateComponentType } from '@/packages/index.d'
import { VideoConfig } from './index' import { VideoConfig } from './index'
import cloneDeep from 'lodash/cloneDeep' import cloneDeep from 'lodash/cloneDeep'
export const VideoList = [
{ label: '数字楼宇', value: 'https://video.699pic.com/videos/76/09/36/b_D4DKnb48qdCI1631760936.mp4' },
{ label: '旋转魔方', value: 'https://video.699pic.com/videos/90/02/69/b_YjJAJZMT6vRK1554900269.mp4' },
{ label: '旋转地球', value: 'https://video.699pic.com/videos/32/13/12/b_7dng21IHECP51553321312.mp4' },
{ label: '声音示例', value: 'https://video.699pic.com/videos/80/62/39/a_qmbxMqNvK9jr1583806239.mp4' }
]
export const option = { export const option = {
// 视频路径 // 视频路径
dataset: '', dataset: '',
// 适应方式 // 循环播放
fit: 'contain', loop: true,
// 圆角 // 自动播放
borderRadius: 0, autoplay: true,
// 透明度 // 静音
opacity: 1 muted: true
} }
export default class Config extends PublicConfigClass implements CreateComponentType { export default class Config extends PublicConfigClass implements CreateComponentType {

View File

@ -1,26 +1,40 @@
<!-- eslint-disable vue/multi-word-component-names -->
<!-- eslint-disable vue/no-mutating-props -->
<template> <template>
<collapse-item name="属性" :expanded="true"> <collapse-item name="视频" expanded>
<setting-item-box name="路径" :alone="true"> <setting-item-box name="源" alone>
<setting-item> <setting-item name="自定义视频源">
<n-input v-model:value="optionData.dataset" size="small"></n-input> <n-input v-model:value="optionData.dataset" size="small"></n-input>
</setting-item> </setting-item>
<setting-item> <setting-item name="使用内置视频">
<n-upload action="https://www.mocky.io/v2/5e4bafc63100007100d8b70f" @finish="handleFinish"> <n-select
v-model:value="optionData.dataset"
size="small"
placeholder="自定义或选择内置视频"
clearable
:options="VideoList"
></n-select>
</setting-item>
<!-- <setting-item>
<n-upload
action="https://www.mocky.io/v2/5e4bafc63100007100d8b70f"
accept="video/*"
@finish="finishHandleFinish"
>
<n-button size="small">本地上传</n-button> <n-button size="small">本地上传</n-button>
</n-upload> </n-upload>
</setting-item> </setting-item> -->
</setting-item-box> </setting-item-box>
<setting-item-box name="样式">
<setting-item name="类型"> <setting-item-box name="控制">
<n-select v-model:value="optionData.fit" size="small" :options="fitList"></n-select> <setting-item>
<n-checkbox v-model:checked="optionData.autoplay" size="small">自动播放</n-checkbox>
</setting-item> </setting-item>
<setting-item name="圆角"> <setting-item>
<n-input-number <n-checkbox v-model:checked="optionData.loop" size="small">循环播放</n-checkbox>
v-model:value="optionData.borderRadius" </setting-item>
size="small" <setting-item>
:min="0" <n-checkbox v-model:checked="optionData.muted" size="small">静音</n-checkbox>
placeholder="圆角"
></n-input-number>
</setting-item> </setting-item>
</setting-item-box> </setting-item-box>
</collapse-item> </collapse-item>
@ -28,9 +42,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from 'vue' import { PropType } from 'vue'
import { option } from './config' import { option, VideoList } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
// eslint-disable-next-line no-unused-vars
const props = defineProps({ const props = defineProps({
optionData: { optionData: {
type: Object as PropType<typeof option>, type: Object as PropType<typeof option>,
@ -38,27 +53,8 @@ const props = defineProps({
} }
}) })
// // eslint-disable-next-line no-unused-vars
const fitList = [ const finishHandleFinish = () => {
{ // console.log()
value: 'fill', }
label: 'fill'
},
{
value: 'contain',
label: 'contain'
},
{
value: 'cover',
label: 'cover'
},
{
value: 'scale-down',
label: 'scale-down'
},
{
value: 'none',
label: 'none'
}
]
</script> </script>

View File

@ -1,25 +1,25 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template> <template>
<div :style="getStyle(borderRadius)"> <video
<video ref="vVideoRef"
class="video-background" class="go-video"
preload="auto" preload="auto"
loop playsinline
playsinline :loop="option.loop"
autoplay :autoplay="option.autoplay"
muted :muted="option.muted"
src="https://video.699pic.com/videos/76/09/36/b_D4DKnb48qdCI1631760936.mp4" :width="w"
:width="w" :height="h"
:height="h" :src="option.dataset"
></video> ></video>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, shallowReactive, watch, toRefs } from 'vue' import { PropType, toRefs, shallowReactive, watch, ref } from 'vue'
import { useChartDataFetch } from '@/hooks' import { useChartDataFetch } from '@/hooks'
import { CreateComponentType } from '@/packages/index.d' import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { option } from './config' import { option as configOption } from './config'
const props = defineProps({ const props = defineProps({
chartConfig: { chartConfig: {
@ -29,41 +29,40 @@ const props = defineProps({
}) })
const { w, h } = toRefs(props.chartConfig.attr) const { w, h } = toRefs(props.chartConfig.attr)
const { dataset, fit, borderRadius } = toRefs(props.chartConfig.option) let option = shallowReactive({ ...configOption })
const option = shallowReactive({ //
dataset: '' const vVideoRef = ref(null)
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
option = newData
}) })
const getStyle = (radius: number) => {
return {
borderRadius: `${radius}px`,
overflow: 'hidden'
}
}
// //
watch( watch(
() => props.chartConfig.option.dataset, () => props.chartConfig.option,
(newData: any) => { (newData: any) => {
option.dataset = newData option = newData
if (!vVideoRef.value) return
const video: any = vVideoRef.value
video.loop = option.loop
video.autoplay = option.autoplay
video.muted = option.muted
//
!option.autoplay && (video.pause(), (video.currentTime = 0))
option.autoplay && video.play()
}, },
{ {
immediate: true, immediate: true,
deep: false deep: true
} }
) )
//
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
option.dataset = newData
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.video-background { @include go('video') {
display: block;
object-fit: cover; object-fit: cover;
mix-blend-mode: screen; mix-blend-mode: screen;
opacity: 1;
} }
</style> </style>