voice.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <template>
  2. <view class="voice">
  3. <button class="adjunction dir-left-nowrap cross-center" @click="open()" v-if="Object.keys(audio).length === 0">
  4. <view class="recording"></view>
  5. <view class="text">添加语音祝福</view>
  6. </button>
  7. <view class="audio dir-left-nowrap cross-center" v-else>
  8. <view class="btn" @click="playaudio" :class="[is_play ? 'btn-pause' : 'btn-play']"></view>
  9. <view class="duration">{{voice_i}}″</view>
  10. <view class="close" @click="close()"></view>
  11. </view>
  12. <view class="black" v-if="start_tran" @click.stop="start_tran = false">
  13. <view class="mouldboard dir-top-nowrap cross-center" @click.stop>
  14. <view class="voice-num">{{voice_i | second}}</view>
  15. <view class="transcription" :class="[`${theme}-background`]" @touchstart="start" @touchend="end">
  16. <image :src="animationStatus ? '../../image/transcriptioning.png' : '../../image/transcription.png'" class="image"/>
  17. <view class="ripple" :class="[`${theme}-border`]" :animation="animationData1"></view>
  18. <view class="ripple" :class="[`${theme}-border`]" :animation="animationData2"></view>
  19. </view>
  20. <view class="active-text">{{animationStatus ? '松开停止录音' : '长按开始录音'}}</view>
  21. </view>
  22. </view>
  23. </view>
  24. </template>
  25. <script>
  26. export default {
  27. name: 'voice',
  28. props: [`theme`, `is_play`, `audio`, `voice_i`],
  29. data() {
  30. return {
  31. animationData1: '',
  32. animationData2: '',
  33. animationStatus: false,
  34. manager: null,
  35. start_tran: false,
  36. }
  37. },
  38. watch: {
  39. voice_i: {
  40. handler(data) {
  41. if (data >= 30) {
  42. this.end();
  43. }
  44. },
  45. }
  46. },
  47. methods: {
  48. animationFun:function(animationData){
  49. if(!this.animationStatus){
  50. return;
  51. }
  52. var animation = uni.createAnimation({
  53. duration: 1000
  54. })
  55. animation.opacity(0).scale(1.5,1.5).step();
  56. this[animationData] = animation.export();
  57. },
  58. animationEnd: function (animationData) {
  59. var animation = uni.createAnimation({
  60. duration: 0
  61. })
  62. animation.opacity(1).scale(1, 1).step();
  63. this[animationData] = animation.export()
  64. },
  65. recodeEnd: function() {
  66. //动画1结束
  67. var animation1 = uni.createAnimation({
  68. duration: 0
  69. })
  70. animation1.opacity(1).scale(1, 1).step();
  71. //动画2结束
  72. var animation2 = uni.createAnimation({
  73. duration: 0
  74. })
  75. animation2.opacity(1).scale(1, 1).step();
  76. this.animationData1 = animation1.export();
  77. this.animationData2 = animation2.export();
  78. this.animationStatus = false;
  79. },
  80. recodeClick: function() {
  81. this.animationStatus = true;
  82. this.animationFun('animationData1');
  83. setTimeout(()=>{
  84. this.animationFun('animationData2');
  85. },500)
  86. setTimeout(() => {
  87. this.animationRest();
  88. }, 1000)
  89. },
  90. animationRest: function() {
  91. this.animationEnd('animationData1');
  92. setTimeout(()=>{
  93. this.animationEnd('animationData2');
  94. },500);
  95. setTimeout(() => {
  96. if (this.animationStatus) {
  97. this.recodeClick();
  98. }
  99. }, 100);
  100. },
  101. start() {
  102. this.recodeClick();
  103. this.$emit('recorder', true);
  104. },
  105. end() {
  106. this.recodeEnd();
  107. this.$emit('recorder', false);
  108. this.start_tran = false;
  109. },
  110. playaudio() {
  111. if (this.is_play) {
  112. this.$emit('play', false);
  113. } else {
  114. this.$emit('play', true);
  115. }
  116. },
  117. open() {
  118. let self = this;
  119. // #ifdef MP
  120. wx.getSetting({
  121. success(res) {
  122. if (!res.authSetting['scope.record']) {
  123. wx.authorize({
  124. scope: 'scope.record',
  125. success () {
  126. self.start_tran = true;
  127. self.$emit('click');
  128. },
  129. fail(e) {
  130. wx.showModal({
  131. title: '提示',
  132. content: '您未授权录音,功能将无法使用',
  133. showCancel: true,
  134. confirmText: "授权",
  135. confirmColor: "#52a2d8",
  136. success() {
  137. wx.openSetting({
  138. success: (res) => {
  139. if (!res.authSetting['scope.record']) {
  140. } else {
  141. self.start_tran = true;
  142. self.$emit('click');
  143. }
  144. },
  145. fail(e) {
  146. }
  147. })
  148. }
  149. })
  150. }
  151. })
  152. } else {
  153. self.start_tran = true;
  154. self.$emit('click');
  155. }
  156. },
  157. fail(e) {
  158. }
  159. });
  160. // #endif
  161. // #ifdef H5
  162. self.start_tran = true;
  163. // #endif
  164. },
  165. close() {
  166. this.audio = {}
  167. this.$emit('close');
  168. }
  169. },
  170. filters: {
  171. second(data) {
  172. if (data < 10) {
  173. return '00:0' + data;
  174. } else {
  175. return '00:' + data;
  176. }
  177. }
  178. }
  179. }
  180. </script>
  181. <style lang="scss" scoped>
  182. @import '../../css/gift.scss';
  183. .audio {
  184. height: #{80upx};
  185. width: #{376upx};
  186. border-radius: #{40upx};
  187. margin-left: #{24upx};
  188. padding: 0;
  189. background-color: #49c265;
  190. }
  191. .btn {
  192. width: #{96upx};
  193. height: #{80upx};
  194. padding: #{16upx 32upx 16upx 16upx};
  195. background-repeat: no-repeat;
  196. background-size: 52% 60%;
  197. background-position: center #{16upx};
  198. }
  199. .btn-play {
  200. background-image: url('../../image/play.png');
  201. }
  202. .btn-pause {
  203. background-image: url('../../image/pause.png');
  204. }
  205. .duration {
  206. width: #{210upx};
  207. text-align: right;
  208. font-size: #{30upx};
  209. color: #ffffff;
  210. padding-right: #{28upx};
  211. border-right: #{1upx} solid #ffffff;
  212. height: #{30upx};
  213. line-height: #{30upx};
  214. }
  215. .close {
  216. width: #{48upx};
  217. height: #{80upx};
  218. padding: #{30upx 28upx 30upx 28upx};
  219. background-image: url('../../image/close.png');
  220. background-repeat: no-repeat;
  221. background-position: center;
  222. background-size: 41.6% 25%;
  223. }
  224. .adjunction {
  225. height: #{80upx};
  226. width: #{278upx};
  227. line-height: #{80upx};
  228. background-color: #ffffff;
  229. border-radius: #{40upx};
  230. margin-left: #{24upx};
  231. margin-bottom: #{56upx};
  232. padding: 0;
  233. }
  234. .text {
  235. font-size: #{28upx};
  236. color: #666666;
  237. margin-left: #{8upx};
  238. }
  239. .recording {
  240. width: #{32upx};
  241. height: #{32upx};
  242. margin-left: #{32upx};
  243. background-repeat: no-repeat;
  244. background-image: url('../../image/recording.png');
  245. background-size: 100% 100%;
  246. }
  247. .black {
  248. position: fixed;
  249. top: 0;
  250. width: 100%;
  251. height: 100%;
  252. z-index: 1600;
  253. background-color: rgba(0,0,0,.5);
  254. }
  255. .mouldboard {
  256. width: #{750upx};
  257. height: #{480upx};
  258. background-color: #ffffff;
  259. position: absolute;
  260. bottom: 0;
  261. border-top-right-radius: #{16upx};
  262. border-top-left-radius: #{16upx};
  263. }
  264. .transcription {
  265. width: #{200upx};
  266. height: #{200upx};
  267. border-radius: 50%;
  268. margin-top: #{50upx};
  269. position: relative;
  270. }
  271. .active-text {
  272. margin-top: #{48upx};
  273. font-size: #{28upx};
  274. color: #999999;
  275. }
  276. .image {
  277. width: #{110upx};
  278. height: #{110upx};
  279. position: absolute;
  280. top: 50%;
  281. left: 50%;
  282. transform: translate(-50%, -50%);
  283. }
  284. .ripple{
  285. position: absolute;
  286. top:0;
  287. left:0;
  288. right:0;
  289. bottom:0;
  290. border-radius: 50%;
  291. }
  292. .voice-num {
  293. font-size: #{30upx};
  294. margin-top: #{50upx};
  295. color: #353535;
  296. font-family: 'DIN';
  297. }
  298. </style>