CustomDialog.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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 }">
  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"></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. closeImg: {
  33. type: String,
  34. default: ''
  35. }
  36. },
  37. data() {
  38. return {
  39. animationData: {}
  40. }
  41. },
  42. watch: {
  43. visible(val) {
  44. if (val) {
  45. this.playShowAnimation()
  46. } else {
  47. this.playHideAnimation()
  48. }
  49. }
  50. },
  51. methods: {
  52. playShowAnimation() {
  53. const animation = uni.createAnimation({
  54. duration: 300,
  55. timingFunction: 'ease'
  56. })
  57. animation.scale(0.8).opacity(0).step({ duration: 0 })
  58. animation.scale(1.1).opacity(1).step({ duration: 150 })
  59. animation.scale(0.95).step({ duration: 75 })
  60. animation.scale(1).step({ duration: 75 })
  61. this.animationData = animation.export()
  62. },
  63. playHideAnimation() {
  64. const animation = uni.createAnimation({
  65. duration: 200,
  66. timingFunction: 'ease'
  67. })
  68. animation.scale(0.95).opacity(0.8).step({ duration: 100 })
  69. animation.scale(0.8).opacity(0).step({ duration: 100 })
  70. this.animationData = animation.export()
  71. },
  72. closeDialog() {
  73. this.$emit('update:visible', false)
  74. this.$emit('close')
  75. }
  76. }
  77. }
  78. </script>
  79. <style lang="scss" scoped>
  80. .custom-dialog {
  81. position: fixed;
  82. top: 0;
  83. left: 0;
  84. right: 0;
  85. bottom: 0;
  86. z-index: 900;
  87. display: flex;
  88. align-items: center;
  89. justify-content: center;
  90. .dialog-mask {
  91. position: absolute;
  92. top: 0;
  93. left: 0;
  94. right: 0;
  95. bottom: 0;
  96. background: rgba(0, 0, 0, 0.6);
  97. }
  98. .dialog-content {
  99. position: relative;
  100. background: #fff;
  101. border-radius: 16rpx;
  102. overflow: hidden;
  103. opacity: 0;
  104. transform: scale(0.8);
  105. &.dialog-show {
  106. opacity: 1;
  107. transform: scale(1);
  108. }
  109. }
  110. .dialog-header {
  111. position: relative;
  112. padding: 30rpx;
  113. text-align: center;
  114. border-bottom: 1rpx solid #eee;
  115. .dialog-title {
  116. font-size: 32rpx;
  117. font-weight: 500;
  118. color: #333;
  119. }
  120. }
  121. .dialog-close {
  122. position: absolute;
  123. right: 20rpx;
  124. top: 20rpx;
  125. width: 60rpx;
  126. height: 60rpx;
  127. line-height: 60rpx;
  128. text-align: center;
  129. font-size: 40rpx;
  130. color: #999;
  131. cursor: pointer;
  132. z-index: 1;
  133. &:active {
  134. opacity: 0.7;
  135. }
  136. }
  137. .dialog-close-img {
  138. position: absolute;
  139. right: 20rpx;
  140. top: 20rpx;
  141. width: 60rpx;
  142. height: 60rpx;
  143. z-index: 1;
  144. cursor: pointer;
  145. &:active {
  146. opacity: 0.7;
  147. }
  148. }
  149. .dialog-body {
  150. padding: 30rpx;
  151. }
  152. }
  153. </style>