index.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import { defineComponent, nextTick, onMounted, reactive } from "vue";
  2. import state, { EnumMusicRenderType } 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 { svg2canvas } from "/src/utils/svg2canvas";
  8. export default defineComponent({
  9. name: "music-list",
  10. setup() {
  11. const query: any = getQuery();
  12. const detailData = reactive({
  13. isLoading: true,
  14. isProductLoading: false,
  15. step: 0,
  16. product: [
  17. {
  18. state: false,
  19. name: "五线谱",
  20. type: EnumMusicRenderType.staff,
  21. base64: "" as any,
  22. },
  23. {
  24. state: false,
  25. name: "首调",
  26. type: EnumMusicRenderType.firstTone,
  27. base64: "" as any,
  28. },
  29. {
  30. state: false,
  31. name: "固定调",
  32. type: EnumMusicRenderType.fixedTone,
  33. base64: "" as any,
  34. },
  35. ],
  36. });
  37. onMounted(() => {
  38. (window as any).appName = "colexiu";
  39. state.xmlUrl = query.xmlUrl;
  40. //课堂乐器,默认简谱
  41. state.musicRenderType = detailData.product[detailData.step].type;
  42. showLoadingToast({ message: "生成中", duration: 0 });
  43. setTimeout(() => {
  44. detailData.isLoading = false;
  45. }, 500);
  46. });
  47. /** 渲染完成 */
  48. const handleRendered = async () => {
  49. try {
  50. console.log(JSON.parse(JSON.stringify(detailData.product)));
  51. } catch (error) {}
  52. detailData.product[detailData.step].state = true;
  53. detailData.product[detailData.step].base64 = await downPng();
  54. detailData.step += 1;
  55. if (detailData.step !== detailData.product.length - 1) {
  56. //课堂乐器,默认简谱
  57. state.musicRenderType = detailData.product[detailData.step].type;
  58. nextTick(() => {
  59. detailData.isLoading = true;
  60. setTimeout(() => {
  61. detailData.isLoading = false;
  62. }, 500);
  63. });
  64. return;
  65. }
  66. closeToast();
  67. console.log(detailData.product);
  68. window.parent?.postMessage(
  69. {
  70. api: "webApi_renderSvg",
  71. product: JSON.stringify(detailData.product),
  72. },
  73. "*"
  74. );
  75. };
  76. const downPng = () => {
  77. return new Promise((resolve) => {
  78. setTimeout(async () => {
  79. try {
  80. const svg: any = document.getElementById("osmdSvgPage1")?.cloneNode(true);
  81. if (!svg) {
  82. resolve("");
  83. return;
  84. }
  85. const cw = svg.width.animVal.value;
  86. const ch = svg.height.animVal.value;
  87. const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
  88. rect.setAttribute("x", "0");
  89. rect.setAttribute("y", "0");
  90. rect.setAttribute("width", `${cw * 2}`);
  91. rect.setAttribute("height", `${ch * 2}`);
  92. rect.setAttribute("fill", "#fff");
  93. svg.prepend(rect);
  94. const _canvas = svg2canvas(svg.outerHTML);
  95. const base64 = _canvas.toDataURL("image/png", 1);
  96. resolve(base64);
  97. } catch (error) {
  98. resolve("");
  99. }
  100. }, 500);
  101. });
  102. };
  103. return () => (
  104. <div class={styles.detail}>
  105. <div id="scrollContainer" class={[styles.container, "hideCursor"]}>
  106. {/* 曲谱渲染 */}
  107. {!detailData.isLoading && <MusicScore showSelection={false} onRendered={handleRendered} />}
  108. </div>
  109. </div>
  110. );
  111. },
  112. });