541 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			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>
 |