1
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
<script lang="ts">
|
||||
import {PropType} from "vue"
|
||||
import { getUid } from "../../core/util/xCoreUtil.uts"
|
||||
import { getDefaultColor } from "../../core/util/xCoreColorUtil.uts"
|
||||
import { checkIsCssUnit } from "../../core/util/xCoreUtil.uts"
|
||||
import { xConfig } from "../../config/xConfig.uts"
|
||||
|
||||
/**
|
||||
* @name 动态全屏 xViewTofull
|
||||
* @page /pages/index/view-tofull
|
||||
* @category 展示组件
|
||||
* @description 动态全屏,点击某一区域时,让该内容自动全屏展开,关闭时,回落到原位置,场景比如:视频播放,详情等不想开新页面的时候非常有用。
|
||||
* 如果想完全全屏,可以自定义导航栏和自定义关闭按钮实现。web端使用时注意:不能套在父组件设置了css transform属性里面,否则错乱。
|
||||
* @constant 平台兼容
|
||||
* | Harmony | H5 | andriod | IOS | 小程序 | UTS | UNIAPP-X SDK | version |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| ☑ | ☑ | ☑️ | ☑️ | ☑️ | ☑️ | 4.76+ | 1.1.18 |
|
||||
*/
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
nodeeleinfo:null as null|NodeInfo,
|
||||
opeing:false,
|
||||
opened:false,
|
||||
isCloseing:false,
|
||||
showCloseBtn:false,
|
||||
showPlace:false,
|
||||
zIndex: 50,
|
||||
opeingZindex:false,
|
||||
tid:555
|
||||
}
|
||||
},
|
||||
slots: Object as SlotsType<{
|
||||
default : {
|
||||
opened : boolean
|
||||
},
|
||||
}>,
|
||||
props:{
|
||||
|
||||
/**
|
||||
* 全屏弹出来时的背景色。
|
||||
*/
|
||||
bgColor:{
|
||||
type:String,
|
||||
default:'#ffffff'
|
||||
},
|
||||
/**
|
||||
* 全屏弹出来时的暗黑背景色。
|
||||
* 默认为空,取全局的暗黑背景
|
||||
*/
|
||||
darkBgColor:{
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
/**
|
||||
* 展开时的动画时长,单位ms
|
||||
*/
|
||||
duration:{
|
||||
type:Number,
|
||||
default:300
|
||||
},
|
||||
/**
|
||||
* 是否显示关闭按钮
|
||||
* 你可以关闭,通过ref来关闭。
|
||||
* 如果要全屏可以自定义导航栏。
|
||||
*/
|
||||
showClose:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
|
||||
_bgColor():string{
|
||||
if(xConfig.dark == 'dark'){
|
||||
if(this.darkBgColor==""){
|
||||
return getDefaultColor(xConfig.backgroundColorContentDark)
|
||||
}
|
||||
return getDefaultColor(this.darkBgColor)
|
||||
}
|
||||
return getDefaultColor(this.bgColor)
|
||||
},
|
||||
_boxMapStyle():Map<string,any>{
|
||||
let stylemap = new Map<string,any>()
|
||||
let w = this.nodeeleinfo?.width??0;
|
||||
let h = this.nodeeleinfo?.height??0;
|
||||
stylemap.set('width',w+'px')
|
||||
stylemap.set('height',h+'px')
|
||||
return stylemap;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick(){
|
||||
this.open()
|
||||
},
|
||||
|
||||
getNodeinfo(){
|
||||
let _this = this;
|
||||
if(_this.opened||_this.opeing) return;
|
||||
_this.opened = false
|
||||
|
||||
uni.createSelectorQuery()
|
||||
.in(this)
|
||||
.select(".xViewToFull")
|
||||
.boundingClientRect()
|
||||
.exec((result)=>{
|
||||
let node = result[0] as NodeInfo
|
||||
_this.nodeeleinfo = node!;
|
||||
_this.setOpens()
|
||||
_this.showPlace = true;
|
||||
|
||||
|
||||
})
|
||||
},
|
||||
setOpens(){
|
||||
let _this = this;
|
||||
let ele = this.$refs['xViewToFullBlock'] as UniElement|null;
|
||||
if(ele==null) return;
|
||||
this.opeing = true;
|
||||
let el = ele! as UniElement;
|
||||
let top = 0
|
||||
let sys= uni.getWindowInfo()
|
||||
// #ifdef WEB
|
||||
top = 44
|
||||
// #endif
|
||||
|
||||
this.isCloseing = false;
|
||||
el.style.setProperty('width',this.nodeeleinfo!.width!+'px')
|
||||
el.style.setProperty('height',this.nodeeleinfo!.height!+'px')
|
||||
el.style.setProperty('left',this.nodeeleinfo!.left!+'px')
|
||||
el.style.setProperty('top',this.nodeeleinfo!.top!+'px')
|
||||
// el.style.setProperty('z-index','88')
|
||||
|
||||
setTimeout(()=>{
|
||||
el.style.setProperty('position','fixed')
|
||||
el.style.setProperty('transition-duration',this.duration+'ms')
|
||||
el.style.setProperty('left','0px')
|
||||
el.style.setProperty('top',top+'px')
|
||||
el.style.setProperty('width',sys.windowWidth+'px')
|
||||
el.style.setProperty('height',sys.windowHeight+'px')
|
||||
el.style.setProperty('background-color',_this._bgColor)
|
||||
|
||||
},50)
|
||||
// #ifdef APP-HARMONY
|
||||
clearTimeout(this.tid)
|
||||
let t = this;
|
||||
this.tid = setTimeout(function() {
|
||||
t.closeAniEnd()
|
||||
}, this.duration+50);
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 手动打开弹层
|
||||
* @public
|
||||
*/
|
||||
open(){
|
||||
this.opeingZindex=true;
|
||||
this.getNodeinfo()
|
||||
},
|
||||
/**
|
||||
* 手动ref调用关闭弹层。
|
||||
* @public
|
||||
*/
|
||||
close() {
|
||||
this.opeingZindex=false;
|
||||
let _this = this;
|
||||
if(!_this.opened||_this.opeing) return;
|
||||
let ele = this.$refs['xViewToFullBlock'] as UniElement|null;
|
||||
if(ele==null) return;
|
||||
let el = ele! as UniElement;
|
||||
this.isCloseing = true;
|
||||
this.showCloseBtn = false;
|
||||
let top = 0
|
||||
// #ifdef WEB
|
||||
top = 44
|
||||
// #endif
|
||||
el.style.setProperty('width',this.nodeeleinfo!.width!+'px')
|
||||
el.style.setProperty('height',this.nodeeleinfo!.height!+'px')
|
||||
el.style.setProperty('left',this.nodeeleinfo!.left!+'px')
|
||||
el.style.setProperty('top',(this.nodeeleinfo!.top!+top)+'px')
|
||||
// #ifdef APP-HARMONY
|
||||
this.opeing = false;
|
||||
this.opened = false;
|
||||
this.isCloseing = false;
|
||||
this.showCloseBtn = false;
|
||||
// #endif
|
||||
},
|
||||
closeAniEnd(){
|
||||
|
||||
if(this.opeing){
|
||||
this.opeing = false;
|
||||
this.opened = true;
|
||||
this.isCloseing = false;
|
||||
this.showCloseBtn = true;
|
||||
}
|
||||
if(!this.isCloseing) return;
|
||||
this.isCloseing = false;
|
||||
this.opeing = false;
|
||||
this.opened = false;
|
||||
let _this = this;
|
||||
let ele = this.$refs['xViewToFullBlock'] as UniElement|null;
|
||||
if(ele==null) return;
|
||||
let el = ele! as UniElement;
|
||||
el.style.setProperty('transition-duration','0ms')
|
||||
el.style.setProperty('position','static')
|
||||
|
||||
el.style.setProperty('top','0px')
|
||||
el.style.setProperty('left','0px')
|
||||
el.style.setProperty('background-color','transparent')
|
||||
this.showPlace = false;
|
||||
this.opeingZindex=false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<view class="xViewToFull">
|
||||
|
||||
<view
|
||||
@click="onClick"
|
||||
@transitionend="closeAniEnd"
|
||||
ref="xViewToFullBlock"
|
||||
class="xViewToFullBlock"
|
||||
:style="{zIndex:opeingZindex?(zIndex+1):zIndex}"
|
||||
>
|
||||
|
||||
<view v-if="showCloseBtn&&showClose" @click.stop="close" class="xViewToFullClose">
|
||||
<!--
|
||||
@slot 关闭按钮插槽
|
||||
@prop {boolean} opened - 是否打开状态
|
||||
-->
|
||||
<slot name="close" :opened="opened">
|
||||
<x-icon font-size="24" name="close-circle-line"></x-icon>
|
||||
</slot>
|
||||
</view>
|
||||
<!--
|
||||
@slot 默认内容插槽
|
||||
@prop {boolean} opened - 是否打开状态
|
||||
-->
|
||||
<slot :opened="opened"></slot>
|
||||
</view>
|
||||
|
||||
<view class="xViewToFullPlace" v-if="showPlace" :style="_boxMapStyle"></view>
|
||||
</view>
|
||||
</template>
|
||||
<style>
|
||||
.xViewToFullBlock{
|
||||
transition-duration: 0ms;
|
||||
transition-property: width,left,top,width,height,opacity;
|
||||
transition-timing-function: cubic-bezier(.42,.38,.15,.93);
|
||||
left: 0px;
|
||||
top:0px;
|
||||
position: relative;
|
||||
/* #ifdef MP */
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
}
|
||||
.xViewToFullClose{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top:16px;
|
||||
z-index: 50;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user