MassMessageRender.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <template>
  2. <view class="text_message_container bg_container" v-if="isText">
  3. <mp-html :previewImg="false" :showImgMenu="false" :lazyLoad="false" :content="getContent" />
  4. </view>
  5. <view @click="playAudio" class="audio_message_container bg_container"
  6. :class="{ audio_message_container_self: isSender }" v-else>
  7. <view class="cricleplay">
  8. <view class="small"></view>
  9. <view class="middle" :class="{ stopanimate: !playing }"></view>
  10. <view class="large" :class="{ stopanimate: !playing }"></view>
  11. </view>
  12. <text class="audio_duration">{{ data.soundElem.duration }}''</text>
  13. </view>
  14. </template>
  15. <script>
  16. export default {
  17. name: "MassMessageRender",
  18. props: {
  19. isSender: Boolean,
  20. data: Object,
  21. },
  22. data() {
  23. return {
  24. playing: false,
  25. paused: false,
  26. innerAudioContext: uni.createInnerAudioContext(),
  27. };
  28. },
  29. mounted() {
  30. this.setPlayListener();
  31. },
  32. beforeDestroy() {
  33. this.innerAudioContext.destroy();
  34. },
  35. computed: {
  36. isText() {
  37. return this.data.textElem !== null
  38. },
  39. getContent() {
  40. if (this.isText) {
  41. return this.data.textElem.content
  42. }
  43. },
  44. },
  45. methods: {
  46. setPlayListener() {
  47. const onPlayHandler = () => {
  48. this.playing = true;
  49. this.paused = false;
  50. };
  51. const onPauseOrStorHandler = () => {
  52. this.playing = false;
  53. this.paused = true;
  54. };
  55. this.innerAudioContext.onPlay(onPlayHandler);
  56. this.innerAudioContext.onPause(onPauseOrStorHandler);
  57. this.innerAudioContext.onEnded(onPauseOrStorHandler);
  58. },
  59. playAudio() {
  60. this.setPlayListener();
  61. if (this.paused) {
  62. this.innerAudioContext.play();
  63. return;
  64. }
  65. if (this.playing) {
  66. this.innerAudioContext.pause();
  67. return;
  68. }
  69. this.innerAudioContext.src = this.data.soundElem.sourceUrl;
  70. this.innerAudioContext.play();
  71. },
  72. }
  73. };
  74. </script>
  75. <style lang="scss" scoped>
  76. .bg_container {
  77. padding: 16rpx 24rpx;
  78. border-radius: 0rpx 12rpx 12rpx 12rpx;
  79. background-color: #f0f0f0;
  80. }
  81. .audio_message_container {
  82. @include vCenterBox();
  83. .audio_duration {
  84. font-size: 28rpx;
  85. }
  86. .cricleplay {
  87. display: flex;
  88. align-items: center;
  89. margin-right: 12rpx;
  90. .small {
  91. width: 5px;
  92. height: 5px;
  93. border-style: solid;
  94. border-color: #3870e4;
  95. border-top-color: transparent;
  96. border-left-color: transparent;
  97. border-bottom-color: transparent;
  98. border-radius: 50%;
  99. box-sizing: border-box;
  100. vertical-align: middle;
  101. display: inline-block;
  102. }
  103. .middle {
  104. width: 10px;
  105. height: 10px;
  106. border-style: solid;
  107. border-color: #3870e4;
  108. border-top-color: transparent;
  109. border-left-color: transparent;
  110. border-bottom-color: transparent;
  111. border-radius: 50%;
  112. box-sizing: border-box;
  113. vertical-align: middle;
  114. display: inline-block;
  115. margin-left: -5px;
  116. animation: show2 2s ease-in-out infinite;
  117. opacity: 1;
  118. }
  119. @keyframes show2 {
  120. 0% {
  121. opacity: 0;
  122. }
  123. 30% {
  124. opacity: 1;
  125. }
  126. 100% {
  127. opacity: 0;
  128. }
  129. }
  130. .large {
  131. width: 20px;
  132. height: 20px;
  133. border-style: solid;
  134. border-color: #3870e4;
  135. border-top-color: transparent;
  136. border-left-color: transparent;
  137. border-bottom-color: transparent;
  138. border-radius: 50%;
  139. box-sizing: border-box;
  140. vertical-align: middle;
  141. display: inline-block;
  142. margin-left: -15px;
  143. animation: show3 2s ease-in-out infinite;
  144. opacity: 1;
  145. }
  146. @keyframes show3 {
  147. 0% {
  148. opacity: 0;
  149. }
  150. 60% {
  151. opacity: 1;
  152. }
  153. 100% {
  154. opacity: 0;
  155. }
  156. }
  157. .stopanimate {
  158. -moz-animation-name: none;
  159. -webkit-animation-name: none;
  160. -ms-animation-name: none;
  161. animation-name: none;
  162. }
  163. }
  164. &_self {
  165. flex-direction: row-reverse;
  166. .cricleplay {
  167. margin-right: 0;
  168. margin-left: 12rpx;
  169. flex-direction: row-reverse;
  170. .small,
  171. .middle,
  172. .large {
  173. border-left-color: #3870e4;
  174. border-right-color: transparent;
  175. }
  176. .middle {
  177. margin-left: 0;
  178. margin-right: -5px;
  179. }
  180. .large {
  181. margin-left: 0;
  182. margin-right: -15px;
  183. }
  184. }
  185. }
  186. }
  187. </style>