speaking.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <template>
  2. <view class="speak-container">
  3. <view
  4. ref="talkRef"
  5. class="talk"
  6. :class="{
  7. normal: normalModel,
  8. start: startModel,
  9. startMouseover: startOverModel,
  10. }"
  11. @touchstart="handleTouchStart"
  12. @touchend="handleTouchEnd"
  13. >{{ talkText }}
  14. <LottieRecording class="lottie" v-if="isShowLottieR" />
  15. <text class="lottie-text" v-if="isShowLottieR">{{ lottieText }}</text>
  16. <yimo-AudioTrans
  17. ref="yimoAudioTransRef"
  18. :options="options"
  19. @countDown="countDown"
  20. @result="resultMsg"
  21. @onStop="onStop"
  22. @onOpen="onOpen"
  23. @change="change"
  24. ></yimo-AudioTrans>
  25. </view>
  26. </view>
  27. </template>
  28. <script setup>
  29. import { onMounted, ref } from "vue";
  30. import LottieRecording from "../../components/lottie/lottie-recording.vue";
  31. import noticeBar from "../../uni_modules/uview-plus/components/u-notice-bar/noticeBar";
  32. const emits = defineEmits(["recordResult"]);
  33. // 动画相关
  34. const isShowLottieR = ref(false);
  35. const showLottieR = () => {
  36. isShowLottieR.value = true;
  37. };
  38. // 按住说话===================
  39. const talkRef = ref(null);
  40. //文字
  41. const normalText = "按住 说话";
  42. const startText = "松手 发送";
  43. const mouseOverText = "松手 取消";
  44. const talkText = ref("");
  45. let lottieTextNormal = "松手发送,上移取消";
  46. let lottieTextCancel = "滑动到按钮区域回复录音";
  47. const lottieText = ref("");
  48. // 样式控制
  49. const normalModel = ref(false);
  50. const startModel = ref(false);
  51. const startOverModel = ref(false);
  52. // 相关方法
  53. const handleTouchStart = () => {
  54. normalModel.value = false;
  55. startModel.value = true;
  56. talkText.value = startText;
  57. // 开始录音
  58. yimoAudioTransRef.value && yimoAudioTransRef.value.start();
  59. };
  60. const handleTouchEnd = () => {
  61. // 结束录音
  62. yimoAudioTransRef.value && yimoAudioTransRef.value.end();
  63. initTalkModel();
  64. };
  65. const handleTouchMove = (event) => {
  66. if (!startModel.value) return;
  67. const touch = event.touches[0];
  68. const currentX = touch.clientX;
  69. const currentY = touch.clientY;
  70. console.log("handleTouchMove", talkRef.value);
  71. const rect = talkRef.value.getBoundingClientRect();
  72. const isInsideX = currentX >= rect.left && currentX <= rect.right;
  73. const isInsideY = currentY >= rect.top && currentY <= rect.bottom;
  74. if (!isInsideX || !isInsideY) {
  75. // 超出范围
  76. startModel.value = false;
  77. startOverModel.value = true;
  78. talkText.value = mouseOverText;
  79. } else {
  80. // 移动中
  81. startModel.value = true;
  82. startOverModel.value = false;
  83. talkText.value = startText;
  84. }
  85. };
  86. const mouseOver = () => {
  87. startModel.value = false;
  88. startOverModel.value = true;
  89. talkText.value = mouseOverText;
  90. };
  91. const mouseIn = () => {
  92. startModel.value = true;
  93. startOverModel.value = false;
  94. talkText.value = startText;
  95. };
  96. const initTalkModel = () => {
  97. normalModel.value = true;
  98. startModel.value = false;
  99. startOverModel.value = false;
  100. talkText.value = normalText;
  101. isShowLottieR.value = false;
  102. lottieText.value = lottieTextNormal;
  103. };
  104. // ==================== 语音相关 =
  105. const yimoAudioTransRef = ref(null);
  106. const options = ref({
  107. receordingDuration: 20,
  108. APPID: "d6d15e17",
  109. API_SECRET: "NmIyZWFjYzMxNTEwMmRjZTE0YjcxNzIw",
  110. API_KEY: "172b9f1528efa9442956f2f26f34ead0",
  111. });
  112. const countDown = (duration) => {
  113. console.log("countDown", duration);
  114. };
  115. const resultMsg = (msg) => {
  116. console.log("resultMsg", msg);
  117. emits("recordResult", msg);
  118. };
  119. const onStop = () => {
  120. console.log("onStop");
  121. };
  122. const onOpen = () => {
  123. console.log("onOpen");
  124. showLottieR();
  125. };
  126. const change = (msg) => {
  127. console.log("change", msg);
  128. };
  129. onMounted(() => {
  130. initTalkModel();
  131. });
  132. </script>
  133. <style lang="scss" scoped>
  134. .speak-container {
  135. width: 100%;
  136. height: 30rpx;
  137. display: flex;
  138. flex-direction: column;
  139. justify-content: center;
  140. align-items: center;
  141. min-height: 300px;
  142. background-color: lightgrey;
  143. .talk {
  144. margin-top: 100px;
  145. width: 80%;
  146. height: 40px;
  147. line-height: 40px;
  148. border-radius: 20px;
  149. font-size: 20px;
  150. text-align: center;
  151. font-weight: bold;
  152. position: relative;
  153. .lottie {
  154. position: absolute;
  155. top: -85px;
  156. left: 0;
  157. }
  158. .lottie-text {
  159. width: 100%;
  160. font-size: 14px;
  161. color: #1f1f1f;
  162. text-align: center;
  163. position: absolute;
  164. top: -35px;
  165. left: 0;
  166. }
  167. }
  168. .normal {
  169. color: black;
  170. background-color: white;
  171. }
  172. .start {
  173. color: white;
  174. background-color: blue;
  175. }
  176. .startMouseover {
  177. color: black;
  178. background-color: red;
  179. }
  180. }
  181. </style>