!50 feat: 新增视频组件

Merge pull request !50 from dodu/dev-video
This commit is contained in:
奔跑的面条 2022-09-22 11:30:40 +00:00 committed by Gitee
commit f1e801340f
8 changed files with 195 additions and 3 deletions

View File

@ -0,0 +1,26 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { VideoConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
import video from '@/assets/videos/earth.mp4'
export const option = {
// 视频路径
dataset: video,
// 循环播放
loop: true,
// 自动播放
autoplay: true,
// 静音
muted: true,
// 适应方式
fit: 'contain',
// 圆角
borderRadius: 10
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = VideoConfig.key
public chartConfig = cloneDeep(VideoConfig)
public option = cloneDeep(option)
}

View File

@ -0,0 +1,74 @@
<!-- eslint-disable vue/multi-word-component-names -->
<!-- eslint-disable vue/no-mutating-props -->
<template>
<collapse-item name="视频" expanded>
<setting-item-box name="源" alone>
<setting-item name="自定义源">
<n-input v-model:value="optionData.dataset" size="small"></n-input>
</setting-item>
</setting-item-box>
<setting-item-box name="控制">
<setting-item>
<n-checkbox v-model:checked="optionData.autoplay" size="small">自动播放</n-checkbox>
</setting-item>
<setting-item>
<n-checkbox v-model:checked="optionData.loop" size="small">循环播放</n-checkbox>
</setting-item>
<setting-item>
<n-checkbox v-model:checked="optionData.muted" size="small">静音</n-checkbox>
</setting-item>
</setting-item-box>
<setting-item-box name="样式">
<setting-item name="类型">
<n-select v-model:value="optionData.fit" size="small" :options="fitList"></n-select>
</setting-item>
<setting-item name="圆角">
<n-input-number
v-model:value="optionData.borderRadius"
size="small"
:min="0"
placeholder="圆角"
></n-input-number>
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { option } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
//
const fitList = [
{
value: 'fill',
label: 'fill'
},
{
value: 'contain',
label: 'contain'
},
{
value: 'cover',
label: 'cover'
},
{
value: 'scale-down',
label: 'scale-down'
},
{
value: 'none',
label: 'none'
}
]
defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
</script>

View File

@ -0,0 +1,14 @@
import image from '@/assets/images/chart/informations/photo.png'
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const VideoConfig: ConfigType = {
key: 'Video',
chartKey: 'VVideo',
conKey: 'VCVideo',
title: '视频',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.INFORMATIONS,
image
}

View File

@ -0,0 +1,71 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<!-- 重要需要设置 crossOrigin="anonymous"否则保存画板缩略图会失败 -->
<video
ref="vVideoRef"
class="go-video"
preload="auto"
crossOrigin="anonymous"
playsinline
:loop="option.loop"
:autoplay="option.autoplay"
:muted="option.muted"
:width="w"
:height="h"
:src="option.dataset"
></video>
</template>
<script setup lang="ts">
import { PropType, toRefs, shallowReactive, watch, ref } from 'vue'
import { useChartDataFetch } from '@/hooks'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { option as configOption } from './config'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const { w, h } = toRefs(props.chartConfig.attr)
let option = shallowReactive({ ...configOption })
//
const vVideoRef = ref(null)
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
option = newData
})
//
watch(
() => props.chartConfig.option,
(newData: any) => {
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,
deep: true
}
)
</script>
<style lang="scss" scoped>
@include go('video') {
display: block;
mix-blend-mode: screen;
object-fit: v-bind('option.fit');
border-radius: v-bind('option.borderRadius');
}
</style>

View File

@ -1,4 +1,5 @@
import { TextCloudConfig } from './TextCloud/index'
import { ImageConfig } from './Image/index'
import { VideoConfig } from './Video/index'
export default [ImageConfig, TextCloudConfig]
export default [ImageConfig, VideoConfig, TextCloudConfig]

View File

@ -69,6 +69,10 @@ const select = computed(() => {
@include go(shape-box) {
position: absolute;
cursor: move;
//
mix-blend-mode: screen;
/* 锚点 */
.shape-point {
z-index: 1;

View File

@ -4,7 +4,7 @@
v-for="item in groupData.groupList"
:class="animationsClass(item.styles.animations)"
:key="item.id"
:style="{
:style="{
...getComponentAttrStyle(item.attr, groupIndex),
...getFilterStyle(item.styles),
...getTransformStyle(item.styles)
@ -15,7 +15,7 @@
:chartConfig="item"
:themeSetting="themeSetting"
:themeColor="themeColor"
:style="{...getSizeStyle(item.attr)}"
:style="{ ...getSizeStyle(item.attr) }"
></component>
</div>
</template>
@ -49,5 +49,6 @@ const props = defineProps({
<style lang="scss" scoped>
.chart-item {
position: absolute;
mix-blend-mode: screen;
}
</style>

View File

@ -63,5 +63,6 @@ const themeColor = computed(() => {
<style lang="scss" scoped>
.chart-item {
position: absolute;
mix-blend-mode: screen;
}
</style>