Files
dvcp_v2_webapp/project/dvui/layout/AiDvWrapper/AiDvWrapper.vue
2022-03-25 11:09:26 +08:00

541 lines
13 KiB
Vue

<template>
<section class="AiDvWrapper">
<dv-full-screen-container>
<div class="viewPanel column" flex>
<el-row type="flex" class="headerPane">
<div class="fill topPane">
<div class="viewTabs" flex>
<div v-for="view in tabs" :key="view.id" class="btn" :class="{active:view.id==active}" flex
@click="$emit('change',view.id)">{{ view.label }}
</div>
<div v-if="hasMoreDvs" class="btn more" :class="{active:isMoreTabs}" flex>更多
<div class="moreViews">
<div v-for="view in moreTabs" :key="view.id" v-text="view.label"
class="moreViewItem" :class="{active:view.id==active}"
:popper-options="{boundariesElement:'AiDvWrapper'}"
@click="$emit('change',view.id)"/>
</div>
</div>
</div>
<div class="headerBottomBorder">
<div class="breatheLights"/>
</div>
</div>
<div class="headerCenter">
<div class="headerZone">
<div ref="fly" class="fly"/>
<span>{{ title }}</span>
</div>
</div>
<div class="fill topPane">
<div class="settingZone" flex>
<right-top-border class="time">{{ currentTime }}</right-top-border>
<right-top-border class="setting" @click.native.stop="dialog=true"/>
<right-top-border class="fullscreen" @click.native.stop="handleFullScreen"/>
</div>
<div class="headerBottomBorder right">
<div class="breatheLights"/>
</div>
</div>
</el-row>
<div class="fill">
<slot/>
</div>
</div>
</dv-full-screen-container>
<ai-dialog :visible.sync="dialog" title="设置" @onConfirm="handleSetting" width="500px" class="settingDialog">
<el-form size="mini">
<el-form-item label="轮播频次">
<el-input-number v-model="setting.splitViewTime" :min="0" controls-position="right"/>
</el-form-item>
</el-form>
</ai-dialog>
</section>
</template>
<script>
import {fullScreenContainer} from '@jiaminghi/data-view'
import {gsap} from 'gsap'
import {MotionPathPlugin} from "gsap/MotionPathPlugin.js"
import Vue from "vue";
import RightTopBorder from "./rightTopBorder";
Vue.use(fullScreenContainer)
export default {
name: "AiDvWrapper",
components: {RightTopBorder},
model: {
prop: 'value',
event: 'change'
},
props: {
title: {default: "数字乡村数据大屏"},
views: {
default: () => []
},
value: {default: ''}
},
computed: {
active: {
set(v) {
this.$emit('change', v)
},
get() {
return this.value || this.views?.[0]?.id
}
},
hasMoreDvs() {
return this.views.length > 4
},
tabs() {
return !this.hasMoreDvs ? this.views : this.views.slice(0, 3)
},
moreTabs() {
return this.views?.slice(3) || []
},
isMoreTabs() {
return this.moreTabs?.some(e => e.id == this.active)
}
},
data() {
return {
currentTime: '',
fullscreen: false,
dialog: false,
setting: {splitViewTime: 0}
}
},
methods: {
handleFullScreen() {
this.fullscreen = !this.fullscreen
if (this.fullscreen) {
let el = document.documentElement;
let rfs = el.requestFullScreen || el.webkitRequestFullScreen ||
el.mozRequestFullScreen || el.msRequestFullScreen;
rfs.call(el)
} else {
let el = document;
let cfs = el.cancelFullScreen || el.webkitCancelFullScreen ||
el.mozCancelFullScreen || el.exitFullScreen;
cfs.call(el)
}
},
initFly() {
gsap.registerPlugin(MotionPathPlugin);
const rand = (min, max) => min + (max - min) * Math.random(),
startFly = (p) => {
gsap.timeline()
.fromTo(p, {
x: rand(0, 600),
y: 90 - rand(8, 50),
scale: rand(1, 3),
}, {
y: 0,
ease: 'elastic.easeInOut',
duration: rand(2, 6),
onComplete: () => {
startFly(p, true);
}
}, 0)
.fromTo(p, {
opacity: 1
}, {
opacity: 0,
duration: rand(1, 1.5),
yoyo: true,
repeat: -1,
ease: 'power4.in'
}, 0)
}
setTimeout(() => {
//初始化标题萤火效果
let numP = 70;
for (let i = 0; i <= numP; i++) {
let p = document.createElement('div');
p.id = "p" + i;
this.$refs.fly?.appendChild(p)
setTimeout(() => startFly(p), 1000)
}
}, 1000)
},
handleSetting() {
if (this.setting.timer) clearInterval(this.setting.timer)
let count = 0
if (this.setting?.splitViewTime > 0) {
this.setting.timer = setInterval(() => {
if (this.views.length > 0) {
count++
this.active = this.views?.[count % this.views.length]?.id
}
}, this.setting.splitViewTime * 1000)
}
this.dialog = false
}
},
created() {
setInterval(() => {
this.currentTime = this.$moment().format("YYYY/MM/DD HH:mm:ss")
}, 1000)
},
mounted() {
this.initFly()
}
}
</script>
<style lang="scss" scoped>
@font-face {
font-family: DIN;
src: url("assets/D-DINExp.otf");
}
@import url('../../lib/animation.scss');
.AiDvWrapper {
.viewPanel {
position: relative;
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-size: 100% 100%;
background-image: url("https://cdn.cunwuyun.cn/dvcp/dv/background.png");
padding: 0 0 20px;
box-sizing: border-box;
& > .fill {
width: 100%;
padding: 0 40px;
box-sizing: border-box;
}
}
::v-deep.headerPane {
height: 120px;
width: 100%;
padding: 0 10px;
position: relative;
color: #fff;
.topPane {
z-index: 5;
}
.viewTabs {
height: 60px;
font-size: 15px;
overflow: visible;
.btn {
cursor: pointer;
justify-content: center;
min-width: 120px;
height: 48px;
background-repeat: no-repeat;
background-position: center;
background-image: url("assets/viewTabBtn.svg");
&.more {
position: relative;
overflow: visible;
&:hover {
background-image: url("assets/moreViewsBtn.svg");
.moreViews {
display: block;
}
}
}
&.active {
position: relative;
background-image: none;
&:before {
content: " ";
display: block;
position: absolute;
width: 126px;
height: 38px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-image: url("assets/viewTabBtn-active.svg");
}
}
& + .btn, & + .moreTabs {
margin-left: 10px;
}
}
}
.settingZone {
font-family: DIN, serif;
height: 60px;
justify-content: flex-end;
font-size: 18px;
z-index: 5;
.rightTopBorder + .rightTopBorder {
margin-left: 10px;
}
.time {
width: 200px;
}
.setting {
background-image: url("assets/setting.svg");
}
.fullscreen {
background-image: url("assets/fullscreen.svg");
}
}
.headerCenter {
width: 880px;
height: 90px;
z-index: 3;
background-repeat: no-repeat;
background-position: center -32px;
background-image: url("assets/headerCenterBg1.svg");
&:before {
content: " ";
display: block;
position: absolute;
background: linear-gradient(180deg, #040718 0%, rgba(4, 7, 24, 0) 100%);
top: 0;
left: 0;
right: 0;
pointer-events: none;
height: 64px;
z-index: 4;
}
.headerZone {
position: relative;
margin: 0 auto;
width: 760px;
height: 124px;
background-repeat: no-repeat;
background-image: url("assets/headerCenterBorderLight.svg"), url("assets/headerCenterBorder.svg"), url("assets/headerCenterBg2.png");
background-position: center bottom, center 0, center -20px;
overflow: visible;
& > span {
position: absolute;
left: 50%;
top: calc(50% - 20px);
transform: translate(-50%, -50%);
white-space: nowrap;
font-size: 40px;
line-height: 47px;
letter-spacing: 5px;
text-shadow: 0 0 8px #1365FF, 0 0 2px rgba(133, 181, 255, .5);
z-index: 9;
font-weight: bold;
}
.fly {
position: absolute;
top: 0;
width: 600px;
height: 90px;
left: 50%;
transform: translateX(-50%);
z-index: 3;
& > div {
width: 0;
box-shadow: 0 0 1px 1px #0aa5ff;
}
}
}
}
.headerBottomBorder {
position: relative;
width: 538px;
height: 15px;
background-image: url("assets/headerBottomBorder.svg");
&:before {
content: " ";
display: block;
position: absolute;
left: -3px;
bottom: -3px;
width: 40px;
height: 12px;
background-image: url("assets/headerBottomLight.svg");
}
.breatheLights {
position: absolute;
right: -7px;
bottom: -20px;
transform: translateX(100%);
width: 132px;
height: 20px;
animation: breathes 1.5s ease-in-out infinite alternate;
animation-delay: .5s;
display: flex;
background-repeat: no-repeat;
&:before {
transform: translateX(calc(6px - 100%));
display: block;
content: " ";
width: 44px;
height: 20px;
animation: breathes 1.5s ease-in-out infinite alternate;
}
&:after {
transform: translateX(-6px);
display: block;
content: " ";
width: 44px;
height: 20px;
animation: breathes 1.5s infinite alternate;
animation-delay: 1s;
}
}
&.right {
float: right;
transform: rotateY(180deg);
}
}
.moreViews {
display: none;
position: absolute;
bottom: 0;
transform: translateY(100%);
width: 120px;
min-width: 120px;
padding: 0;
background: rgba(9, 43, 75, 0.5);
box-shadow: 0 0 8px 0 #20B8FF inset;
border: 1px solid #66DBFF;
border-radius: 0;
z-index: 2;
.moreViewItem {
height: 44px;
width: 100px;
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid #0C5369;
margin: 0 10px;
color: #fff;
cursor: pointer;
&:last-of-type {
border-bottom: none;
}
&.active, &:hover {
color: #FFDB52;
}
}
}
}
::v-deep.settingDialog {
.ai-dialog {
background: #1D2127;
box-shadow: 0 0 4px 0 #206EFF;
border: 1px solid #4283FF;
color: #fff;
.el-dialog__header {
border-radius: 0;
box-shadow: none;
line-height: 28px;
font-size: 20px;
font-family: FZZZHONGJW--GB1-0, FZZZHONGJW--GB1;
text-shadow: 0 0 8px #1365FF;
background: linear-gradient(270deg, #F0F4FF 0%, #FFFFFF 51%, #F0F4FF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
.ai-dialog__header {
border-bottom: none;
}
}
.el-dialog__footer {
background: inherit;
}
}
.el-form {
.el-form-item__label {
color: #fff;
}
.el-input:after {
position: absolute;
display: block;
right: 32px;
top: 50%;
content: "秒";
transform: translateY(-50%);
font-size: 12px;
}
.el-input__inner {
background: #262C33;
border: 1px solid #030411;
border-radius: 0;
color: #fff;
text-align: start;
position: relative;
}
.el-input-number__decrease, .el-input-number__increase {
border-color: #030411;
background: #262C33;
color: #fff;
}
}
}
}
@keyframes breatheList {
0% {
border-color: rgba(#FFC24A, 1);
box-shadow: 0 0 8px 0 #FFC24A, 0 0 4px 0 #FFFAE7;
}
50% {
border-color: rgba(#FFC24A, .4);
box-shadow: 0 0 8px 0 rgba(#FFC24A, .4), 0 0 4px 0 rgba(#FFFAE7, .4);
}
100% {
border-color: rgba(#FFC24A, .2);
box-shadow: 0 0 8px 0 rgba(#FFC24A, .2), 0 0 4px 0 rgba(#FFFAE7, .2);
}
}
@keyframes breathes {
0% {
background-image: url("assets/parallelogram.svg");
}
50% {
background-image: url("assets/parallelogram1.svg");
}
100% {
background-image: url("assets/parallelogram2.svg");
}
}
</style>