|
@@ -1,8 +1,8 @@
|
|
|
<template>
|
|
|
<div class="video_area" :style="getAreaStyle()">
|
|
|
<SerialNumberPosition :property="data.property" />
|
|
|
- <div class="main">
|
|
|
- <ul v-if="'list' === data.property.view_method" class="view_list">
|
|
|
+ <div ref="videoArea" class="main">
|
|
|
+ <ul v-if="'list' === data.property.view_method" class="view-list">
|
|
|
<li v-for="(file, i) in data.file_list" :key="i">
|
|
|
<VideoPlay
|
|
|
view-size="small"
|
|
@@ -13,13 +13,14 @@
|
|
|
/>
|
|
|
</li>
|
|
|
</ul>
|
|
|
- <div v-if="'independent' === data.property.view_method" class="view_independent">
|
|
|
+ <div v-if="'independent' === data.property.view_method" class="view-independent">
|
|
|
<el-carousel
|
|
|
ref="video_carousel"
|
|
|
indicator-position="none"
|
|
|
direction="vertical"
|
|
|
:autoplay="false"
|
|
|
:interval="0"
|
|
|
+ :style="{ width: elementWidth - 248 - 32 + 'px', height: elementHeight + 'px' }"
|
|
|
>
|
|
|
<el-carousel-item v-for="(file, i) in data.file_list" :key="i">
|
|
|
<VideoPlay
|
|
@@ -30,11 +31,23 @@
|
|
|
/>
|
|
|
</el-carousel-item>
|
|
|
</el-carousel>
|
|
|
- <ul class="view_independent_list">
|
|
|
- <li v-for="(file, i) in data.file_list" :key="i" @click="handleAudioClick(i)">
|
|
|
- <VideoPlay view-size="small" :file-id="file.file_id" :audio-index="i" :cur-video-index="curVideoIndex" />
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
+ <div class="container-box">
|
|
|
+ <ul
|
|
|
+ ref="container"
|
|
|
+ class="view-list-bottom"
|
|
|
+ :style="{ height: elementHeight + 'px', transform: `translateY(${translateY}px)` }"
|
|
|
+ >
|
|
|
+ <li v-for="(file, i) in data.file_list" :key="i" @click="handleAudioClick(i)">
|
|
|
+ <VideoPlay view-size="small" :file-id="file.file_id" :audio-index="i" :cur-video-index="curVideoIndex" />
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ <button v-if="viewTopBottomBtn" class="arrow top" @click="scroll(1)">
|
|
|
+ <i class="el-icon-arrow-up"></i>
|
|
|
+ </button>
|
|
|
+ <button v-if="viewTopBottomBtn" class="arrow bottom" @click="scroll(-1)">
|
|
|
+ <i class="el-icon-arrow-down"></i>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -53,8 +66,39 @@ export default {
|
|
|
return {
|
|
|
data: getVideoData(),
|
|
|
curVideoIndex: 0,
|
|
|
+ elementWidth: 0,
|
|
|
+ elementHeight: 0,
|
|
|
+ viewTopBottomBtn: false,
|
|
|
+ fileLen: 0,
|
|
|
+ translateY: 0,
|
|
|
};
|
|
|
},
|
|
|
+ watch: {
|
|
|
+ data: {
|
|
|
+ handler(val) {
|
|
|
+ this.fileLen = val.file_list.length;
|
|
|
+ if (this.fileLen > 0) {
|
|
|
+ const ele = this.$refs.videoArea;
|
|
|
+ this.elementWidth = ele.clientWidth;
|
|
|
+ this.elementHeight = ele.clientHeight;
|
|
|
+ window.addEventListener('resize', this.handleResize);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ },
|
|
|
+ elementWidth(newWidth, oldWidth) {
|
|
|
+ // console.log(`宽度从 ${oldWidth} 变为 ${newWidth}`);
|
|
|
+ this.elementWidth = newWidth;
|
|
|
+ },
|
|
|
+ elementHeight(newHeight, oldHeight) {
|
|
|
+ // console.log(`高度从 ${oldHeight} 变为 ${newHeight}`);
|
|
|
+ this.elementHeight = newHeight;
|
|
|
+ this.isViewTopBottomBtn();
|
|
|
+ },
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ window.removeEventListener('resize', this.handleResize);
|
|
|
+ },
|
|
|
methods: {
|
|
|
handleAudioClick(index) {
|
|
|
// 获取 Carousel 实例
|
|
@@ -81,27 +125,40 @@ export default {
|
|
|
this.curVideoIndex = this.data.file_id_list.length - 1;
|
|
|
}
|
|
|
},
|
|
|
-
|
|
|
- /**
|
|
|
- * 得到序号外部样式
|
|
|
- */
|
|
|
- getAreaStyle() {
|
|
|
- const position = this.data.property.sn_position;
|
|
|
- let grid = '';
|
|
|
-
|
|
|
- if (position.includes('right')) {
|
|
|
- grid = `"main position" / 1fr auto`;
|
|
|
- } else if (position.includes('left')) {
|
|
|
- grid = `"position main" / auto 1fr`;
|
|
|
- } else if (position.includes('top')) {
|
|
|
- grid = `"position" auto "main" 1fr`;
|
|
|
- } else if (position.includes('bottom')) {
|
|
|
- grid = `"main" 1fr "position" auto`;
|
|
|
+ handleResize() {
|
|
|
+ const width = this.$refs.videoArea.clientWidth;
|
|
|
+ if (width !== this.elementWidth) {
|
|
|
+ this.elementWidth = width;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 是否显示上下箭头
|
|
|
+ isViewTopBottomBtn() {
|
|
|
+ // 计算右侧列表图片高度
|
|
|
+ let listHeight = this.fileLen * this.data.min_height + 20 * (this.fileLen - 1);
|
|
|
+ if (listHeight > this.elementHeight) {
|
|
|
+ this.viewTopBottomBtn = true;
|
|
|
+ } else {
|
|
|
+ this.viewTopBottomBtn = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 滚动图片列表
|
|
|
+ scroll(direction) {
|
|
|
+ const minHeight = Number(this.data.min_height);
|
|
|
+ const step = minHeight + 20; // 每次滚动的距离
|
|
|
+ let _down = (minHeight + 20) * (this.fileLen - 1);
|
|
|
+ // 计算滚动后的 translateY 值
|
|
|
+ let newY = this.translateY + step * direction;
|
|
|
+ // 检查是否超出上下边界
|
|
|
+ if (newY > 0) {
|
|
|
+ // 滚动到第一张图片时不再向上滚动
|
|
|
+ this.translateY = 0;
|
|
|
+ } else if (newY < -_down) {
|
|
|
+ // 滚动到最后一张图片时不再向下滚动
|
|
|
+ this.translateY = -_down;
|
|
|
+ } else {
|
|
|
+ // 在边界内时执行滚动
|
|
|
+ this.translateY = newY;
|
|
|
}
|
|
|
-
|
|
|
- return {
|
|
|
- grid,
|
|
|
- };
|
|
|
},
|
|
|
},
|
|
|
};
|
|
@@ -125,41 +182,66 @@ export default {
|
|
|
grid-area: main;
|
|
|
width: 100%;
|
|
|
|
|
|
- .view_list {
|
|
|
+ .view-list {
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
- gap: 20px 2%;
|
|
|
+ gap: 20px;
|
|
|
width: 100%;
|
|
|
|
|
|
> li {
|
|
|
- flex: 0 0 23%;
|
|
|
+ width: 248px;
|
|
|
+ height: 139px;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .view_independent {
|
|
|
+ .view-independent {
|
|
|
display: flex;
|
|
|
- column-gap: 2%;
|
|
|
+ column-gap: 32px;
|
|
|
|
|
|
:deep .el-carousel {
|
|
|
- width: 100%;
|
|
|
+ background-color: #d9d9d9;
|
|
|
|
|
|
&__container {
|
|
|
- height: 0;
|
|
|
- padding-bottom: 56.25%; /* 16:9 比例的视频 */
|
|
|
- overflow: hidden;
|
|
|
- background-color: #d9d9d9;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .container-box {
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ .arrow {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 10;
|
|
|
+ width: 100%;
|
|
|
+ height: 40px;
|
|
|
+ text-align: center;
|
|
|
+ background-color: rgba(0, 0, 0, 10%);
|
|
|
+ border-radius: 0;
|
|
|
}
|
|
|
|
|
|
- &__item {
|
|
|
- transition: none !important;
|
|
|
+ .arrow:hover {
|
|
|
+ background-color: rgba(0, 0, 0, 30%);
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .view_independent_list {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- row-gap: 20px;
|
|
|
- width: 23%;
|
|
|
+ .top {
|
|
|
+ top: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .bottom {
|
|
|
+ bottom: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .view-list-bottom {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ row-gap: 20px;
|
|
|
+
|
|
|
+ > li {
|
|
|
+ width: 248px;
|
|
|
+ height: calc(248px * 9 / 16);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|