CustomDialog.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <template>
  2. <view class="custom-dialog" v-if="visible">
  3. <view class="dialog-mask" @click="closeDialog"></view>
  4. <view class="dialog-content" :class="{'dialog-show': visible}" :animation="animationData" :style="{ width: contentWidth, background: backgroundColor }">
  5. <view class="dialog-header" v-if="title && title.length > 0">
  6. <text class="dialog-title">{{title}}</text>
  7. </view>
  8. <view class="dialog-close" @click="closeDialog" v-if="!closeImg">×</view>
  9. <image v-if="closeImg" class="dialog-close-img" :src="closeImg" @click="closeDialog" mode="aspectFit" :style="{ top: closeImgTop && closeImgTop.length > 0 ? closeImgTop : '20rpx' }"></image>
  10. <view class="dialog-body">
  11. <slot></slot>
  12. </view>
  13. </view>
  14. </view>
  15. </template>
  16. <script>
  17. export default {
  18. name: 'CustomDialog',
  19. props: {
  20. visible: {
  21. type: Boolean,
  22. default: false
  23. },
  24. title: {
  25. type: String,
  26. default: '提示'
  27. },
  28. contentWidth: {
  29. type: String,
  30. default: '600rpx'
  31. },
  32. backgroundColor: {
  33. type: String,
  34. default: '#fff'
  35. },
  36. closeImg: {
  37. type: String,
  38. default: ''
  39. },
  40. closeImgTop: {
  41. type: String,
  42. default: ''
  43. }
  44. },
  45. data() {
  46. return {
  47. animationData: {}
  48. }
  49. },
  50. watch: {
  51. visible(val) {
  52. if (val) {
  53. this.playShowAnimation()
  54. } else {
  55. this.playHideAnimation()
  56. }
  57. }
  58. },
  59. methods: {
  60. playShowAnimation() {
  61. const animation = uni.createAnimation({
  62. duration: 300,
  63. timingFunction: 'ease'
  64. })
  65. animation.scale(0.8).opacity(0).step({ duration: 0 })
  66. animation.scale(1.1).opacity(1).step({ duration: 150 })
  67. animation.scale(0.95).step({ duration: 75 })
  68. animation.scale(1).step({ duration: 75 })
  69. this.animationData = animation.export()
  70. },
  71. playHideAnimation() {
  72. const animation = uni.createAnimation({
  73. duration: 200,
  74. timingFunction: 'ease'
  75. })
  76. animation.scale(0.95).opacity(0.8).step({ duration: 100 })
  77. animation.scale(0.8).opacity(0).step({ duration: 100 })
  78. this.animationData = animation.export()
  79. },
  80. closeDialog() {
  81. this.$emit('update:visible', false)
  82. this.$emit('close')
  83. }
  84. }
  85. }
  86. </script>
  87. <style lang="scss" scoped>
  88. .custom-dialog {
  89. position: fixed;
  90. top: 0;
  91. left: 0;
  92. right: 0;
  93. bottom: 0;
  94. z-index: 900;
  95. display: flex;
  96. align-items: center;
  97. justify-content: center;
  98. .dialog-mask {
  99. position: absolute;
  100. top: 0;
  101. left: 0;
  102. right: 0;
  103. bottom: 0;
  104. background: rgba(0, 0, 0, 0.6);
  105. }
  106. .dialog-content {
  107. position: relative;
  108. border-radius: 16rpx;
  109. overflow: hidden;
  110. opacity: 0;
  111. transform: scale(0.8);
  112. &.dialog-show {
  113. opacity: 1;
  114. transform: scale(1);
  115. }
  116. }
  117. .dialog-header {
  118. position: relative;
  119. padding: 30rpx;
  120. text-align: center;
  121. border-bottom: 1rpx solid #eee;
  122. .dialog-title {
  123. font-size: 32rpx;
  124. font-weight: 500;
  125. color: #333;
  126. }
  127. }
  128. .dialog-close {
  129. position: absolute;
  130. right: 20rpx;
  131. top: 20rpx;
  132. width: 60rpx;
  133. height: 60rpx;
  134. line-height: 60rpx;
  135. text-align: center;
  136. font-size: 40rpx;
  137. color: #999;
  138. cursor: pointer;
  139. z-index: 1;
  140. &:active {
  141. opacity: 0.7;
  142. }
  143. }
  144. .dialog-close-img {
  145. position: absolute;
  146. right: 20rpx;
  147. width: 60rpx;
  148. height: 60rpx;
  149. z-index: 1;
  150. cursor: pointer;
  151. &:active {
  152. opacity: 0.7;
  153. }
  154. }
  155. .dialog-body {
  156. padding: 0rpx;
  157. }
  158. }
  159. </style>