Browse Source

酷乐秀初始化+播放预备节拍器

liushengqiang 2 years ago
parent
commit
b6944cb734

+ 1 - 1
image2code.js

@@ -4,7 +4,7 @@ const path = require('path')
 // 指法文件夹位置
 // const filesDir = path.join(__dirname, './fingering')
 // const filesDir = path.join(__dirname, './pages/detail')
-const filesDir = path.join(__dirname, './iconss')
+const filesDir = path.join(__dirname, './images')
 console.log("🚀 ~ filesDir:", filesDir, path.join(filesDir, 'index.json'))
 
 // 需要处理的文件后缀

+ 18 - 0
images/accompaniment.svg

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="29px" height="29px" viewBox="0 0 29 29" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>伴奏</title>
+    <defs>
+        <path d="M14.5,5 C14.9198469,5 15.3333326,5.02709975 15.7387868,5.0796372 L15.739461,11.4914597 C15.425484,11.3833985 15.0883542,11.3247036 14.7374468,11.3247036 C13.0452347,11.3247036 11.6734257,12.6896792 11.6734257,14.3734619 C11.6734257,16.0572446 13.0452347,17.4222202 14.7374468,17.4222202 C16.429659,17.4222202 17.801468,16.0572446 17.801468,14.3734619 L17.7942219,14.1621325 L17.7942219,14.1621325 L17.7727995,13.954679 L17.7707276,5.57515703 C21.4060448,6.90159152 24,10.3757181 24,14.4526775 C24,19.6732471 19.7467051,23.9053549 14.5,23.9053549 C9.25329488,23.9053549 5,19.6732471 5,14.4526775 C5,9.23210785 9.25329488,5 14.5,5 Z M13.6485145,7.42213135 L13.5380921,7.43232999 C11.1412583,7.78453026 9.07005055,9.32180515 8.06867876,11.570923 C6.47021778,15.1611251 8.09835858,19.3711273 11.7018864,20.9755213 C15.3054142,22.5799152 19.5234944,20.9728183 21.1219554,17.3826162 C22.085337,15.2188257 21.8982132,12.7571482 20.6799325,10.7712115 C20.3864474,10.2927972 19.7606992,10.1428825 19.2822849,10.4363676 C18.8038706,10.7298528 18.6539559,11.355601 18.947441,11.8340153 C19.8194764,13.2555325 19.9529316,15.011182 19.2651692,16.5559217 C18.1242057,19.1185678 15.108704,20.2674799 12.5285809,19.1187351 C9.9484578,17.9699903 8.78450142,14.9602635 9.92546495,12.3976175 C10.6403077,10.7920543 12.1179292,9.69534616 13.8335833,9.44324113 C14.3888811,9.36164347 14.7728909,8.8453377 14.6912933,8.29003993 C14.6096956,7.73474215 14.0933898,7.35073233 13.5380921,7.43232999 Z" id="path-1"></path>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="主界面" transform="translate(-515.000000, -13.000000)">
+            <g id="伴奏" transform="translate(515.000000, 13.000000)">
+                <rect id="矩形备份-27" fill="#2DC7AA" x="0" y="0" width="29" height="29" rx="14.5"></rect>
+                <mask id="mask-2" fill="white">
+                    <use xlink:href="#path-1"></use>
+                </mask>
+                <use id="形状结合" fill="#FFFFFF" xlink:href="#path-1"></use>
+            </g>
+        </g>
+    </g>
+</svg>

File diff suppressed because it is too large
+ 1 - 0
images/index.json


+ 67 - 0
images/model-1.svg

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="138px" height="50px" viewBox="0 0 138 50" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>切片</title>
+    <defs>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
+            <stop stop-color="#46DABE" offset="0%"></stop>
+            <stop stop-color="#2DC7AA" offset="100%"></stop>
+        </linearGradient>
+        <rect id="path-2" x="0" y="0" width="138" height="50" rx="25"></rect>
+        <filter x="-1.8%" y="-5.0%" width="103.6%" height="110.0%" filterUnits="objectBoundingBox" id="filter-3">
+            <feGaussianBlur stdDeviation="1.5" in="SourceAlpha" result="shadowBlurInner1"></feGaussianBlur>
+            <feOffset dx="0" dy="-2" in="shadowBlurInner1" result="shadowOffsetInner1"></feOffset>
+            <feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1"></feComposite>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0.704144022   0 0 0 0 0.569800754  0 0 0 1 0" type="matrix" in="shadowInnerInner1"></feColorMatrix>
+        </filter>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-4">
+            <stop stop-color="#FFFFFF" stop-opacity="0.5" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" stop-opacity="0" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-5">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" stop-opacity="0" offset="100%"></stop>
+        </linearGradient>
+        <text id="text-6" font-family="STYuanti-SC-Bold, Yuanti SC" font-size="15" font-weight="bold" fill="#FFFFFF">
+            <tspan x="0" y="16">练习模式</tspan>
+        </text>
+        <filter x="-3.3%" y="-4.8%" width="106.7%" height="119.0%" filterUnits="objectBoundingBox" id="filter-7">
+            <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0.318367388   0 0 0 0 0.848505435   0 0 0 0 0.748674244  0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
+        </filter>
+        <text id="text-8" font-family="STYuanti-SC-Light, Yuanti SC" font-size="10" font-weight="300" fill="#FFFFFF">
+            <tspan x="0" y="30">原音指法跟播</tspan>
+        </text>
+        <filter x="-3.3%" y="-7.1%" width="106.7%" height="128.6%" filterUnits="objectBoundingBox" id="filter-9">
+            <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0.318367388   0 0 0 0 0.848505435   0 0 0 0 0.748674244  0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
+        </filter>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="主界面(10.18)" transform="translate(-154.000000, -290.000000)">
+            <g id="示范模式" transform="translate(154.000000, 290.000000)">
+                <g id="矩形">
+                    <use fill="url(#linearGradient-1)" fill-rule="evenodd" xlink:href="#path-2"></use>
+                    <use fill="black" fill-opacity="1" filter="url(#filter-3)" xlink:href="#path-2"></use>
+                </g>
+                <g id="编组-11" transform="translate(14.000000, 10.000000)">
+                    <circle id="椭圆形" fill="url(#linearGradient-4)" cx="15" cy="15" r="15"></circle>
+                    <path d="M24,14.5 C24,9.25329488 19.7467051,5 14.5,5 C9.25329488,5 5,9.25329488 5,14.5 C5,19.7467051 9.25329488,24 14.5,24" id="路径" stroke="url(#linearGradient-5)" stroke-width="2" stroke-linecap="round" transform="translate(14.500000, 14.500000) rotate(-270.000000) translate(-14.500000, -14.500000) "></path>
+                    <path d="M17.7929013,12.6979322 L20.464394,17.2394698 C20.8844232,17.9535195 20.6460726,18.8728721 19.9320229,19.2929013 C19.7015079,19.4284984 19.4389319,19.5 19.1714927,19.5 L13.8285073,19.5 C13.0000802,19.5 12.3285073,18.8284271 12.3285073,18 C12.3285073,17.7325608 12.400009,17.4699848 12.535606,17.2394698 L15.2070987,12.6979322 C15.6271279,11.9838826 16.5464805,11.7455319 17.2605302,12.1655611 C17.4803607,12.2948732 17.6635893,12.4781017 17.7929013,12.6979322 Z" id="三角形" fill="#FFFFFF" transform="translate(16.500000, 15.000000) rotate(-270.000000) translate(-16.500000, -15.000000) "></path>
+                    <path d="M13.8574929,22.5124882 L15.5913025,25.4021709 C15.8754507,25.8757512 15.7218856,26.4900114 15.2483054,26.7741596 C15.09289,26.8674088 14.9150535,26.9166667 14.7338096,26.9166667 L11.2661904,26.9166667 C10.7139056,26.9166667 10.2661904,26.4689514 10.2661904,25.9166667 C10.2661904,25.7354227 10.3154482,25.5575863 10.4086975,25.4021709 L12.1425071,22.5124882 C12.4266552,22.038908 13.0409155,21.8853429 13.5144958,22.1694911 C13.6552454,22.2539408 13.7730432,22.3717386 13.8574929,22.5124882 Z" id="三角形备份" fill="#FFFFFF" transform="translate(13.000000, 24.000000) rotate(-90.000000) translate(-13.000000, -24.000000) "></path>
+                </g>
+                <g id="编组" transform="translate(56.000000, 6.000000)" fill="#FFFFFF" fill-opacity="1">
+                    <g id="练习模式">
+                        <use filter="url(#filter-7)" xlink:href="#text-6"></use>
+                        <use xlink:href="#text-6"></use>
+                    </g>
+                    <g id="原音指法跟播">
+                        <use filter="url(#filter-9)" xlink:href="#text-8"></use>
+                        <use xlink:href="#text-8"></use>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

File diff suppressed because it is too large
+ 50 - 0
images/model-2.svg


+ 62 - 0
images/model-3.svg

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="138px" height="50px" viewBox="0 0 138 50" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>切片</title>
+    <defs>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
+            <stop stop-color="#A259FF" offset="0%"></stop>
+            <stop stop-color="#933FFE" offset="100%"></stop>
+        </linearGradient>
+        <rect id="path-2" x="0" y="0" width="138" height="50" rx="25"></rect>
+        <filter x="-1.8%" y="-5.0%" width="103.6%" height="110.0%" filterUnits="objectBoundingBox" id="filter-3">
+            <feGaussianBlur stdDeviation="1.5" in="SourceAlpha" result="shadowBlurInner1"></feGaussianBlur>
+            <feOffset dx="0" dy="-2" in="shadowBlurInner1" result="shadowOffsetInner1"></feOffset>
+            <feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1"></feComposite>
+            <feColorMatrix values="0 0 0 0 0.515291285   0 0 0 0 0.13675686   0 0 0 0 1  0 0 0 1 0" type="matrix" in="shadowInnerInner1"></feColorMatrix>
+        </filter>
+        <linearGradient x1="100%" y1="50%" x2="0%" y2="50%" id="linearGradient-4">
+            <stop stop-color="#FFFFFF" stop-opacity="0.5" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" stop-opacity="0" offset="100%"></stop>
+        </linearGradient>
+        <text id="text-5" font-family="STYuanti-SC-Light, Yuanti SC" font-size="10" font-weight="300" fill="#FFFFFF">
+            <tspan x="2.48689958e-14" y="30">跟音实时纠错</tspan>
+        </text>
+        <filter x="-3.3%" y="-7.1%" width="106.7%" height="128.6%" filterUnits="objectBoundingBox" id="filter-6">
+            <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0.675712051   0 0 0 0 0.424161585   0 0 0 0 1  0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
+        </filter>
+        <text id="text-7" font-family="STYuanti-SC-Bold, Yuanti SC" font-size="15" font-weight="bold" fill="#FFFFFF">
+            <tspan x="2.48689958e-14" y="16">跟练模式</tspan>
+        </text>
+        <filter x="-3.3%" y="-4.8%" width="106.7%" height="119.0%" filterUnits="objectBoundingBox" id="filter-8">
+            <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0.675712051   0 0 0 0 0.424161585   0 0 0 0 1  0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
+        </filter>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="主界面(10.18)" transform="translate(-550.000000, -290.000000)">
+            <g id="跟练模式" transform="translate(550.000000, 290.000000)">
+                <g id="矩形备份-4">
+                    <use fill="url(#linearGradient-1)" fill-rule="evenodd" xlink:href="#path-2"></use>
+                    <use fill="black" fill-opacity="1" filter="url(#filter-3)" xlink:href="#path-2"></use>
+                </g>
+                <g id="编组-9" transform="translate(15.000000, 14.000000)">
+                    <rect id="矩形备份-5" fill="url(#linearGradient-4)" x="0" y="1" width="25" height="20"></rect>
+                    <rect id="矩形" fill="#FFFFFF" x="23" y="0" width="3" height="22" rx="1.5"></rect>
+                    <path d="M15.337,3.36984407 C16.3850641,3.45356076 17.0135838,4.94285402 18.7395136,4.94414392 C19.191266,4.94448154 19.3604869,5.36096605 19.1917441,5.54466333 C18.8811643,5.88276768 18.0829942,6.43880357 17.3160371,6.65970461 C16.2873269,6.95599651 15.6529504,6.87779633 15.4386654,6.89730024 L16.0108711,12.7441637 C16.0771854,13.0382245 16.1122361,13.3435336 16.1124855,13.6566725 C16.1143681,16.0199852 14.1332679,17.9343469 11.6875744,17.9325424 C9.24188082,17.9306913 7.25772835,16.0133661 7.25582193,13.6500534 C7.2539632,11.2867407 9.23506342,9.37237896 11.680757,9.37420678 C12.4163451,9.37475653 13.1101814,9.54858569 13.7208897,9.85571169 C13.4786646,6.87677885 13.3574832,5.30079449 13.3573453,5.1277586 C13.356398,3.93855616 14.1664214,3.27634123 15.337,3.36984407 Z" id="路径备份-5" fill="#FFFFFF" transform="translate(13.255823, 10.646827) rotate(-19.000000) translate(-13.255823, -10.646827) "></path>
+                </g>
+                <g id="编组" transform="translate(56.000000, 6.000000)" fill="#FFFFFF" fill-opacity="1">
+                    <g id="跟音实时纠错">
+                        <use filter="url(#filter-6)" xlink:href="#text-5"></use>
+                        <use xlink:href="#text-5"></use>
+                    </g>
+                    <g id="跟练模式">
+                        <use filter="url(#filter-8)" xlink:href="#text-7"></use>
+                        <use xlink:href="#text-7"></use>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 25 - 0
images/music.svg

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="29px" height="29px" viewBox="0 0 29 29" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>编组 6</title>
+    <defs>
+        <linearGradient x1="41.2368343%" y1="0%" x2="97.1381951%" y2="78.9366254%" id="linearGradient-1">
+            <stop stop-color="#FFC660" offset="0%"></stop>
+            <stop stop-color="#FFBD4B" offset="100%"></stop>
+        </linearGradient>
+        <path d="M9.37679833,1.81534677 L9.37419306,3.04816586 C9.37346127,3.33467339 9.18383076,3.5868294 8.90940839,3.66620062 L5.85992188,4.0208176 L5.85188205,7.82778866 C5.84934408,9.03897664 4.89162503,10.0343315 3.68635578,10.0784143 L3.60963888,10.0798661 C2.64577957,10.0818791 1.79156753,9.46371158 1.4895916,8.54564682 C1.18761568,7.62758207 1.50574958,6.61596919 2.27916009,6.03495037 C3.05257061,5.45393155 4.10742189,5.43409966 4.89716884,5.9857301 L4.90515888,2.05098317 L4.92593563,2.0509391 C4.98390648,1.83154189 5.15266508,1.65863389 5.36991876,1.59603942 L8.56333252,1.19938128 C8.90300857,1.10135042 9.25633505,1.29808342 9.35255706,1.63882333 C9.36877585,1.69621115 9.37693434,1.75562497 9.37679833,1.81534677 Z" id="path-2"></path>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="主界面播放中" transform="translate(-515.000000, -13.000000)">
+            <g id="编组-6" transform="translate(515.000000, 13.000000)">
+                <rect id="矩形备份-40" fill="#2DC7AA" x="0" y="0" width="29" height="29" rx="14.5"></rect>
+                <g id="原声" transform="translate(3.396546, 5.242923)" fill-rule="nonzero">
+                    <path d="M11.6943607,4.24183306 C11.3291428,4.24183306 10.9752986,4.38175852 10.7040597,4.66163723 C10.4319278,4.94555471 10.2994641,5.31335252 10.2974559,5.68515601 L10.3059192,7.44794878 L10.3162589,12.2210844 C9.87412006,11.8946809 9.33560726,11.7009401 8.7539964,11.703952 C7.25680722,11.6985079 6.0505457,12.9437999 6.04950867,14.4878049 C6.05688754,16.0248766 7.27348324,17.2775431 8.76418639,17.281423 C10.2553241,17.2854168 11.4616178,16.0401248 11.4605456,14.495146 L11.4379862,7.45282164 L18.8956957,7.47795057 L18.903767,12.2510171 C18.4600339,11.9237701 17.9258022,11.7310559 17.3395869,11.724006 C15.8475723,11.7240347 14.6402265,12.9742541 14.6454327,14.5108044 C14.6455314,16.0597895 15.8604372,17.311975 17.3543339,17.311975 C18.8459774,17.3113798 20.056664,16.0666783 20.0495087,14.5207016 L20.0343921,7.47546658 L20.0309119,5.71905145 C20.0307636,5.34672653 19.8899744,4.97734178 19.612914,4.69009969 C19.3403622,4.41335562 18.9795651,4.27168215 18.6262951,4.26924317 L11.6943607,4.24183306 Z" id="路径备份-4" fill="#FFFFFF" transform="translate(13.049509, 10.776904) rotate(8.000000) translate(-13.049509, -10.776904) "></path>
+                    <g id="路径备份-6" transform="translate(5.376798, 5.627027) rotate(-22.000000) translate(-5.376798, -5.627027) ">
+                        <use fill="url(#linearGradient-1)" xlink:href="#path-2"></use>
+                        <use fill="#FFFFFF" xlink:href="#path-2"></use>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 19 - 0
images/pause.svg

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>播放</title>
+    <defs>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="99.3846973%" id="linearGradient-1">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" stop-opacity="0.589416077" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="主界面播放中" transform="translate(-737.000000, -301.000000)">
+            <g id="播放" transform="translate(737.000000, 301.000000)">
+                <rect id="矩形" fill="#2DC7AA" x="0" y="0" width="40" height="40" rx="20"></rect>
+                <path d="M14.5,11 C15.8807119,11 17,12.1192881 17,13.5 L17,26.5 C17,27.8807119 15.8807119,29 14.5,29 C13.1192881,29 12,27.8807119 12,26.5 L12,13.5 C12,12.1192881 13.1192881,11 14.5,11 Z" id="矩形" fill="url(#linearGradient-1)"></path>
+                <path d="M26.0066313,11 C27.3873432,11 28.5066313,12.1192881 28.5066313,13.5 L28.5066313,26.5 C28.5066313,27.8807119 27.3873432,29 26.0066313,29 C24.6259194,29 23.5066313,27.8807119 23.5066313,26.5 L23.5066313,13.5 C23.5066313,12.1192881 24.6259194,11 26.0066313,11 Z" id="矩形备份-30" fill="url(#linearGradient-1)"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 30 - 0
images/play.svg

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>播放</title>
+    <defs>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="99.3846973%" id="linearGradient-1">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" stop-opacity="0.589416077" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-2">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" stop-opacity="0.667663147" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="4.46840985%" x2="50%" y2="104.686646%" id="linearGradient-3">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" stop-opacity="0.696550276" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="主界面" transform="translate(-737.000000, -301.000000)">
+            <g id="播放" transform="translate(737.000000, 301.000000)">
+                <rect id="矩形" fill="#2DC7AA" x="0" y="0" width="40" height="40" rx="20"></rect>
+                <g id="编组-2" transform="translate(11.204229, 6.895148)">
+                    <path d="M3.14942999,1.45267811 C4.53014187,1.45267811 5.64942999,2.57196623 5.64942999,3.95267811 L5.64942999,22.3439825 C5.64942999,23.7246943 4.53014187,24.8439825 3.14942999,24.8439825 C1.76871812,24.8439825 0.649429993,23.7246943 0.649429993,22.3439825 L0.649429993,3.95267811 C0.649429993,2.57196623 1.76871812,1.45267811 3.14942999,1.45267811 Z" id="矩形" fill="url(#linearGradient-1)"></path>
+                    <path d="M10.7709354,8.19196933 C12.1516472,8.19196933 13.2709354,9.31125746 13.2709354,10.6919693 L13.2709354,27.4310998 C13.2709354,28.8118116 12.1516472,29.9310998 10.7709354,29.9310998 C9.39022348,29.9310998 8.27093535,28.8118116 8.27093535,27.4310998 L8.27093535,10.6919693 C8.27093535,9.31125746 9.39022348,8.19196933 10.7709354,8.19196933 Z" id="矩形备份" fill="url(#linearGradient-2)" transform="translate(10.770935, 19.061535) rotate(62.000000) translate(-10.770935, -19.061535) "></path>
+                    <path d="M11.0789734,-2.50463277 C12.4596853,-2.50463277 13.5789734,-1.38534465 13.5789734,-0.00463277154 L13.5789734,17.6040632 C13.5789734,18.9847751 12.4596853,20.1040632 11.0789734,20.1040632 C9.69826153,20.1040632 8.57897341,18.9847751 8.57897341,17.6040632 L8.57897341,-0.00463277154 C8.57897341,-1.38534465 9.69826153,-2.50463277 11.0789734,-2.50463277 Z" id="矩形备份-28" fill="url(#linearGradient-3)" transform="translate(11.078973, 8.799715) rotate(127.000000) translate(-11.078973, -8.799715) "></path>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 26 - 5
src/page-colexiu/detail/index.module.less

@@ -14,23 +14,44 @@
     width: 100vw;
     height: 100vh;
     overflow: hidden;
-    background-color: var(--van-primary-color);
     --header-height: 62px;
+    background: var(--container-background);
     &.opencamera {
         opacity: .7;
     }
 
     .headHeight {
+        position: fixed;
+        left: 0;
+        top: 0;
+        width: 100%;
         height: var(--header-height);
+        transition: margin .3s;
+        z-index: 10;
+        &.headHide{
+            margin-top: calc(0Px - var(--header-height));
+        }
     }
 
     .container {
         position: relative;
-        height: calc(100vh - 18px - var(--header-height));
-        margin: 0 18px;
-        background: var(--container-background);
+        height: 100vh;
+        margin: 0 10px;
         border-radius: 10px;
-        overflow: hidden;
+        padding-top: var(--header-height);
+        overflow-x: hidden;
+        overflow-y: auto;
+        &::-webkit-scrollbar {
+            width: 0;
+            display: none;
+        }
+        :global{
+            #musicAndSelection{
+                overflow: auto;
+                height: initial;
+                max-height: initial;
+            }
+        }
     }
 }
 

+ 31 - 8
src/page-colexiu/detail/index.tsx

@@ -19,6 +19,7 @@ import MeasureSpeed from "/src/view/plugins/measure-speed";
 import { mappingVoicePart, subjectFingering } from "/src/view/fingering/fingering-config";
 import Fingering from "/src/view/fingering";
 import store from "store";
+import Tick, { handleInitTick } from "/src/view/tick";
 
 export default defineComponent({
 	name: "music-list",
@@ -32,6 +33,7 @@ export default defineComponent({
 		const detailData = reactive({
 			isLoading: true,
 			paddingLeft: "",
+			headerHide: false,
 		});
 		const getAPPData = async () => {
 			const screenData = await isSpecialShapedScreen();
@@ -70,7 +72,8 @@ export default defineComponent({
 		};
 
 		const setState = (data: any, index: number) => {
-			state.appName = 'COLEXIU'
+			state.scrollContainer = "scrollContainer";
+			state.appName = "COLEXIU";
 			state.detailId = data.id;
 			state.xmlUrl = data.xmlFileUrl;
 			state.partIndex = index;
@@ -89,7 +92,7 @@ export default defineComponent({
 				}
 			}
 			state.isOpenMetronome = data.mp3Type === "MP3_METRONOME" ? true : false;
-			state.needTick = data.isOpenMetronome;
+			state.needTick = true; // data.isOpenMetronome;
 			state.isShowFingering = data.showFingering ? true : false;
 			state.music = data.audioFileUrl;
 			state.accompany = data.metronomeUrl || data.metronomeUrl;
@@ -126,15 +129,20 @@ export default defineComponent({
 		const handleRendered = (osmd: any) => {
 			state.musicRendered = true;
 			state.osmd = osmd;
-			const saveSpeed = (store.get('speeds') || {})[state.examSongId]
-			const bpm = (osmd as any).bpm || osmd.Sheet.userStartTempoInBPM
-			state.originSpeed = state.speed = saveSpeed || bpm || 100
+			const saveSpeed = (store.get("speeds") || {})[state.examSongId];
+			const bpm = (osmd as any).bpm || osmd.Sheet.userStartTempoInBPM;
+			state.originSpeed = state.speed = saveSpeed || bpm || 100;
 			state.times = formateTimes(osmd);
 			console.log("🚀 ~ state.times:", state.times);
 			try {
 				metronomeData.metro = new Metronome();
 				metronomeData.metro.init(state.times);
 			} catch (error) {}
+			// 设置节拍器
+			if (state.needTick) {
+				const beatLengthInMilliseconds = osmd?.Sheet?.SheetPlaybackSetting?.beatLengthInMilliseconds || (60 / bpm * 1000);
+				handleInitTick(beatLengthInMilliseconds, osmd?.Sheet?.SheetPlaybackSetting?.Rhythm?.Numerator || 4);
+			}
 		};
 		/** 指法配置 */
 		const fingerConfig = computed<any>(() => {
@@ -184,19 +192,32 @@ export default defineComponent({
 				}
 			}
 		);
+		// 监听播放状态
+		watch(() => state.playState, () => {
+			detailData.headerHide = state.playState === 'play' ? true : false
+		})
 		return () => (
-			<div class={[styles.detail, state.setting.camera && styles.opencamera]} style={{ paddingLeft: detailData.paddingLeft }}>
+			<div
+				class={[styles.detail, state.setting.camera && styles.opencamera, state.setting.eyeProtection && "eyeProtection"]}
+				style={{ paddingLeft: detailData.paddingLeft }}
+			>
 				{!state.musicRendered && (
 					<div class={styles.skeleton}>
 						<Skeleton class={styles.skeleton} row={8} />
 					</div>
 				)}
-				<div class={styles.headHeight}>
+				<div class={[styles.headHeight, detailData.headerHide && styles.headHide]}>
 					<Transition name="van-slide-down">{state.musicRendered && <HeaderTop />}</Transition>
 				</div>
 				<div
+					id="scrollContainer"
 					style={{ ...fingerConfig.value.container }}
-					class={[styles.container, state.setting.eyeProtection && "eyeProtection", !state.setting.displayCursor && "hideCursor"]}
+					class={[styles.container, !state.setting.displayCursor && "hideCursor"]}
+					onClick={(e: Event) => {
+						if (state.playState === 'play') {
+							detailData.headerHide = !detailData.headerHide
+						}
+					}}
 				>
 					{/* 曲谱渲染 */}
 					{!detailData.isLoading && <MusicScore onRendered={handleRendered} />}
@@ -225,6 +246,8 @@ export default defineComponent({
 						</>
 					)}
 				</div>
+				{/* 节拍器 */}
+				{state.needTick && <Tick />}
 			</div>
 		);
 	},

File diff suppressed because it is too large
+ 0 - 2
src/page-colexiu/header-top/image/headerTop.json


+ 5 - 8
src/page-colexiu/header-top/image/icon-back.svg

@@ -1,11 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-    <g id="云教练2版" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
-        <g id="画板" transform="translate(-27.000000, -123.000000)">
-            <g id="返回箭头备份" transform="translate(43.000000, 139.000000) scale(-1, 1) translate(-43.000000, -139.000000) translate(27.000000, 123.000000)">
-                <circle id="椭圆形" fill="#FFFFFF" cx="16" cy="16" r="16"></circle>
-                <path d="M17.3783645,23.2991468 L23.9125501,16.7649612 C24.157653,16.5199302 24.2953565,16.1875536 24.2953565,15.8409766 C24.2953565,15.4943995 24.157653,15.162023 23.9125501,14.916992 L17.3783645,8.38280634 C17.1333334,8.13770343 16.8009569,8 16.4543799,8 C16.1078028,8 15.7754263,8.13770343 15.5303953,8.38280634 C15.0201983,8.89302883 15.0201983,9.72023586 15.5303953,10.2304583 L19.8337592,14.5344566 L7.30683717,14.5344566 C6.96021662,14.5343725 6.62776858,14.6720297 6.38267084,14.9171274 C6.13757309,15.1622252 6,15.4946732 6,15.8412938 C6,16.1879143 6.13757308,16.5203624 6.38267083,16.7654601 C6.62776858,17.0105579 6.96021662,17.1482151 7.30683717,17.1481309 L19.8337592,17.1481309 L15.5303953,21.4514948 C15.2002874,21.7816027 15.0713656,22.2627455 15.1921934,22.7136812 C15.3130213,23.164617 15.6652423,23.516838 16.116178,23.6376658 C16.5671138,23.7584937 17.0482566,23.6295719 17.3783645,23.299464 L17.3783645,23.2991468 Z" id="路径" fill="#2DC7AA" fill-rule="nonzero"></path>
-            </g>
+<svg width="15px" height="24px" viewBox="0 0 15 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g transform="translate(-40.000000, -22.000000)" fill="#494949" fill-rule="nonzero" id="形状" stroke="#494949">
+            <path d="M42.2681508,32.7499394 C42.5890877,32.7499394 42.9114702,32.8699082 43.168798,33.0950183 L53.620931,42.6520856 C53.8607785,42.8704624 53.997204,43.1690827 53.9999596,43.4816468 C54.0026326,43.7942108 53.8714111,44.0948519 53.6353876,44.3168215 C53.138464,44.7783404 52.3366638,44.7837362 51.8326476,44.3289532 L41.379069,34.7718859 C41.1392215,34.5535091 41.002796,34.2548888 41.0000404,33.9423247 C40.9973673,33.6297606 41.1285889,33.3291196 41.3646123,33.1071499 C41.5948722,32.8710256 41.9246144,32.7409471 42.2667051,32.7512873 L42.2681508,32.7499394 Z M52.7106158,23 C53.0356188,23 53.3591643,23.117702 53.6185837,23.3424057 C53.8599334,23.5590403 53.9971822,23.8550613 53.9999596,24.1648752 C54.0026536,24.474689 53.8706502,24.7727125 53.6331578,24.9929083 L43.1980856,34.5695682 C42.6976948,35.027014 41.8904764,35.0329595 41.3821498,34.5829434 C41.1403528,34.3662582 41.0028184,34.0699512 41.0000404,33.7598084 C40.9973456,33.4496656 41.1296337,33.1513535 41.3675757,32.9311033 L51.8026479,23.3544434 C52.0474932,23.117702 52.3856129,23 52.7106158,23 Z"></path>
         </g>
     </g>
-</svg>
+</svg>

File diff suppressed because it is too large
+ 7 - 8
src/page-colexiu/header-top/image/menu.svg


+ 15 - 0
src/page-colexiu/header-top/image/modeType.svg

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="29px" height="29px" viewBox="0 0 29 29" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>切片</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="曲谱评测(按钮合集)" transform="translate(-346.000000, -218.000000)">
+            <g id="示范" transform="translate(346.000000, 218.000000)">
+                <rect id="矩形备份-37" fill="#2DC7AA" x="0" y="0" width="29" height="29" rx="14.5"></rect>
+                <path d="M11,8 C12.6568542,8 14,9.34314575 14,11 L14,13 C14,13.5522847 13.5522847,14 13,14 L11,14 C9.34314575,14 8,12.6568542 8,11 C8,9.34314575 9.34314575,8 11,8 Z" id="矩形" fill="#FFFFFF"></path>
+                <path d="M11,15 L13,15 C13.5522847,15 14,15.4477153 14,16 L14,18 C14,19.6568542 12.6568542,21 11,21 C9.34314575,21 8,19.6568542 8,18 C8,16.3431458 9.34314575,15 11,15 Z" id="矩形备份-2" fill="#FFFFFF"></path>
+                <rect id="矩形备份" fill-opacity="0.8" fill="#FFFFFF" x="15" y="8" width="6" height="6" rx="3"></rect>
+                <path d="M16,15 L18,15 C19.6568542,15 21,16.3431458 21,18 C21,19.6568542 19.6568542,21 18,21 C16.3431458,21 15,19.6568542 15,18 L15,16 C15,15.4477153 15.4477153,15 16,15 Z" id="矩形备份-3" fill="#FFFFFF"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 20 - 10
src/page-colexiu/header-top/image/replay.svg

@@ -1,15 +1,25 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<svg width="34px" height="34px" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-    <title>编组 5备份 4</title>
-    <g id="云教练2版" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
-        <g id="画板" transform="translate(-499.000000, -55.000000)">
-            <g id="编组-5备份-4" transform="translate(501.000000, 57.000000)">
-                <rect id="矩形" stroke="#8EE1DC" stroke-width="2" fill="#FFFFFF" x="-1" y="-1" width="32" height="32" rx="12"></rect>
-                <g id="编组" transform="translate(15.000000, 15.500000) scale(-1, 1) translate(-15.000000, -15.500000) translate(4.000000, 5.000000)" fill="#01C1B5" fill-rule="nonzero">
-                    <path d="M21.8359743,5.91618045 C21.4133965,7.0257019 21.0615062,8.16089287 20.7824176,9.31493233 C20.5279569,10.3734135 19.9595125,10.6413835 19.1023816,10.1813684 C19.1023816,10.1813684 16.8062829,8.88915789 15.8866529,8.47231579 C14.8132553,7.98401503 14.9714872,7.47437594 16.3613486,6.9433985 C16.7720572,6.78708271 17.1663969,6.59057144 17.5726412,6.4238346 C16.1878095,3.53041761 13.2777299,1.67769054 10.0712582,1.64801504 C5.30782736,1.72874517 1.51067257,5.65548936 1.58774614,10.4210526 C1.5098371,15.1866217 5.30633371,19.1140403 10.0697701,19.1955789 C12.4640261,19.1829371 14.7366908,18.1386081 16.3062899,16.3297895 C16.5067122,16.1698604 16.7415656,16.0587535 16.9922922,16.0052481 C17.3774369,16.0098332 17.6998373,16.2986565 17.7467459,16.6811278 C17.7563723,16.870475 17.7141837,17.0588621 17.6247238,17.226 C17.5872265,17.2811669 17.5427057,17.331212 17.4922852,17.3748722 C15.6413244,19.5566109 12.9315942,20.8226441 10.0712582,20.8421053 C4.41465343,20.7450836 -0.0930331504,16.0801605 0.0014588411,10.4210526 C0.0139187466,9.29275203 0.205800339,8.17362578 0.569903248,7.10566917 C0.580968335,7.01624856 0.606605274,6.92924621 0.645795047,6.8481203 C2.01644926,2.79485654 5.79595676,0.0492687634 10.0727463,0 C13.931717,0.0337531718 17.4260937,2.28823581 19.048811,5.79112781 C19.5205306,5.58270676 20.0041547,5.40406014 20.4714101,5.18075188 C21.8166293,4.53861654 22.2739642,4.78375939 21.8434147,5.91618045 L21.8359743,5.91618045 Z" id="路径"></path>
-                    <path d="M8.18320392,13.7071392 C7.50450737,14.1305274 6.94736842,13.8126149 6.94736842,13.0014923 L6.94736842,7.84061301 C6.94736842,7.02949037 7.50306026,6.71157784 8.18320392,7.13496603 L12.2264409,9.65152602 C12.5343515,9.77570179 12.7368421,10.0807 12.7368421,10.4203098 C12.7368421,10.7599196 12.5343515,11.0649179 12.2264409,11.1890937 L8.18320392,13.7071392 Z" id="路径" transform="translate(9.842105, 10.421053) scale(-1, 1) translate(-9.842105, -10.421053) "></path>
+<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>暂停备份</title>
+    <defs>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="99.3846973%" id="linearGradient-1">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" stop-opacity="0.589416077" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="99.3846973%" id="linearGradient-2">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#FFFFFF" stop-opacity="0.589416077" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="主界面暂停" transform="translate(-677.000000, -301.000000)">
+            <g id="暂停备份" transform="translate(677.000000, 301.000000)">
+                <rect id="矩形" fill="#2DC7AA" x="0" y="0" width="40" height="40" rx="20"></rect>
+                <g id="编组" transform="translate(19.522776, 19.799926) scale(-1, 1) translate(-19.522776, -19.799926) translate(5.000000, 6.000000)">
+                    <path d="M13.3725568,0 L13.3563443,0 C7.68145471,0.0653974039 2.6664899,3.70847155 0.847834102,9.08655422 L0.817617962,9.15122482 C0.797302775,9.20165727 0.777069364,9.26566714 0.759461507,9.33689435 L0.732063087,9.4749694 L0.753800649,9.40595609 C0.272209238,10.8185203 0.0184121264,12.2987613 0.00193173024,13.7911355 C-0.123254569,21.2877541 5.85181356,27.4712437 13.3499838,27.5998518 L13.7189868,27.5922013 C17.2787984,27.468538 20.6206322,25.9074407 22.9897078,23.2690016 L23.2070631,23.0189694 L23.1449335,23.0794585 C23.2603529,22.9795146 23.362263,22.8649591 23.4480926,22.7386843 C23.6720399,22.329715 23.7570443,21.9501401 23.7376485,21.5686354 C23.6254619,20.6372478 22.888075,19.9766574 22.0070416,19.9661689 L21.8305569,19.9837288 C21.3964214,20.0763739 20.9897811,20.2687516 20.64277,20.5456526 L20.5375202,20.6466519 C18.7304559,22.7291273 16.1140168,23.9314266 13.357623,23.9459806 C7.96780108,23.8535225 3.63958992,19.4689892 3.57989406,14.0920329 L3.58062942,13.8130463 C3.49162395,8.28356315 7.87660023,3.74893628 13.3772597,3.65571168 L13.6826276,3.66341095 C16.9313146,3.79699016 19.8952317,5.57049175 21.5651633,8.35089652 L21.6090631,8.4259694 L21.1341843,8.63175621 L20.925866,8.71400596 C18.6892851,9.56846024 18.1787287,11.0457946 20.1238869,12.0193514 L20.5442371,12.2181679 L21.0321057,12.4617975 L21.6313166,12.7737254 L22.2220542,13.0890242 C22.5238873,13.2515877 22.8360126,13.4216673 23.1493276,13.5939227 L24.2374418,14.1981448 C25.8107445,15.0427057 27.0707432,14.4070096 27.5034432,12.6071061 L27.6808279,11.9061013 C27.9271949,10.9739797 28.2129083,10.0522959 28.537129,9.14382584 L28.5970631,8.9799694 L28.7969478,8.46456175 C29.623868,6.28961617 28.2971865,5.51302702 26.159053,6.46427584 L25.6914434,6.67968867 L24.9420631,6.9949694 L24.8465083,6.8181108 C22.5404703,2.66770793 18.1686454,0.041949839 13.3725568,0 Z" id="路径" fill="url(#linearGradient-1)"></path>
+                    <path d="M12.5618308,10.560238 L16.242904,16.2863518 C16.6908822,16.9832069 16.4891277,17.9112777 15.7922727,18.3592559 C15.5503267,18.5147926 15.2687637,18.5974882 14.9811363,18.5974882 L7.61898991,18.5974882 C6.79056278,18.5974882 6.11898991,17.9259153 6.11898991,17.0974882 C6.11898991,16.8098608 6.20168548,16.5282978 6.35722219,16.2863518 L10.0382954,10.560238 C10.4862736,9.86338291 11.4143444,9.66162839 12.1111995,10.1096066 C12.2919535,10.2258056 12.4456318,10.379484 12.5618308,10.560238 Z" id="三角形" fill="url(#linearGradient-2)" transform="translate(11.300063, 13.597488) rotate(-90.000000) translate(-11.300063, -13.597488) "></path>
                 </g>
             </g>
         </g>
     </g>
-</svg>
+</svg>

File diff suppressed because it is too large
+ 10 - 9
src/page-colexiu/header-top/image/section0.svg


File diff suppressed because it is too large
+ 10 - 9
src/page-colexiu/header-top/image/section1.svg


File diff suppressed because it is too large
+ 10 - 9
src/page-colexiu/header-top/image/section2.svg


+ 34 - 14
src/page-colexiu/header-top/image/speed.svg

@@ -1,21 +1,41 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<svg width="34px" height="34px" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-    <title>编组 5备份 4</title>
-    <g id="云教练2版" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
-        <g id="画板" transform="translate(-549.000000, -55.000000)">
-            <g id="编组-5备份-4" transform="translate(551.000000, 57.000000)">
-                <rect id="矩形" stroke="#8EE1DC" stroke-width="2" fill="#FFFFFF" x="-1" y="-1" width="32" height="32" rx="12"></rect>
-                <g id="编组-2" transform="translate(4.000000, 6.000000)" fill="#01C1B5" fill-rule="nonzero">
-                    <g id="编组">
-                        <path d="M17.1788934,2.65984165 L21.2637262,2.66129281 C21.6441871,2.6595274 21.9627029,2.95663144 21.9969824,3.34525683 C22.0312619,3.73388223 21.7699052,4.08478959 21.3953125,4.15308163 L21.2637262,4.16614204 L17.1788934,4.16614204 C17.3474571,3.67892357 17.3474571,3.14706012 17.1788934,2.65984165 L17.1788934,2.65984165 Z" id="形状"></path>
-                        <path d="M12.7368421,0 C14.6553049,0 16.2105263,1.5552214 16.2105263,3.47368421 C16.2105263,5.39214703 14.6553049,6.94736842 12.7368421,6.94736842 C11.0558023,6.94736842 9.65365999,5.75326639 9.33235683,4.16700399 L0.73627375,4.16614204 C0.355812911,4.16790744 0.0372970883,3.8708034 0.00301760378,3.48217801 C-0.0312618807,3.09355262 0.230094793,2.74264526 0.604687516,2.67435322 L0.73627375,2.66129281 L9.35922942,2.65897043 C9.72584461,1.13357143 11.0989635,0 12.7368421,0 Z" id="形状结合"></path>
+<svg width="29px" height="29px" viewBox="0 0 29 29" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>速度</title>
+    <defs>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
+            <stop stop-color="#1D8270" offset="0%"></stop>
+            <stop stop-color="#105548" offset="100%"></stop>
+        </linearGradient>
+        <path d="M7.39092163,3.03294464 C7.39092163,3.72564768 7.56508899,4.37722505 7.87156676,4.94536012 L1.5,4.94501223 C0.671572875,4.94501223 1.01453063e-16,4.27343935 0,3.44501223 C-1.01453063e-16,2.6165851 0.671572875,1.94501223 1.5,1.94501223 L7.53933813,1.94388547 C7.44265229,2.29012358 7.39092163,2.6554266 7.39092163,3.03294464 Z M17.1949452,1.94501223 C18.0233723,1.94501223 18.6949452,2.6165851 18.6949452,3.44501223 C18.6949452,4.27343935 18.0233723,4.94501223 17.1949452,4.94501223 L14.8233784,4.94536012 C15.1298562,4.37722505 15.3040235,3.72564768 15.3040235,3.03294464 C15.3040235,2.6554266 15.2522929,2.29012358 15.155607,1.94388547 L17.1949452,1.94501223 Z" id="path-2"></path>
+        <path d="M3.42,12.4830669 C3.42,13.17577 3.59416736,13.8273473 3.90064512,14.3954824 L1.5,14.3951345 C0.671572875,14.3951345 1.01453063e-16,13.7235616 0,12.8951345 C-1.01453063e-16,12.0667074 0.671572875,11.3951345 1.5,11.3951345 L3.5684165,11.3940078 C3.47173066,11.7402459 3.42,12.1055489 3.42,12.4830669 Z M17.1949452,11.3951345 C18.0233723,11.3951345 18.6949452,12.0667074 18.6949452,12.8951345 C18.6949452,13.7235616 18.0233723,14.3951345 17.1949452,14.3951345 L10.8524568,14.3954824 C11.1589345,13.8273473 11.3331019,13.17577 11.3331019,12.4830669 C11.3331019,12.1055489 11.2813712,11.7402459 11.1846854,11.3940078 L17.1949452,11.3951345 Z" id="path-3"></path>
+        <ellipse id="path-4" cx="11.3474726" cy="3.03294464" rx="3" ry="3.03294464"></ellipse>
+        <ellipse id="path-5" cx="7.32" cy="12.4830669" rx="3" ry="3.03294464"></ellipse>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="主界面" transform="translate(-611.000000, -13.000000)">
+            <g id="速度" transform="translate(611.000000, 13.000000)">
+                <rect id="矩形备份-31" fill="#2DC7AA" x="0" y="0" width="29" height="29" rx="14.5"></rect>
+                <g id="编组-4" transform="translate(5.180000, 6.900000)">
+                    <g id="形状结合">
+                        <use fill="url(#linearGradient-1)" xlink:href="#path-2"></use>
+                        <use fill="#166B5B" xlink:href="#path-2"></use>
+                        <use fill="#FFFFFF" xlink:href="#path-2"></use>
                     </g>
-                    <g id="编组备份-3" transform="translate(11.000000, 15.078947) scale(-1, 1) translate(-11.000000, -15.078947) translate(0.000000, 11.578947)">
-                        <path d="M17.1788934,2.65984165 L21.2637262,2.66129281 C21.6441871,2.6595274 21.9627029,2.95663144 21.9969824,3.34525683 C22.0312619,3.73388223 21.7699052,4.08478959 21.3953125,4.15308163 L21.2637262,4.16614204 L17.1788934,4.16614204 C17.3474571,3.67892357 17.3474571,3.14706012 17.1788934,2.65984165 L17.1788934,2.65984165 Z" id="形状"></path>
-                        <path d="M12.7368421,0 C14.6553049,0 16.2105263,1.5552214 16.2105263,3.47368421 C16.2105263,5.39214703 14.6553049,6.94736842 12.7368421,6.94736842 C11.0558023,6.94736842 9.65365999,5.75326639 9.33235683,4.16700399 L0.73627375,4.16614204 C0.355812911,4.16790744 0.0372970883,3.8708034 0.00301760378,3.48217801 C-0.0312618807,3.09355262 0.230094793,2.74264526 0.604687516,2.67435322 L0.73627375,2.66129281 L9.35922942,2.65897043 C9.72584461,1.13357143 11.0989635,0 12.7368421,0 Z" id="形状结合"></path>
+                    <g id="形状结合">
+                        <use fill="url(#linearGradient-1)" xlink:href="#path-3"></use>
+                        <use fill="#166B5B" xlink:href="#path-3"></use>
+                        <use fill="#FFFFFF" xlink:href="#path-3"></use>
+                    </g>
+                    <g id="椭圆形备份-8">
+                        <use fill="#FFBB39" xlink:href="#path-4"></use>
+                        <ellipse stroke="#2DC7AA" stroke-width="1" fill="#FFFFFF" cx="11.3474726" cy="3.03294464" rx="3.5" ry="3.53294464"></ellipse>
+                    </g>
+                    <g id="椭圆形备份-9">
+                        <use fill="#FFBB39" xlink:href="#path-5"></use>
+                        <ellipse stroke="#2DC7AA" stroke-width="1" fill="#FFFFFF" cx="7.32" cy="12.4830669" rx="3.5" ry="3.53294464"></ellipse>
                     </g>
                 </g>
             </g>
         </g>
     </g>
-</svg>
+</svg>

+ 34 - 3
src/page-colexiu/header-top/index.module.less

@@ -5,6 +5,8 @@
     height: 100%;
     flex-shrink: 0;
     padding: 8px 10px;
+    background: var(--container-background);
+    padding-bottom: 0;
 }
 .back{
     display: flex;
@@ -27,7 +29,6 @@
         flex-direction: column;
         justify-content: center;
         align-items: center;
-        color: #fff;
         font-size: 11px;
         line-height: 16px;
         font-weight: 400;
@@ -50,8 +51,8 @@
             left: 50%;
             top: 50%;
             transform: translate(-50%, -50%);
-            width: 20px;
-            height: 20px;
+            width: 85%;
+            height: 85%;
         }
         &.disabled{
             opacity: .8;
@@ -67,9 +68,39 @@
             }
         }
     }
+    .playBtn{
+        position: fixed;
+        right: 32px;
+        bottom: 32px;
+        .btnWrap{
+            width: 36px;
+            height: 36px;
+            .iconBtn{
+                display: block;
+                width: 100%;
+                height: 100%;
+            }
+        }
+    }
+    .resetBtn{
+        position: fixed;
+        right: 88px;
+        bottom: 32px;
+        padding: 0;
+        .iconBtn{
+            display: block;
+            width: 36px;
+            height: 36px;
+        }
+    }
 }
 
 .disable{
     pointer-events: none;
     opacity: .6;
+}
+:global{
+    .var-popup{
+        overflow: hidden;
+    }
 }

+ 34 - 17
src/page-colexiu/header-top/index.tsx

@@ -3,7 +3,6 @@ import styles from "./index.module.less";
 
 import iconBack from "./image/icon-back.svg";
 import Title from "./title";
-import state, { handleChangeSection, handleResetPlay, togglePlay } from "../../state";
 import { headImg } from "./image";
 import icons from "./image/headerTop.json";
 import { Badge, Circle, Popover } from "vant";
@@ -12,6 +11,8 @@ import Speed from "./speed";
 import { evaluatingData, handleStartEvaluat } from "/src/view/evaluating";
 import { Popup } from "@varlet/ui";
 import Settting from "./settting";
+import ModeTypeMode from "./mode-type-mode";
+import state, { handleChangeSection, handleResetPlay, handleRessetState, togglePlay } from "/src/state";
 
 export const headData = reactive({
 	speedShow: false,
@@ -22,36 +23,50 @@ export default defineComponent({
 	setup() {
 		const headerData = reactive({
 			settingMode: false,
+			modeMode: true, // 模式弹框
 		});
 		const headRef = ref();
 
 		const toggleEvaluat = () => {
 			handleStartEvaluat();
 		};
+
+		/** 切换模式 */
+		const handleChangeModeType = (value: "practise" | "follow" | "evaluating") => {
+			if (value === 'evaluating') {
+				toggleEvaluat()
+			}
+			headerData.modeMode = false;
+		};
 		const disabledList = ["evaluating"];
 		return () => (
 			<div ref={headRef} class={styles.headerTop}>
 				<div class={styles.back}>
 					<img src={iconBack} />
 				</div>
-				<Title text={state.examSongName} />
+				<Title text={state.examSongName} rightView={false} />
 
-				<div class={styles.headRight}>
-					<div class={styles.btn} id="tips-step-2" onClick={toggleEvaluat}>
+				<div class={styles.headRight} style={{ display: headerData.modeMode ? "none" : "" }}>
+					<div class={styles.btn} onClick={() => {
+						handleRessetState()
+						headerData.modeMode = true
+					}}>
+						<img class={styles.iconBtn} src={headImg(`modeType.svg`)} />
+						<span>模式</span>
+					</div>
+					{/* <div class={styles.btn} id="tips-step-2" onClick={toggleEvaluat}>
 						<img class={styles.iconBtn} src={state.modeType === "evaluating" ? icons.evaluating2 : icons.evaluating} />
 						<span>评测</span>
-					</div>
+					</div> */}
 					<div class={[styles.btn, disabledList.includes(state.modeType) && styles.disable]} id="tips-step-4" onClick={() => handleChangeSection()}>
 						<img class={styles.iconBtn} src={headImg(`section${state.section.length}.svg`)} />
-						{/* <Button class={styles.button} icon={Icons["section" + state.section.length]} color="#01C1B5" disabled={runtime.isFirstPlay || runtime.evaluatingStatus || isHomework} onClick={this.authBefore("excerpts", RuntimeUtils.sectionChange)} /> */}
 						<span>选段</span>
 					</div>
-					<div class={[styles.btn, disabledList.includes(state.modeType) && styles.disable]} id="tips-step-5" onClick={() => togglePlay()}>
+					<div class={[styles.btn, styles.playBtn, disabledList.includes(state.modeType) && styles.disable]} id="tips-step-5" onClick={() => togglePlay()}>
 						<div class={styles.btnWrap}>
-							<img style={{ marginTop: "-1px" }} class={styles.iconBtn} src={state.playState === "paused" ? icons.play : icons.pause} />
-							<Circle class={styles.progress} stroke-width={80} currentRate={state.playProgress} rate={100} layerColor="#01C1B5" color="#FFC830" />
+							<img class={styles.iconBtn} src={state.playState === "paused" ? icons.play : icons.pause} />
+							<Circle style={{opacity: state.playState === "play" ? 1 : 0}} class={styles.progress} stroke-width={80} currentRate={state.playProgress} rate={100} color="#FFC830" />
 						</div>
-						<span>{state.playState === "play" ? "暂停" : "播放"}</span>
 					</div>
 					<div
 						class={[styles.btn, disabledList.includes(state.modeType) && styles.disable]}
@@ -63,7 +78,7 @@ export default defineComponent({
 						<img class={styles.iconBtn} src={state.playSource === "music" ? icons.music : icons.background} />
 						<span>{state.playSource === "music" ? "原声" : "伴奏"}</span>
 					</div>
-					<div
+					{/* <div
 						class={[styles.btn]}
 						onClick={async () => {
 							metronomeData.lineShow = !metronomeData.lineShow;
@@ -71,8 +86,8 @@ export default defineComponent({
 					>
 						<img class={styles.iconBtn} src={headImg("iconStep.png")} />
 						<span>{metronomeData.lineShow ? "高级" : "初级"}</span>
-					</div>
-					<div
+					</div> */}
+					{/* <div
 						class={styles.btn}
 						onClick={async () => {
 							metronomeData.disable = !metronomeData.disable;
@@ -82,10 +97,9 @@ export default defineComponent({
 						<img style={{ display: metronomeData.disable ? "block" : "none" }} class={styles.iconBtn} src={headImg("tickoff.png")} />
 						<img style={{ display: !metronomeData.disable ? "block" : "none" }} class={styles.iconBtn} src={headImg("tickon.png")} />
 						<span style={{ whiteSpace: "nowrap" }}>节拍器</span>
-					</div>
-					<div class={[styles.btn, disabledList.includes(state.modeType) && styles.disable]} id="tips-step-7" onClick={() => handleResetPlay()}>
+					</div> */}
+					<div class={[styles.btn, styles.resetBtn, disabledList.includes(state.modeType) && styles.disable]} id="tips-step-7" onClick={() => handleResetPlay()}>
 						<img class={styles.iconBtn} src={headImg("replay.svg")} />
-						<span>重播</span>
 					</div>
 
 					<Popover trigger="manual" v-model:show={headData.speedShow} placement="bottom" overlay={false}>
@@ -115,7 +129,10 @@ export default defineComponent({
 				</div>
 
 				<Popup teleport="body" defaultStyle={false} v-model:show={headerData.settingMode}>
-					<Settting onClose={() => headerData.settingMode = false} />
+					<Settting onClose={() => (headerData.settingMode = false)} />
+				</Popup>
+				<Popup teleport="body" position="bottom" closeOnClickOverlay={false} overlay={false} defaultStyle={false} v-model:show={headerData.modeMode}>
+					<ModeTypeMode onClose={(value) => handleChangeModeType(value)} />
 				</Popup>
 			</div>
 		);

+ 12 - 0
src/page-colexiu/header-top/mode-type-mode/index.module.less

@@ -0,0 +1,12 @@
+.wrap {
+  height: 110px;
+  display: flex;
+  justify-content: space-evenly;
+  align-items: center;
+  background: linear-gradient(to top, rgba(255,255,255,1), rgba(255,255,255, .7));
+  padding: 0 40px;
+  img {
+    width: 127px;
+    height: 46px;
+  }
+}

+ 17 - 0
src/page-colexiu/header-top/mode-type-mode/index.tsx

@@ -0,0 +1,17 @@
+import { defineComponent, Teleport, Transition } from "vue";
+import styles from "./index.module.less";
+import { model1, model2, model3 } from "../image/headerTop.json";
+
+export default defineComponent({
+	name: "modelWraper",
+	emits: ["close"],
+	setup(props, { emit }) {
+		return () => (
+			<div class={styles.wrap}>
+				<img onClick={() => emit("close", "practise")} src={model1} />
+				<img onClick={() => emit("close", "follow")} src={model3} />
+				<img onClick={() => emit("close", "evaluating")} src={model2} />
+			</div>
+		);
+	},
+});

+ 0 - 1
src/page-colexiu/header-top/title/index.tsx

@@ -23,7 +23,6 @@ export default defineComponent({
   render() {
     return (
       <div class={styles.container}>
-        <img class={styles.icon} src={MusicIcon}/>
         <NoticeBar
           text={this.text}
           color="#000"

+ 1 - 1
src/page-gym/header-top/index.module.less

@@ -48,7 +48,7 @@
         .progress{
             position: absolute;
             left: 50%;
-            top: 50%;
+            top: 47%;
             transform: translate(-50%, -50%);
             width: 20px;
             height: 20px;

+ 55 - 78
src/state.ts

@@ -1,11 +1,12 @@
-import { showToast, Toast } from "vant";
-import { reactive, watchEffect } from "vue";
+import { showToast } from "vant";
+import { reactive } from "vue";
 import { OpenSheetMusicDisplay } from "../osmd-extended/src";
-import _event, { EventEnum } from "./helpers/eventemitter";
 import { metronomeData } from "./helpers/metronome";
-import { GradualNote, GradualTimes, GradualVersion, IMode } from "./type";
-import { handleEndBegin, sendEvaluatingOffsetTime } from "./view/evaluating";
+import { GradualNote, GradualTimes, GradualVersion } from "./type";
+import { handleEndBegin, handleStartEvaluat, sendEvaluatingOffsetTime } from "./view/evaluating";
 import { IFingering } from "src/view/fingering/fingering-config";
+import { handleStartTick } from "./view/tick";
+import { audioListStart, getAudioCurrentTime, getAudioDuration, setAudioCurrentTime, setAudioPlaybackRate } from "./view/audio-list";
 
 /** 入门 | 进阶 | 大师 */
 export type IDifficulty = "BEGINNER" | "ADVANCED" | "PERFORMER";
@@ -70,10 +71,6 @@ const state = reactive({
 	activeNoteIndex: 0,
 	/** 激活的小节 */
 	activeMeasureIndex: 0,
-	/** 原音ref */
-	songEl: null as unknown as HTMLAudioElement,
-	/** 背景音乐ref */
-	backgroundEl: null as unknown as HTMLAudioElement,
 	/** 选段状态 */
 	sectionStatus: false,
 	/** 选段数据 */
@@ -117,39 +114,14 @@ const state = reactive({
 	fixtime: 0,
 	/** 指法信息 */
 	fingeringInfo: {} as IFingering,
-
-	repeatedBeats: 0,
-
-	maskStatus: false,
-	timesById: {} as any,
-
-	activeTick: -1,
-	activeTickRepeat: 1,
-	showTick: false,
-	isSpecialShapedScreen: false,
-	notchHeight: 0,
-	fixedKey: 0,
-	renderLoading: false,
-
-	isPauseRecording: false,
-	feeShow: false,
-	vipShow: false,
-	mode: "contact" as IMode,
-	activeSpeed: 90 as number, // 当前速度
-	baseSpeed: 90 as number, // 基准速度
-	activeDetail: null as any,
-	// 是否跳过节拍器时间
-	skipTick: false,
-
-	sectionFlash: false,
-	befireSection: null as any,
+	/** 滚动容器的ID */
+	scrollContainer: "musicAndSelection",
 	/** 是否是打击乐 */
 	isPercussion: false,
-	isAppPlay: false, // 是否是app播放
-	partListNames: [] as string[], // 当前曲谱中所有声部名字
-
-	midiPlayIniting: false, // midi播放器是否初始化中
-
+	/** 是否重复节拍器的时间 */
+	repeatedBeats: 0,
+	/**当前曲谱中所有声部名字 */
+	partListNames: [] as string[],
 	/** 渐变速度信息 */
 	gradual: [] as GradualNote[],
 	/** 渐变速度版本 */
@@ -184,7 +156,7 @@ const setStep = () => {
 export const onPlay = () => {
 	setStep();
 	if (state.modeType === "evaluating") {
-		const currentTime = state.songEl?.currentTime || 0;
+		const currentTime = getAudioCurrentTime();
 		sendEvaluatingOffsetTime(currentTime);
 	}
 };
@@ -209,32 +181,31 @@ export const onEnded = () => {
  * 播放一直触发的事件
  */
 const handlePlaying = (_item?: any) => {
-	if (state.songEl) {
-		const currentTime = state.songEl.currentTime;
-		state.playProgress = (currentTime / state.songEl.duration) * 100;
-		const item = _item ? _item : getNote(currentTime);
+	const currentTime = getAudioCurrentTime();
+	const duration = getAudioDuration();
+	state.playProgress = (currentTime / duration) * 100;
+	const item = _item ? _item : getNote(currentTime);
 
-		if (item) {
-			// 选段状态下
-			if (state.sectionStatus && state.section.length === 2) {
-				let startItemIndex = state.section[0].index;
-				let startXmlIndex = state.section[0].MeasureNumberXML;
-				// 开启预备拍
-				if (state.sectionFirst) {
-					startItemIndex = state.sectionFirst.i;
-					startXmlIndex = state.sectionFirst.MeasureNumberXML;
-				}
-				if (item.MeasureNumberXML < startXmlIndex || item.MeasureNumberXML > state.section[1].MeasureNumberXML) {
-					// console.log('选段播放结束')
-					skipNotePlay(startItemIndex);
-					return;
-				}
+	if (item) {
+		// 选段状态下
+		if (state.sectionStatus && state.section.length === 2) {
+			let startItemIndex = state.section[0].index;
+			let startXmlIndex = state.section[0].MeasureNumberXML;
+			// 开启预备拍
+			if (state.sectionFirst) {
+				startItemIndex = state.sectionFirst.i;
+				startXmlIndex = state.sectionFirst.MeasureNumberXML;
+			}
+			if (item.MeasureNumberXML < startXmlIndex || item.MeasureNumberXML > state.section[1].MeasureNumberXML) {
+				// console.log('选段播放结束')
+				skipNotePlay(startItemIndex);
+				return;
 			}
-			gotoNext(item);
 		}
-
-		metronomeData.metro?.sound(currentTime);
+		gotoNext(item);
 	}
+
+	metronomeData.metro?.sound(currentTime);
 };
 /** 跳转到指定音符开始播放 */
 export const skipNotePlay = (itemIndex: number, isStart = false) => {
@@ -245,8 +216,7 @@ export const skipNotePlay = (itemIndex: number, isStart = false) => {
 	}
 	// console.log("🚀 ~ itemTime:", itemTime);
 	if (item) {
-		state.songEl && (state.songEl.currentTime = itemTime);
-		state.backgroundEl && (state.backgroundEl.currentTime = itemTime);
+		setAudioCurrentTime(itemTime)
 		handlePlaying(item);
 	}
 };
@@ -255,25 +225,24 @@ export const skipNotePlay = (itemIndex: number, isStart = false) => {
  * 切换曲谱播放状态
  * @param playState 可选: 默认 undefined, 需要切换的状态 play:播放, paused: 暂停
  */
-export const togglePlay = (playState?: "play" | "paused") => {
+export const togglePlay = async (playState?: "play" | "paused") => {
 	state.playState = playState ? playState : state.playState === "paused" ? "play" : "paused";
+	if (state.playState === "play" && state.needTick) {
+		const tickend = await handleStartTick();
+		// console.log("🚀 ~ tickend:", tickend)
+	}
 	if (state.playState == "play") {
 		// 如果没有选段结束开始播放,清空选段状态
 		if (state.sectionStatus && state.section.length < 2) {
 			clearSelection();
 		}
-		state.songEl?.play();
-		state.backgroundEl?.play();
-	} else {
-		state.songEl?.pause();
-		state.backgroundEl?.pause();
 	}
+	audioListStart(state.playState);
 };
 /** 结束播放 */
 export const handleStopPlay = () => {
 	state.playState = "paused";
-	state.songEl?.pause();
-	state.backgroundEl?.pause();
+	audioListStart(state.playState);
 	skipNotePlay(0, true);
 };
 
@@ -345,8 +314,7 @@ export const handleSetSpeed = (speed: number) => {
 	console.log("🚀 ~ playbackRate:", speed, state.originSpeed);
 
 	// 按照比例设置速度
-	state.songEl && (state.songEl.playbackRate = playbackRate);
-	state.backgroundEl && (state.backgroundEl.playbackRate = playbackRate);
+	setAudioPlaybackRate(playbackRate);
 };
 /** 清除选段状态 */
 export const clearSelection = () => {
@@ -399,7 +367,7 @@ export const handleSelection = (item: any) => {
 		state.sectionToast.message = "请选择结束小节";
 	}
 };
-let offsetTop = 0
+let offsetTop = 0;
 /**
  * 窗口内滚动到音符的区域
  * @param isScroll 可选: 强制滚动到顶部, 默认: false
@@ -407,9 +375,9 @@ let offsetTop = 0
  */
 export const scrollViewNote = () => {
 	const cursorElement = document.getElementById("cursorImg-0")!;
-	const musicAndSelection = document.getElementById("musicAndSelection")!;
+	const musicAndSelection = document.getElementById(state.scrollContainer)!;
 	if (!cursorElement || !musicAndSelection || offsetTop === cursorElement.offsetTop) return;
-	offsetTop = cursorElement.offsetTop
+	offsetTop = cursorElement.offsetTop;
 	if (cursorElement.offsetTop > 50) {
 		musicAndSelection.scrollTo({
 			top: cursorElement.offsetTop - 25,
@@ -427,4 +395,13 @@ export const scrollViewNote = () => {
 export const isRhythmicExercises = () => {
 	return state.examSongName.indexOf("节奏练习") > -1;
 };
+
+/** 重置状态 */
+export const handleRessetState = () => {
+	if (state.modeType === "evaluating") {
+		handleStartEvaluat();
+	} else if (state.modeType === "practise") {
+		togglePlay("paused");
+	}
+};
 export default state;

+ 39 - 5
src/view/audio-list/index.tsx

@@ -1,8 +1,42 @@
-import { computed, defineComponent, onMounted, reactive } from "vue";
+import { computed, defineComponent, reactive } from "vue";
 import state, { onEnded, onLoadedmetadata, onPlay, onTimeupdate } from "../../state";
 import styles from "./index.module.less";
-import { Howl, Howler } from "howler";
-import tockAndTick from "/src/constant/tockAndTick.json";
+
+const audioData = reactive({
+	songEle: null as unknown as HTMLAudioElement,
+	backgroundEle:  null as unknown as HTMLAudioElement,
+
+})
+/** 播放或暂停 */
+export const audioListStart = (type: 'play' | 'paused') => {
+	if (type === 'play'){
+		audioData.songEle?.play()
+		audioData.backgroundEle?.play()
+	} else if (type === 'paused') {
+		audioData.songEle?.pause()
+		audioData.backgroundEle?.pause()
+	}
+}
+/** 设置倍数播放 */
+export const setAudioPlaybackRate = (rate: number) => {
+	audioData.songEle && (audioData.songEle.playbackRate = rate)
+	audioData.backgroundEle && (audioData.backgroundEle.playbackRate = rate)
+}
+
+/** 获取当前播放的时间 */
+export const getAudioCurrentTime = () => {
+	return audioData.songEle?.currentTime || audioData.backgroundEle?.currentTime || 0
+}
+/** 获取曲谱的总时间 */
+export const getAudioDuration = () => {
+	return audioData.songEle?.duration || audioData.backgroundEle?.duration || 0
+}
+
+/** 设置播放的开始时间 */
+export const setAudioCurrentTime = (time: number) => {
+	audioData.songEle && (audioData.songEle.currentTime = time)
+	audioData.backgroundEle && (audioData.backgroundEle.currentTime = time)
+}
 
 export default defineComponent({
 	name: "audio-list",
@@ -38,7 +72,7 @@ export default defineComponent({
 					preload="auto"
 					ref={(el) => {
 						if (state.music) {
-							state.songEl = el as HTMLAudioElement;
+							audioData.songEle = el as HTMLAudioElement
 						}
 					}}
 					src={state.music}
@@ -52,7 +86,7 @@ export default defineComponent({
 					preload="auto"
 					ref={(el) => {
 						if (state.accompany) {
-							state.backgroundEl = el as HTMLAudioElement;
+							audioData.backgroundEle = el as HTMLAudioElement;
 						}
 					}}
 					src={state.accompany}

+ 1 - 1
src/view/selection/index.tsx

@@ -121,7 +121,7 @@ export default defineComponent({
 			calcNoteData();
 		});
 		return () => (
-			<div class={styles.selectionContainer}>
+			<div class={styles.selectionContainer} onClick={(e: Event) => e.stopPropagation()}>
 				{selectData.staves.map((item: any) => {
 					const scoreItem = evaluatingData.evaluatings[item.measureListIndex];
 					return (

+ 26 - 0
src/view/tick/index.module.less

@@ -0,0 +1,26 @@
+.popup{
+    background: transparent;
+    width: 100%;
+    height: 100%;
+}
+.dots{
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+    height: 100%;
+}
+.dot{
+    width: 30px;
+    height: 30px;
+    margin: 0 20px;
+    background-color: #C0C0C0;
+    border-radius: 50%;
+    
+    &.active{
+        background-color: #fff;
+    }
+    &.one{
+        background-color: var(--van-primary-color);
+    }
+}

+ 85 - 0
src/view/tick/index.tsx

@@ -0,0 +1,85 @@
+import { defineComponent, reactive } from "vue";
+import tockAndTick from "/src/constant/tockAndTick.json";
+import { Howl } from "howler";
+import { Popup } from "vant";
+import styles from "./index.module.less";
+import { handleRessetState } from "/src/state";
+
+const tickData = reactive({
+	list: [] as number[],
+	timerList: [] as any[],
+	len: 0,
+	state: "",
+	source1: "" as unknown as Howl,
+	source2: "" as unknown as Howl,
+	index: 0,
+	show: false,
+});
+
+const handlePlay = (t: number, i: number) => {
+	return new Promise((resolve) => {
+		const timer = setTimeout(() => {
+			tickData.index++;
+			const source = i === 0 ? tickData.source1 : i === tickData.list.length - 1 ? ("" as unknown as Howl) : tickData.source2;
+			if (source) source.play();
+			resolve(t);
+		}, t);
+		tickData.timerList.push(timer);
+	});
+};
+
+/** 设置节拍器 */
+export const handleInitTick = (beatLengthInMilliseconds: number, beat: number) => {
+	const base = 500;
+	tickData.state = "";
+	tickData.list = [];
+	tickData.len = beat;
+	for (let i = 0; i < beat; i++) {
+		tickData.list.push(beatLengthInMilliseconds * i + base);
+	}
+	tickData.list.push(beatLengthInMilliseconds * beat + base);
+};
+
+/** 开始节拍器 */
+export const handleStartTick = async () => {
+	tickData.show = true;
+	if (tickData.state !== "ok") {
+		tickData.source1 = new Howl({
+			src: tockAndTick.tick,
+		});
+		tickData.source2 = new Howl({
+			src: tockAndTick.tock,
+		});
+		tickData.state = "ok";
+	}
+	tickData.index = 0;
+    tickData.timerList = []
+	const playList = tickData.list.map((t: number, i: number) => handlePlay(t, i));
+	await Promise.all(playList);
+	tickData.show = false;
+	return Promise.resolve(tickData.list);
+};
+
+export default defineComponent({
+	name: "metronome",
+	setup() {
+		/** 手动关闭 */
+		const handleClose = () => {
+			handleRessetState();
+            tickData.timerList.forEach((t) => {
+                clearTimeout(t)
+            })
+		};
+		return () => (
+			<Popup class={styles.popup} v-model:show={tickData.show} closeable onClickCloseIcon={handleClose}>
+				<div class={styles.dots}>
+					{Array(tickData.len)
+						.fill(0)
+						.map((n, i) => (
+							<div class={[styles.dot, tickData.index > i && styles.active, tickData.index > i && i === 0 && styles.one]}></div>
+						))}
+				</div>
+			</Popup>
+		);
+	},
+});

+ 1 - 1
vite.config.ts

@@ -55,7 +55,7 @@ export default defineConfig({
 				rewrite: (path) => path.replace(/^\/gym/, ""),
 			},
 			"^/colexiu/.*": {
-				target: "https://online.colexiu.com",
+				target: "https://dev.colexiu.com",
 				changeOrigin: true,
 				rewrite: (path) => path.replace(/^\/colexiu/, ""),
 			},

Some files were not shown because too many files changed in this diff