wyb-popup.vue 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. <template>
  2. <view v-if="isShow" class="container">
  3. <wyb-transition :contentStyle="maskRoot" :isContentShow="isPopupShow" :typeList="['fade']" :duration="duration">
  4. <view :style="maskRoot" @tap="close" />
  5. </wyb-transition>
  6. <wyb-transition :contentStyle="root" :isContentShow="isPopupShow" :zoomLessenMulti="zoomLessenMulti" :typeList="popupAnim" mode="ease-out" :duration="duration">
  7. <view v-if="showCloseIcon" class="iconfont icon-close close" :style="closeRoot" @tap="hide" />
  8. <slot></slot>
  9. </wyb-transition>
  10. </view>
  11. </template>
  12. <script>
  13. import wybTransition from '../wyb-transition/wyb-transition.vue'
  14. export default {
  15. components: {
  16. wybTransition
  17. },
  18. data() {
  19. return {
  20. w: uni.getSystemInfoSync().screenWidth,
  21. h: uni.getSystemInfoSync().screenHeight,
  22. root: '',
  23. maskRoot: '',
  24. closeRoot: '',
  25. isShow: false,
  26. isPopupShow: false,
  27. popupAnim: ['slide-up']
  28. }
  29. },
  30. props: {
  31. type: {
  32. type: String,
  33. default: 'bottom'
  34. },
  35. mode: {
  36. type: String,
  37. default: 'size-auto'
  38. },
  39. height: {
  40. type: [String, Number],
  41. default: 400
  42. },
  43. width: {
  44. type: [String, Number],
  45. default: 500
  46. },
  47. radius: {
  48. type: [String, Number],
  49. default: 0
  50. },
  51. zIndex: {
  52. type: [String, Number],
  53. default: 10076
  54. },
  55. maskClickClose: {
  56. type: Boolean,
  57. default: true
  58. },
  59. maskAlpha: {
  60. type: Number,
  61. default: 0.5
  62. },
  63. duration: {
  64. type: Number,
  65. default: 400
  66. },
  67. showCloseIcon: {
  68. type: Boolean,
  69. default: false
  70. },
  71. centerAnim: {
  72. type: String,
  73. default: 'zoom-lessen'
  74. },
  75. closeIconPos: {
  76. type: String,
  77. default: 'top-right'
  78. },
  79. bgColor: {
  80. type: String,
  81. default: '#ffffff'
  82. },
  83. zoomLessenMulti: {
  84. type: Number,
  85. default: 1.15
  86. }
  87. },
  88. methods: {
  89. processStyle() {
  90. let style = 'z-index: ' + this.zIndex + '; '
  91. style += 'background-color: ' + this.bgColor + '; position: fixed; '
  92. switch (this.type) {
  93. case 'bottom':
  94. if (this.mode === 'size-fixed') {
  95. style += 'height: ' + this.height + 'rpx; '
  96. } else if (this.mode === 'size-auto') {
  97. style += 'min-height: ' + this.height + 'rpx; '
  98. style += 'height: auto; '
  99. }
  100. style += 'bottom: 0; left: 0; right: 0; '
  101. style += 'border-top-left-radius: ' + this.radius + 'px; '
  102. style += 'border-top-right-radius: ' + this.radius + 'px; '
  103. style += 'width: 100%; '
  104. this.popupAnim = ['slide-up']
  105. break
  106. case 'top':
  107. if (this.mode === 'size-fixed') {
  108. style += 'height: ' + this.height + 'rpx; '
  109. } else if (this.mode === 'size-auto') {
  110. style += 'min-height: ' + this.height + 'rpx; '
  111. style += 'height: auto; '
  112. }
  113. style += 'top: 0; left: 0; right: 0; '
  114. style += 'border-bottom-left-radius: ' + this.radius + 'px; '
  115. style += 'border-bottom-right-radius: ' + this.radius + 'px; '
  116. style += 'width: 100%; '
  117. this.popupAnim = ['slide-down']
  118. break
  119. case 'left':
  120. if (this.mode === 'size-fixed') {
  121. style += 'width: ' + this.width + 'rpx; '
  122. } else if (this.mode === 'size-auto') {
  123. style += 'min-width: ' + this.width + 'rpx; '
  124. style += 'width: auto; '
  125. }
  126. style += 'height: 100%; '
  127. style += 'top: 0; left: 0; bottom: 0; '
  128. style += 'border-top-right-radius: ' + this.radius + 'px; '
  129. style += 'border-bottom-right-radius: ' + this.radius + 'px; '
  130. this.popupAnim = ['slide-left']
  131. break
  132. case 'right':
  133. if (this.mode === 'size-fixed') {
  134. style += 'width: ' + this.width + 'rpx; '
  135. } else if (this.mode === 'size-auto') {
  136. style += 'min-width: ' + this.width + 'rpx; '
  137. style += 'width: auto; '
  138. }
  139. style += 'height: 100%; '
  140. style += 'top: 0; right: 0; bottom: 0; '
  141. style += 'border-top-left-radius: ' + this.radius + 'px; '
  142. style += 'border-bottom-left-radius: ' + this.radius + 'px; '
  143. this.popupAnim = ['slide-right']
  144. break
  145. case 'center':
  146. style += 'border-radius: ' + this.radius + 'px;'
  147. style += 'width: ' + this.width + 'rpx; '
  148. style += 'height: ' + this.height + 'rpx; '
  149. let statusBarHeight = uni.getSystemInfoSync().statusBarHeight
  150. // #ifdef H5
  151. style += 'left: ' + (this.w - this.rpxToPx(this.width)) / 2 + 'px; top: ' + (this.h - this.rpxToPx(this.height)) / 2 +
  152. 'px; '
  153. // #endif
  154. // #ifndef H5 || MP-WEIXIN
  155. style += 'left: ' + (this.w - this.rpxToPx(this.width)) / 2 + 'px; top: ' + (((this.h - this.rpxToPx(this.height)) / 2) -
  156. 45 - statusBarHeight) + 'px; '
  157. // #endif
  158. // #ifdef MP-WEIXIN
  159. let navBarHeight = wx.getMenuButtonBoundingClientRect().bottom
  160. style += 'left: ' + (this.w - this.rpxToPx(this.width)) / 2 + 'px; top: ' + (this.h - this.rpxToPx(this.height)) / 2 -
  161. statusBarHeight - navBarHeight + 'px; '
  162. // #endif
  163. if (this.centerAnim === 'zoom-lessen') {
  164. this.popupAnim = ['fade', 'zoom-lessen']
  165. } else if (this.centerAnim === 'zoom-largen') {
  166. this.popupAnim = ['fade', 'zoom-largen']
  167. } else if (this.centerAnim === 'fade') {
  168. this.popupAnim = ['fade']
  169. } else if (this.centerAnim === 'bounce') {
  170. this.popupAnim = ['bounce', 'fade']
  171. } else if (this.centerAnim === 'slide-up') {
  172. this.popupAnim = ['fade', 'slide-up']
  173. } else if (this.centerAnim === 'slide-down') {
  174. this.popupAnim = ['fade', 'slide-down']
  175. }
  176. break
  177. }
  178. return style
  179. },
  180. processMask() {
  181. let style = 'z-index: ' + (parseInt(this.zIndex) - 1) + '; '
  182. style += 'background-color: rgba(0, 0, 0, ' + this.maskAlpha +
  183. '); position: fixed; top: 0; left: 0; right: 0; bottom: 0;'
  184. style += 'width: ' + this.w + 'px; '
  185. style += 'height: ' + this.h + 'px; '
  186. return style
  187. },
  188. processClose() {
  189. let style = 'position: absolute; font-size: 40rpx; color: #808080;'
  190. switch (this.closeIconPos) {
  191. case 'top-right':
  192. style += 'top: 22rpx; right: 22rpx;'
  193. break
  194. case 'top-left':
  195. style += 'top: 22rpx; left: 22rpx;'
  196. break
  197. case 'bottom-left':
  198. style += 'bottom: 22rpx; left: 22rpx;'
  199. break
  200. case 'bottom-right':
  201. style += 'bottom: 22rpx; right: 22rpx;'
  202. break
  203. }
  204. return style
  205. },
  206. close() {
  207. this.maskClickClose && this.hide()
  208. },
  209. show() {
  210. this.root = this.processStyle()
  211. this.maskRoot = this.processMask()
  212. this.closeRoot = this.processClose()
  213. this.isShow = true
  214. setTimeout(function() {
  215. this.isPopupShow = true
  216. setTimeout(function() {
  217. this.$emit('show')
  218. }.bind(this), this.duration + 10)
  219. }.bind(this), 10)
  220. },
  221. hide() {
  222. this.isPopupShow = false
  223. setTimeout(function() {
  224. this.isShow = false
  225. this.$emit('hide')
  226. }.bind(this), this.duration + 10)
  227. },
  228. rpxToPx(rpx) {
  229. return rpx / 750 * this.w
  230. }
  231. }
  232. }
  233. </script>
  234. <style>
  235. @import "./iconfont.css";
  236. </style>