MassMessageRender.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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. .audio_message_container {
  77. @include vCenterBox();
  78. .audio_duration {
  79. font-size: 28rpx;
  80. }
  81. .cricleplay {
  82. display: flex;
  83. align-items: center;
  84. margin-right: 12rpx;
  85. .small {
  86. width: 5px;
  87. height: 5px;
  88. border-style: solid;
  89. border-color: #3870e4;
  90. border-top-color: transparent;
  91. border-left-color: transparent;
  92. border-bottom-color: transparent;
  93. border-radius: 50%;
  94. box-sizing: border-box;
  95. vertical-align: middle;
  96. display: inline-block;
  97. }
  98. .middle {
  99. width: 10px;
  100. height: 10px;
  101. border-style: solid;
  102. border-color: #3870e4;
  103. border-top-color: transparent;
  104. border-left-color: transparent;
  105. border-bottom-color: transparent;
  106. border-radius: 50%;
  107. box-sizing: border-box;
  108. vertical-align: middle;
  109. display: inline-block;
  110. margin-left: -5px;
  111. animation: show2 2s ease-in-out infinite;
  112. opacity: 1;
  113. }
  114. @keyframes show2 {
  115. 0% {
  116. opacity: 0;
  117. }
  118. 30% {
  119. opacity: 1;
  120. }
  121. 100% {
  122. opacity: 0;
  123. }
  124. }
  125. .large {
  126. width: 20px;
  127. height: 20px;
  128. border-style: solid;
  129. border-color: #3870e4;
  130. border-top-color: transparent;
  131. border-left-color: transparent;
  132. border-bottom-color: transparent;
  133. border-radius: 50%;
  134. box-sizing: border-box;
  135. vertical-align: middle;
  136. display: inline-block;
  137. margin-left: -15px;
  138. animation: show3 2s ease-in-out infinite;
  139. opacity: 1;
  140. }
  141. @keyframes show3 {
  142. 0% {
  143. opacity: 0;
  144. }
  145. 60% {
  146. opacity: 1;
  147. }
  148. 100% {
  149. opacity: 0;
  150. }
  151. }
  152. .stopanimate {
  153. -moz-animation-name: none;
  154. -webkit-animation-name: none;
  155. -ms-animation-name: none;
  156. animation-name: none;
  157. }
  158. }
  159. &_self {
  160. flex-direction: row-reverse;
  161. .cricleplay {
  162. margin-right: 0;
  163. margin-left: 12rpx;
  164. flex-direction: row-reverse;
  165. .small,
  166. .middle,
  167. .large {
  168. border-left-color: #3870e4;
  169. border-right-color: transparent;
  170. }
  171. .middle {
  172. margin-left: 0;
  173. margin-right: -5px;
  174. }
  175. .large {
  176. margin-left: 0;
  177. margin-right: -15px;
  178. }
  179. }
  180. }
  181. }
  182. </style>