1
|
1
|
<template>
|
2
|
|
- <div class="go-content-box" :style="{ width: w + 'px', height: h + 'px' }">
|
3
|
|
- <video id="my-player" ref="videoRef" class="video-js my-video vjs-theme-city vjs-big-play-centered">
|
4
|
|
- <source :src="dataset" />
|
5
|
|
- </video>
|
|
2
|
+ <div class="banner-box" ref="root">
|
|
3
|
+ <div class="wrapper">
|
|
4
|
+ <div v-for="(item, index) in option.dataset" :key="index + item" :class="item.className" :style="item.sty">
|
|
5
|
+ <CameraItem ref="cameraRef" :key="item + index" :sourceSrc="item.url" :w="w" :h="h" :index="index" />
|
|
6
|
+ </div>
|
|
7
|
+ </div>
|
|
8
|
+ <a href="javascript:;" class="left" @click="changeSlide('left')"></a>
|
|
9
|
+ <a href="javascript:;" class="right" @click="changeSlide('right')"></a>
|
6
|
10
|
</div>
|
7
|
11
|
</template>
|
8
|
12
|
<script setup lang="ts">
|
9
|
|
-import { PropType, onMounted, ref, watch, toRefs, onUnmounted } from 'vue'
|
|
13
|
+import { PropType, watch, toRefs, shallowReactive, onMounted, ref } from 'vue'
|
10
|
14
|
import { CreateComponentType } from '@/packages/index.d'
|
11
|
|
-import videojs from 'video.js'
|
12
|
|
-import type { VideoJsPlayerOptions } from 'video.js'
|
13
|
15
|
import 'video.js/dist/video-js.min.css'
|
|
16
|
+import { option as configOption } from './config'
|
|
17
|
+import CameraItem from './cameraItem.vue'
|
14
|
18
|
|
15
|
19
|
const props = defineProps({
|
16
|
20
|
chartConfig: {
|
...
|
...
|
@@ -21,66 +25,165 @@ const props = defineProps({ |
21
|
25
|
|
22
|
26
|
const { w, h } = toRefs(props.chartConfig.attr)
|
23
|
27
|
|
24
|
|
-const { dataset } = toRefs(props.chartConfig.option)
|
|
28
|
+const option = shallowReactive({
|
|
29
|
+ dataset: configOption.dataset
|
|
30
|
+})
|
25
|
31
|
|
26
|
|
-// video标签
|
27
|
|
-const videoRef = ref<HTMLElement | null>(null)
|
|
32
|
+const cameraRef = ref<InstanceType<typeof CameraItem>>()
|
28
|
33
|
|
29
|
|
-// video实例对象
|
30
|
|
-let videoPlayer: videojs.Player | null = null
|
|
34
|
+let initial = ref(0)
|
31
|
35
|
|
32
|
|
-//options配置
|
33
|
|
-const options: VideoJsPlayerOptions = {
|
34
|
|
- language: 'zh-CN', // 设置语言
|
35
|
|
- controls: true, // 是否显示控制条
|
36
|
|
- preload: 'auto', // 预加载
|
37
|
|
- autoplay: true, // 是否自动播放
|
38
|
|
- fluid: false, // 自适应宽高
|
39
|
|
- src: dataset?.value, // 要嵌入的视频源的源 URL
|
40
|
|
- muted:true,
|
41
|
|
- userActions: {
|
42
|
|
- hotkeys: true
|
43
|
|
- }
|
44
|
|
-}
|
|
36
|
+let interval = ref(4000)
|
45
|
37
|
|
46
|
|
-// 初始化videojs
|
47
|
|
-const initVideo = () => {
|
48
|
|
- if (videoRef.value) {
|
49
|
|
- // 创建 video 实例
|
50
|
|
- videoPlayer = videojs(videoRef.value, options)
|
51
|
|
- }
|
|
38
|
+const computedFunc = (initial: number, source: any) => {
|
|
39
|
+ if (initial < 0) initial = 0
|
|
40
|
+ let len = source.length,
|
|
41
|
+ temp1 = initial - 2 < 0 ? initial - 2 + len : initial - 2,
|
|
42
|
+ temp2 = initial - 1 < 0 ? initial - 1 + len : initial - 1,
|
|
43
|
+ temp3 = initial,
|
|
44
|
+ temp4 = initial + 1 >= len ? initial + 1 - len : initial + 1,
|
|
45
|
+ temp5 = initial + 2 >= len ? initial + 2 - len : initial + 2
|
|
46
|
+ return source.map((item: any, index: number) => {
|
|
47
|
+ let transform = `translate(-50%, -50%) scale(0.7)`,
|
|
48
|
+ zIndex = 0,
|
|
49
|
+ className = 'slide'
|
|
50
|
+ switch (index) {
|
|
51
|
+ case temp3:
|
|
52
|
+ transform = `translate(-50%, -50%) scale(1)`
|
|
53
|
+ className = ['slide', 'activate'] as any
|
|
54
|
+ zIndex = 3
|
|
55
|
+ break
|
|
56
|
+ case temp1:
|
|
57
|
+ transform = `translate(-80%, -50%) scale(0.7)`
|
|
58
|
+ zIndex = 1
|
|
59
|
+ break
|
|
60
|
+ case temp5:
|
|
61
|
+ transform = `translate(100%, -50%) scale(0.7)`
|
|
62
|
+ zIndex = 1
|
|
63
|
+ break
|
|
64
|
+ case temp2:
|
|
65
|
+ transform = `translate(-100%, -50%) scale(0.85)`
|
|
66
|
+ zIndex = 2
|
|
67
|
+ break
|
|
68
|
+ case temp4:
|
|
69
|
+ transform = `translate(58%, -50%) scale(0.85)`
|
|
70
|
+ zIndex = 2
|
|
71
|
+ break
|
|
72
|
+ }
|
|
73
|
+ item.sty = {
|
|
74
|
+ transform,
|
|
75
|
+ zIndex
|
|
76
|
+ }
|
|
77
|
+ item.className = className
|
|
78
|
+ return item
|
|
79
|
+ })
|
52
|
80
|
}
|
53
|
81
|
|
54
|
|
-onMounted(() => {
|
55
|
|
- initVideo()
|
56
|
|
-})
|
57
|
|
-
|
58
|
|
-onUnmounted(() => {
|
59
|
|
- videoPlayer?.dispose()
|
60
|
|
-})
|
61
|
|
-
|
62
|
82
|
watch(
|
63
|
83
|
() => props.chartConfig.option.dataset,
|
64
|
84
|
newData => {
|
65
|
|
- props.chartConfig.option.dataset = newData
|
66
|
|
- videoPlayer?.src(newData)
|
67
|
|
- videoPlayer?.play()
|
|
85
|
+ option.dataset = newData
|
|
86
|
+ console.log(option.dataset)
|
68
|
87
|
},
|
69
|
88
|
{
|
70
|
|
- immediate: true
|
|
89
|
+ immediate: true,
|
|
90
|
+ deep: true
|
71
|
91
|
}
|
72
|
92
|
)
|
|
93
|
+option.dataset = computedFunc(initial.value, option.dataset)
|
|
94
|
+
|
|
95
|
+watch(
|
|
96
|
+ () => initial.value,
|
|
97
|
+ newV => {
|
|
98
|
+ option.dataset = computedFunc(newV, option.dataset)
|
|
99
|
+ }
|
|
100
|
+)
|
|
101
|
+// 处理自动轮播
|
|
102
|
+let timer: any = null
|
|
103
|
+
|
|
104
|
+const autoPlay = () => {
|
|
105
|
+ timer = setInterval(() => {
|
|
106
|
+ initial.value++
|
|
107
|
+ if (initial.value >= option.dataset.length) {
|
|
108
|
+ initial.value = 0
|
|
109
|
+ }
|
|
110
|
+ }, interval.value)
|
|
111
|
+}
|
|
112
|
+
|
|
113
|
+// 鼠标移入移除效果
|
|
114
|
+let root = ref(null)
|
|
115
|
+
|
|
116
|
+onMounted(() => {
|
|
117
|
+ clearInterval(timer)
|
|
118
|
+ autoPlay()
|
|
119
|
+ const box: any = root.value
|
|
120
|
+ box.onmouseenter = () => clearInterval(timer)
|
|
121
|
+ box.onmouseleave = () => autoPlay()
|
|
122
|
+})
|
|
123
|
+
|
|
124
|
+// 点击左右按钮切换图片
|
|
125
|
+function changeVideo(dir: string) {
|
|
126
|
+ if (dir === 'left') {
|
|
127
|
+ // cameraRef.value?.handleVideoPlay()
|
|
128
|
+ clearInterval(timer)
|
|
129
|
+ initial.value++
|
|
130
|
+ initial.value >= option.dataset.length ? (initial.value = 0) : false
|
|
131
|
+ return
|
|
132
|
+ }
|
|
133
|
+ // cameraRef.value?.handleVideoDispose()
|
|
134
|
+ initial.value--
|
|
135
|
+ initial.value < 0 ? (initial.value = option.dataset.length - 1) : false
|
|
136
|
+}
|
|
137
|
+
|
|
138
|
+// 左右切换图片设置防抖效果
|
|
139
|
+function changeSlide(dir: string) {
|
|
140
|
+ changeVideo(dir)
|
|
141
|
+}
|
73
|
142
|
</script>
|
74
|
143
|
|
75
|
144
|
<style lang="scss" scoped>
|
76
|
|
-.go-content-box {
|
77
|
|
- display: flex;
|
78
|
|
- align-items: center;
|
79
|
|
- justify-content: center;
|
80
|
|
- .my-video {
|
81
|
|
- width: 100% !important;
|
82
|
|
- height: 100% !important;
|
|
145
|
+.banner-box {
|
|
146
|
+ width: 100%;
|
|
147
|
+ height: 100%;
|
|
148
|
+ // position: absolute;
|
|
149
|
+ top: 50%;
|
|
150
|
+ left: 50%;
|
|
151
|
+ transform: translate(-50%, -50%);
|
|
152
|
+ .wrapper {
|
|
153
|
+ width: 100%;
|
|
154
|
+ height: 100%;
|
83
|
155
|
position: relative;
|
|
156
|
+ .slide {
|
|
157
|
+ width: 20%;
|
|
158
|
+ height: 100%;
|
|
159
|
+ position: absolute;
|
|
160
|
+ top: 50%;
|
|
161
|
+ left: 10%;
|
|
162
|
+ transform: translate(-50%, -50%);
|
|
163
|
+ transition: 0.5s;
|
|
164
|
+ box-shadow: 0 0 4px black;
|
|
165
|
+ }
|
|
166
|
+ }
|
|
167
|
+ .arrow {
|
|
168
|
+ position: absolute;
|
|
169
|
+ top: 50%;
|
|
170
|
+ transform: translateY(-50%);
|
|
171
|
+ z-index: 9;
|
|
172
|
+ width: 50px;
|
|
173
|
+ height: 50px;
|
|
174
|
+ background-size: contain;
|
|
175
|
+ background-color: white;
|
|
176
|
+ opacity: 0.5;
|
|
177
|
+ }
|
|
178
|
+ a.left {
|
|
179
|
+ @extend .arrow;
|
|
180
|
+ background-image: url(./left.svg);
|
|
181
|
+ left: 0px;
|
|
182
|
+ }
|
|
183
|
+ a.right {
|
|
184
|
+ @extend .arrow;
|
|
185
|
+ background-image: url(./right.svg);
|
|
186
|
+ right: 0px;
|
84
|
187
|
}
|
85
|
188
|
}
|
86
|
189
|
</style> |
...
|
...
|
|