123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- <template>
- <view v-if="isShow">
- <view
- @tap.stop.prevent
- @touchmove.stop.prevent
- class="wyb-popup-box"
- :style="{
- transitionDuration: duration + 'ms',
- opacity: contentOpacity || (type === 'center' ? 0 : 1),
- transform: contentTransform || autoTransform,
- zIndex: zIndex,
- borderTopRightRadius: type === 'center' || type === 'bottom' || type === 'left' ? radius + 'px' : 0,
- borderTopLeftRadius: type === 'center' || type === 'bottom' || type === 'right' ? radius + 'px' : 0,
- borderBottomRightRadius: type === 'center' || type === 'top' || type === 'left' ? radius + 'px' : 0,
- borderBottomLeftRadius: type === 'center' || type === 'top' || type === 'right' ? radius + 'px' : 0,
- width: autoWidth,
- height: autoHeight,
- minWidth: width + 'rpx',
- minHeight: height + 'rpx',
- top: sizeChange && type === 'center' ? winReTop : autoTop,
- bottom: autoBottom,
- left: autoLeft,
- right: autoRight,
- backgroundColor: bgColor}">
- <view
- class="wyb-popup-close"
- v-if="showCloseIcon"
- :style="{
- width: closeIcon ? closeIconSize + 'rpx' : 'auto',
- height: closeIcon ? closeIconSize + 'rpx' : 'auto',
- top: closeIconPos === 'top-right' || closeIconPos === 'top-left' ? vertOffset + 'rpx' : 'auto',
- bottom: closeIconPos === 'bottom-right' || closeIconPos === 'bottom-left' ? vertOffset + 'rpx' : 'auto',
- left: closeIconPos === 'bottom-left' || closeIconPos === 'top-left' ? horiOffset + 'rpx' : 'auto',
- right: closeIconPos === 'bottom-right' || closeIconPos === 'top-right' ? horiOffset + 'rpx' : 'auto'}">
- <image class="wyb-popup-custom-close" v-if="showCloseIcon&&closeIcon" :src="closeIcon" @tap="hide" :style="{
- width: closeIconSize + 'rpx',
- height: closeIconSize + 'rpx'}" />
- <view v-if="showCloseIcon&&!closeIcon" class="iconfont icon-close" @tap="hide" />
- </view>
-
- <scroll-view
- class="wyb-popup-container"
- :style="{
- width: autoWidth,
- height: autoHeight}"
- :enable-flex="true"
- :scroll-y="scrollY"
- :scroll-x="scrollX">
- <view class="wyb-popup-slot"><slot></slot></view>
- </scroll-view>
- </view>
- <view
- class="wyb-popup-mask"
- @tap.stop="close"
- @touchmove.stop.prevent
- :style="{
- opacity: maskOpacity,
- transitionDuration: duration + 'ms',
- backgroundColor: 'rgba(0, 0, 0, ' + maskAlpha + ')',
- zIndex: zIndex - 1}" />
- </view>
- </template>
- <script>
- export default {
- data() {
- return {
- w: uni.getSystemInfoSync().screenWidth,
- h: uni.getSystemInfoSync().screenHeight,
- isShow: false,
- winReBottom: '',
- winReTop: '',
- sizeChange: false,
- contentOpacity: null,
- contentTransform: null,
- maskOpacity: 0
- }
- },
- computed: {
- autoCenterTop() {
- let statusBarHeight = uni.getSystemInfoSync().statusBarHeight
- let windowHeight = uni.getSystemInfoSync().windowHeight
- let popupHeight = this.rpxToPx(this.height)
- let navHeight = 44
- let result = `${(windowHeight - popupHeight) / 2 - this.negativeTop}px`
- return result
- },
- autoTransform() {
- let result = ''
- switch(this.type) {
- case 'center':
- if (this.centerAnim === 'zoom-lessen') {
- result = `scale(${this.zoomLessenMulti})`
- } else if (this.centerAnim === 'slide-up') {
- result = `translateY(${100 * this.slideMulti}%)`
- } else if (this.centerAnim === 'slide-down') {
- result = `translateY(${-100 * this.slideMulti}%)`
- } else if (this.centerAnim === 'fade') {
- result = 'auto'
- }
- break
- case 'bottom':
- result = 'translateY(100%)'
- break
- case 'top':
- result = 'translateY(-100%)'
- break
- case 'left':
- result = 'translateX(-100%)'
- break
- case 'right':
- result = 'translateX(100%)'
- break
- }
- return result
- },
- autoWidth() {
- if (this.type === 'center') {
- return `${this.width}rpx`
- } else {
- if (this.mode === 'size-fixed') {
- if (this.type === 'top' || this.type === 'bottom') {
- return '100%'
- } else {
- return `${this.width}rpx`
- }
- } else {
- if (this.type === 'top' || this.type === 'bottom') {
- return '100%'
- } else {
- return 'auto'
- }
- }
- }
- },
- autoHeight() {
- if (this.type === 'center') {
- return `${this.height}rpx`
- } else {
- if (this.mode === 'size-fixed') {
- if (this.type === 'left' || this.type === 'right') {
- return '100%'
- } else {
- return `${this.height}rpx`
- }
- } else {
- if (this.type === 'left' || this.type === 'right') {
- return '100%'
- } else {
- return 'auto'
- }
- }
- }
- },
- autoTop() {
- if (this.type === 'center') {
- return this.autoCenterTop
- } else if (this.type === 'bottom') {
- return 'auto'
- } else {
- return 0
- }
- },
- autoBottom() {
- if (this.type === 'center' || this.type === 'top') {
- return 'auto'
- } else {
- return 0
- }
- },
- autoLeft() {
- if (this.type === 'center') {
- return `${(this.w - this.rpxToPx(this.width)) / 2}px`
- } else if (this.type === 'right') {
- return 'auto'
- } else {
- return 0
- }
- },
- autoRight() {
- if (this.type === 'center' || this.type === 'left') {
- return 'auto'
- } else {
- return 0
- }
- }
- },
- props: {
- type: {
- type: String,
- default: 'bottom'
- },
- mode: {
- type: String,
- default: 'size-auto'
- },
- height: {
- type: [String, Number],
- default: 400
- },
- width: {
- type: [String, Number],
- default: 500
- },
- radius: {
- type: [String, Number],
- default: 0
- },
- zIndex: {
- type: [String, Number],
- default: 10076
- },
- maskClickClose: {
- type: Boolean,
- default: true
- },
- maskAlpha: {
- type: Number,
- default: 0.5
- },
- duration: {
- type: Number,
- default: 400
- },
- showCloseIcon: {
- type: Boolean,
- default: false
- },
- scrollY: {
- type: Boolean,
- default: false
- },
- scrollX: {
- type: Boolean,
- default: false
- },
- closeIconPos: {
- type: String,
- default: 'top-right'
- },
- closeIcon: {
- type: String,
- default: ''
- },
- closeIconSize: {
- type: [String, Number],
- default: '20'
- },
- vertOffset: {
- type: [String, Number],
- default: '22'
- },
- horiOffset: {
- type: [String, Number],
- default: '22'
- },
- centerAnim: {
- type: String,
- default: 'zoom-lessen'
- },
- bgColor: {
- type: String,
- default: '#ffffff'
- },
- zoomLessenMulti: {
- type: Number,
- default: 1.15
- },
- slideMulti: {
- type: Number,
- default: 1
- },
- negativeTop: {
- type: Number,
- default: 0
- }
- },
- mounted() {
- // #ifdef H5
- let winHeight = uni.getSystemInfoSync().windowHeight
- uni.onWindowResize(res => {
- this.sizeChange = true
- if (this.type === 'bottom') {
- this.winReBottom = winHeight - res.size.windowHeight + 'px'
- } else if (this.type === 'center') {
- this.winReTop = ((res.size.windowHeight - this.rpxToPx(this.height)) / 2 - this.negativeTop) + 'px'
- }
- })
- // #endif
- },
- methods: {
- close() {
- this.maskClickClose && this.hide()
- },
- show() {
- this.isShow = true
- // #ifndef H5
- this.$nextTick(() => {
- this.maskIn()
- this.contentIn()
- this.wait(this.duration + 1).then(() => {
- this.$emit('show', {
- pageScroll: false,
- overflow: 'hidden'
- })
- })
- })
- // #endif
- // #ifdef H5
- this.wait(10).then(() => {
- this.maskIn()
- this.contentIn()
- this.wait(this.duration + 1).then(() => {
- this.$emit('show', {
- pageScroll: false,
- overflow: 'hidden'
- })
- })
- })
- // #endif
- },
- hide() {
- this.contentOut()
- this.maskOut()
- this.wait(this.duration + 1).then(() => {
- this.isShow = false
- this.$emit('hide', {
- pageScroll: true,
- overflow: 'scroll'
- })
- })
- },
- contentIn() {
- switch (this.type) {
- case 'center':
- if (this.centerAnim === 'zoom-lessen') {
- this.contentOpacity = 1
- this.contentTransform = 'scale(1)'
- } else if (this.centerAnim === 'slide-up' || this.centerAnim === 'slide-down') {
- this.contentOpacity = 1
- this.contentTransform = 'translateY(0)'
- } else if (this.centerAnim === 'fade') {
- this.contentOpacity = 1
- }
- break
- case 'bottom':
- case 'top':
- this.contentTransform = 'translateY(0)'
- break
- case 'left':
- case 'right':
- this.contentTransform = 'translateX(0)'
- break
- }
- },
- contentOut() {
- this.contentOpacity = null
- this.contentTransform = null
- },
- maskIn() {
- this.maskOpacity = 1
- },
- maskOut() {
- this.maskOpacity = 0
- },
- rpxToPx(rpx) {
- return rpx / 750 * this.w
- },
- wait(time) {
- return new Promise(resolve => {
- setTimeout(() => {
- resolve()
- }, time)
- })
- }
- }
- }
- </script>
- <style>
- @import "./iconfont.css";
- .wyb-popup-box{
- position: fixed;
- transition-timing-function: ease-out;
- transition-property: opacity, transform;
- }
-
- .wyb-popup-container {
- position: relative;
- box-sizing: border-box;
- }
-
- .wyb-popup-slot {
- width: 100%;
- height: 100%;
- }
-
- .wyb-popup-mask {
- position: fixed;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- transition-timing-function: ease;
- transition-property: opacity, transform;
- }
-
- .wyb-popup-close {
- position: absolute;
- font-size:48rpx;
- color: #808080;
- z-index: 20000;
-
- }
- .wyb-popup-close .iconfont {
- font-size:48rpx;
- }
- .wyb-popup-custom-close {
- left: 0;
- top: 0;
- position: absolute;
- }
- </style>
|