木邻有你前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
4.8 KiB

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
  1. <template>
  2. <!-- 如何让他点击遮罩层的时候关闭弹窗 -->
  3. <view v-if="visible" class="popup-overlay" @click="close">
  4. <view class="popup-content" @click.stop :animation="animationData" :style="{backgroundImage: `${bgImage}`}">
  5. <image class="popup-title" :src="titleImage" mode="aspectFit"></image>
  6. <!-- <view class="popup-header"> -->
  7. <text class="popup-text">{{ content }}</text>
  8. <text class="popup-subtext">{{ subContent }}</text>
  9. <!-- </view> -->
  10. <button v-if="popupType === 'success'" class="popup-btn success" @click="close">我知道了</button>
  11. <button v-else class="popup-btn fail" @click="close">好的</button>
  12. </view>
  13. </view>
  14. </template>
  15. <script>
  16. export default {
  17. name: 'GlobalPopup',
  18. data() {
  19. return {
  20. visible: false,
  21. content: '',
  22. subContent: '',
  23. titleType: '',
  24. popupType: '',
  25. animationData: {},
  26. closefn: () => {}
  27. }
  28. },
  29. computed: {
  30. bgImage() {
  31. return `url(${this.popupType === 'success' ? '/static/成功弹窗.png' : '/static/失败弹窗.png'})`
  32. },
  33. titleImage() {
  34. switch (this.titleType) {
  35. case 'exchange':
  36. if (this.popupType === 'success') {
  37. return '/static/兑换成功.png'
  38. }else{
  39. return '/static/兑换失败.png'
  40. }
  41. case 'signup':
  42. return '/static/报名成功.png'
  43. case 'submit':
  44. return '/static/提交成功.png'
  45. default:
  46. return ''
  47. }
  48. }
  49. },
  50. methods: {
  51. close() {
  52. this.createHideAnimation()
  53. this.closefn()
  54. },
  55. // 主内容 副内容 标题类型 弹窗类型
  56. open({
  57. content = '默认内容',
  58. subContent = '默认子内容',
  59. titleType = 'exchange', // 报名 兑换 提交
  60. popupType = 'success', // 成功 失败
  61. closefn = () => {}
  62. }) {
  63. this.content = content
  64. this.subContent = subContent
  65. this.titleType = titleType
  66. this.popupType = popupType
  67. // 先设置初始动画状态
  68. this.setInitialAnimation()
  69. // 显示弹窗
  70. this.visible = true
  71. // 延迟执行显示动画
  72. this.$nextTick(() => {
  73. setTimeout(() => {
  74. this.createShowAnimation()
  75. }, 50)
  76. })
  77. this.closefn = closefn
  78. },
  79. // 设置初始动画状态
  80. setInitialAnimation() {
  81. const animation = uni.createAnimation({
  82. transformOrigin: "50% 50%",
  83. duration: 0,
  84. timingFunction: "ease-out",
  85. delay: 0
  86. })
  87. animation.translateX('-50%').translateY('-50%').scale(0).opacity(0).step()
  88. this.animationData = animation.export()
  89. },
  90. // 创建弹窗显示动画
  91. createShowAnimation() {
  92. const animation = uni.createAnimation({
  93. transformOrigin: "50% 50%",
  94. duration: 200,
  95. timingFunction: "ease-out",
  96. delay: 0
  97. })
  98. // 动画到最终状态:保持居中,缩放为1,透明度为1
  99. animation.translateX('-50%').translateY('-50%').scale(1).opacity(1).step()
  100. this.animationData = animation.export()
  101. },
  102. // 创建弹窗隐藏动画
  103. createHideAnimation() {
  104. const animation = uni.createAnimation({
  105. transformOrigin: "50% 50%",
  106. duration: 200,
  107. timingFunction: "ease-in",
  108. delay: 0
  109. })
  110. animation.translateX('-50%').translateY('-50%').scale(0).opacity(0).step()
  111. this.animationData = animation.export()
  112. // 动画结束后隐藏弹窗
  113. setTimeout(() => {
  114. this.visible = false
  115. }, 200)
  116. }
  117. }
  118. }
  119. </script>
  120. <style scoped lang="scss">
  121. .popup-overlay {
  122. position: fixed;
  123. inset: 0;
  124. width: 100%;
  125. height: 100%;
  126. background: #00000050;
  127. z-index: 999;
  128. .popup-content {
  129. position: absolute;
  130. top: 50%;
  131. left: 50%;
  132. width: 632rpx;
  133. padding: 0;
  134. height: 830rpx;
  135. // background: red;
  136. // border-radius: 20rpx;
  137. background-size: 100% 100%;
  138. .popup-title{
  139. position: absolute;
  140. top: 44rpx;
  141. left: 88rpx;
  142. height: 100rpx;
  143. width: 254rpx;
  144. }
  145. .popup-btn{
  146. position: absolute;
  147. bottom: 30rpx;
  148. left: 50%;
  149. transform: translateX(-50%);
  150. width: 432rpx;
  151. height: 94rpx;
  152. border-radius: 20.5px;
  153. // width: 28px;
  154. font-size: 14px;
  155. line-height: 94rpx;
  156. color: #ffffff;
  157. }
  158. .success{
  159. background: #1488db;
  160. }
  161. .fail{
  162. background: #e54b4b;
  163. }
  164. .popup-text{
  165. font-size: 16px;
  166. position: absolute;
  167. top: 480rpx;
  168. left: 50%;
  169. transform: translateX(-50%);
  170. font-weight: 700;
  171. color: #000000;
  172. white-space: nowrap;
  173. // text-align: center;
  174. }
  175. .popup-subtext{
  176. position: absolute;
  177. bottom: 252rpx;
  178. left: 50%;
  179. transform: translateX(-50%);
  180. font-size: 14px;
  181. color: #999999;
  182. white-space: nowrap;
  183. // text-align: center;
  184. }
  185. }
  186. }
  187. </style>