index.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. import { defineComponent, onMounted, onUnmounted, reactive, nextTick } from "vue";
  2. import state, { getMusicDetail, handleSetSpeed, addNoteBBox, getNote, gotoNext, fillWordColor } from "/src/state";
  3. import MusicScore from "../../view/music-score";
  4. import styles from "./index.module.less";
  5. import { getQuery } from "/src/utils/queryString";
  6. import { closeToast, showLoadingToast } from "vant";
  7. import store from "store";
  8. import { formateTimes } from "../../helpers/formateMusic";
  9. import { setCustomGradual, setCustomNoteRealValue } from "/src/helpers/customMusicScore"
  10. import { initSmoothAnimation, smoothAnimationState, destroySmoothAnimation, moveSmoothAnimationByPlayTime } from "../view-detail/smoothAnimation";
  11. import { api_cloudLoading, simple_musicPage } from "/src/helpers/communication";
  12. export default defineComponent({
  13. name: "simple-detail",
  14. setup() {
  15. const query: any = getQuery();
  16. const detailData = reactive({
  17. isLoading: true,
  18. currentTime: 0, // 当前播放的时间
  19. totalTime: 0, // 音视频总时长
  20. });
  21. const communicateCb = (res: any) => {
  22. let resInfo: any = {};
  23. try {
  24. resInfo = typeof res?.data === 'string' ? JSON.parse(res.data) : res.data;
  25. // console.log('Received data:', resInfo);
  26. } catch (error) {
  27. console.error('parse_error: Invalid JSON data received');
  28. }
  29. // 开始播放
  30. if (resInfo?.api === "api_play") {
  31. console.log('h5开始播放')
  32. state.playState = 'play';
  33. setStep();
  34. }
  35. // 暂停播放
  36. if (resInfo?.api === "api_paused") {
  37. console.log('暂停播放')
  38. state.playState = 'paused';
  39. }
  40. // 暂停状态下,拖动进度
  41. if (resInfo?.api === "api_updateProgress") {
  42. console.log('拖动的进度')
  43. if (state.playState === 'paused') {
  44. detailData.currentTime = resInfo?.content?.currentTime ? resInfo?.content?.currentTime : detailData.currentTime;
  45. handlePlaying(true);
  46. }
  47. }
  48. // 播放进度
  49. if (resInfo?.api === "api_playProgress") {
  50. // console.log('播放进度',resInfo)
  51. if (resInfo?.content?.currentTime) {
  52. if (resInfo?.content?.currentTime < detailData.currentTime) {
  53. state.activeNoteIndex = 0
  54. }
  55. detailData.currentTime = resInfo?.content?.currentTime
  56. }
  57. }
  58. };
  59. // 监听评测曲谱音频播放进度,返回
  60. const progress = (res: any) => {
  61. console.log('app播放进度',res)
  62. const currentTime = res?.currentTime || res?.content?.currentTime;
  63. if (currentTime) {
  64. if (currentTime < detailData.currentTime) {
  65. state.activeNoteIndex = 0
  66. }
  67. detailData.currentTime = currentTime
  68. }
  69. };
  70. onMounted(async () => {
  71. const id = query.id || '';
  72. state.isSimplePage = true;
  73. await getMusicDetail(id, 'open');
  74. detailData.isLoading = false;
  75. state.isSingleLine = true;
  76. window.addEventListener("message", communicateCb);
  77. });
  78. onUnmounted(() => {
  79. state.isSimplePage = false;
  80. window.removeEventListener("message", communicateCb);
  81. });
  82. /** 渲染完成 */
  83. const handleRendered = async (osmd: any) => {
  84. const svgHeight = document.getElementById('scrollContainer')?.getBoundingClientRect().height;
  85. state.osmd = osmd;
  86. // 没有设置速度使用读取的速度
  87. if (state.originSpeed === 0) {
  88. state.originSpeed = state.speed = (osmd as any).bpm || osmd.Sheet.userStartTempoInBPM || 100;
  89. }
  90. const saveSpeed = (store.get("speeds") || {})[state.examSongId] || state.speed || (osmd as any).bpm || osmd.Sheet.userStartTempoInBPM;
  91. // 加载本地缓存的速度
  92. if (saveSpeed) {
  93. handleSetSpeed(saveSpeed);
  94. }
  95. setCustomGradual();
  96. setCustomNoteRealValue();
  97. state.times = formateTimes(osmd);
  98. console.log("🚀 ~ state.times:", state.times, state);
  99. nextTick(() => {
  100. state.activeMeasureIndex = state.times[0].MeasureNumberXML;
  101. fillWordColor();
  102. })
  103. // 音符添加位置信息bbox
  104. addNoteBBox(state.times);
  105. // 一行谱创建 动画
  106. initSmoothAnimation();
  107. //destroySmoothAnimation();
  108. //smoothAnimationState.isShow.value = false;
  109. api_cloudLoading();
  110. console.log('渲染完成',svgHeight)
  111. window.parent.postMessage(
  112. {
  113. api: "api_musicPage",
  114. height: svgHeight
  115. },
  116. "*"
  117. );
  118. simple_musicPage({
  119. height: svgHeight
  120. })
  121. // state.playState = 'play';
  122. // setStep();
  123. };
  124. /**
  125. * 播放一直触发的事件
  126. */
  127. const handlePlaying = (skipNote?: boolean) => {
  128. //detailData.currentTime += 0.03
  129. const currentTime = detailData.currentTime;
  130. // console.log('👀~播放进度',currentTime)
  131. let item = getNote(currentTime);
  132. if (item) {
  133. gotoNext(item, skipNote);
  134. }
  135. state.activeNoteIndex = item?.i || 0
  136. // 一行谱,需要滚动小节
  137. if (state.isSingleLine) {
  138. moveSmoothAnimationByPlayTime(currentTime)
  139. }
  140. };
  141. /** 在渲染前后计算光标应该走到的音符 */
  142. const setStep = () => {
  143. // console.log('播放状态',state.playState)
  144. if (state.playState !== "play") {
  145. console.log("暂停播放");
  146. return;
  147. }
  148. let startTime = Date.now();
  149. requestAnimationFrame(() => {
  150. const endTime = Date.now();
  151. // 渲染时间大于16.6,就会让页面卡顿, 如果渲染时间大与16.6就下一个渲染帧去计算
  152. if (endTime - startTime < 16.7) {
  153. handlePlaying();
  154. setStep();
  155. } else {
  156. setTimeout(() => {
  157. handlePlaying();
  158. setStep();
  159. }, 16.7);
  160. }
  161. });
  162. };
  163. return () => (
  164. <div class={styles.detail}>
  165. <div id="scrollContainer" class={[styles.container, "hideCursor"]}>
  166. {/* 曲谱渲染 */}
  167. {!detailData.isLoading &&
  168. <MusicScore
  169. onRendered={handleRendered}
  170. musicColor={'#FFFFFF'}
  171. />}
  172. </div>
  173. </div>
  174. );
  175. },
  176. });