Metronome.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. <template>
  2. <div class="Metronome">
  3. <div class="MetronomeBox">
  4. <div class="headTools">
  5. <img
  6. src="./imgs/minMet.png"
  7. @click="
  8. () => {
  9. emits('windowMet');
  10. }
  11. "
  12. />
  13. <img
  14. src="./imgs/closeMet.png"
  15. @click="
  16. () => {
  17. emits('closeMet');
  18. }
  19. "
  20. />
  21. </div>
  22. <div class="beatWrap">
  23. <div
  24. class="dot"
  25. ref="dotDom"
  26. @mousedown="handleDotMousedown"
  27. @touchstart="handleDotTouchstart"
  28. ></div>
  29. <div class="round"></div>
  30. <canvas
  31. ref="mycanvasDom"
  32. class="mycanvas"
  33. width="252"
  34. height="252"
  35. @click="handleEventCanvas"
  36. ></canvas>
  37. <div class="beatCon">
  38. <img
  39. class="optImg"
  40. src="./imgs/jia.png"
  41. @click="
  42. () => {
  43. if (speedNum < 200) {
  44. speedNum++;
  45. }
  46. }
  47. "
  48. />
  49. <div class="optMid">
  50. <img class="optImg" src="./imgs/yin.png" />
  51. <n-input-number
  52. :disabled="true"
  53. placeholder=""
  54. :value="speedNum"
  55. :show-button="false"
  56. @update:value="(num:number)=>{
  57. if(num){
  58. if(num<=50){
  59. speedNum=50
  60. }else if(num>=200){
  61. speedNum=200
  62. }else{
  63. speedNum=num
  64. }
  65. }
  66. }"
  67. />
  68. </div>
  69. <img
  70. class="optImg"
  71. src="./imgs/jian.png"
  72. @click="
  73. () => {
  74. if (speedNum > 50) {
  75. speedNum--;
  76. }
  77. }
  78. "
  79. />
  80. </div>
  81. </div>
  82. <div class="selectCon">
  83. <n-select
  84. v-model:value="beatVal"
  85. :options="beatValOpt"
  86. :show-checkmark="false"
  87. :show-arrow="false"
  88. :placement="'top'"
  89. :render-tag="
  90. ({ option }:any) => {
  91. return h('div',{class:'beatName'},[h('div',option.labelHide),h('div','拍')])
  92. }
  93. "
  94. :render-label="
  95. (option:any) => {
  96. return h('div', option.labelHide);
  97. }
  98. "
  99. ></n-select>
  100. <n-select
  101. class="beatSymbolSel"
  102. v-model:value="beatSymbol"
  103. :options="beatSymbolOpt"
  104. :show-checkmark="false"
  105. :show-arrow="false"
  106. :placement="'top'"
  107. :render-tag="
  108. ({ option }:any) => {
  109. return h('div', { class: `beatSymbolImg${option.labelHide} beatSymbolImg` });
  110. }
  111. "
  112. :render-label="
  113. (option:any) => {
  114. return h('div', { class: `beatSymbolImg${option.labelHide} beatSymbolImg` });
  115. }
  116. "
  117. ></n-select>
  118. </div>
  119. <div class="sliderList">
  120. <img src="./imgs/sound.png" alt="" />
  121. <NSlider v-model:value="volumeNum" :step="1" :tooltip="false">
  122. <template #thumb>
  123. <img class="thumbDot" src="./imgs/dotBtn.png" alt="" />
  124. </template>
  125. </NSlider>
  126. <span class="sliderText">{{ volumeNum }}</span>
  127. </div>
  128. <div v-if="playState === 'pause'" class="playBtn" @click="startPlay">
  129. <span>播放</span>
  130. <img src="./imgs/playtBtn.png" />
  131. </div>
  132. <div v-else class="playBtn" @click="pausePlay">
  133. <span>暂停</span>
  134. <img class="pauseImg" src="./imgs/pauseBtn.png" />
  135. </div>
  136. </div>
  137. <Dragbom></Dragbom>
  138. </div>
  139. </template>
  140. <script setup lang="ts">
  141. import { ref, reactive, onMounted, onUnmounted, h, watch } from 'vue';
  142. import { NInputNumber, NSelect, NSlider } from 'naive-ui';
  143. import useMetronome from './useMetronome';
  144. import Dragbom from '@/hooks/useDrag/dragbom';
  145. import { getCachePos, setCachePos } from './useMetronome';
  146. import { useUserStore } from '@/store/modules/users';
  147. const users = useUserStore();
  148. const emits = defineEmits<{
  149. (e: 'windowMet'): void;
  150. (e: 'closeMet'): void;
  151. (e: 'playStateChange', state: 'play' | 'pause'): void;
  152. }>();
  153. /* dom */
  154. const mycanvasDom = ref<HTMLCanvasElement>();
  155. const dotDom = ref<HTMLElement>();
  156. /* select */
  157. const beatVal = ref('1');
  158. const beatValOpt = [
  159. {
  160. label: '',
  161. labelHide: '0',
  162. value: '0',
  163. class: 'beatValOptItem'
  164. },
  165. {
  166. label: '',
  167. labelHide: '1',
  168. value: '1',
  169. class: 'beatValOptItem'
  170. },
  171. {
  172. label: '',
  173. labelHide: '2',
  174. value: '1-1',
  175. class: 'beatValOptItem'
  176. },
  177. {
  178. label: '',
  179. labelHide: '3',
  180. value: '1-1-1',
  181. class: 'beatValOptItem'
  182. },
  183. {
  184. label: '',
  185. labelHide: '4',
  186. value: '1-1-1-1',
  187. class: 'beatValOptItem'
  188. },
  189. {
  190. label: '',
  191. labelHide: '5',
  192. value: '1-1-1-1-1',
  193. class: 'beatValOptItem'
  194. },
  195. {
  196. label: '',
  197. labelHide: '6',
  198. value: '1-1-1-1-1-1',
  199. class: 'beatValOptItem'
  200. },
  201. {
  202. label: '',
  203. labelHide: '7',
  204. value: '1-1-1-1-1-1-1',
  205. class: 'beatValOptItem'
  206. },
  207. {
  208. label: '',
  209. labelHide: '8',
  210. value: '1-1-1-1-1-1-1-1',
  211. class: 'beatValOptItem'
  212. },
  213. {
  214. label: '',
  215. labelHide: '9',
  216. value: '1-1-1-1-1-1-1-1-1',
  217. class: 'beatValOptItem'
  218. }
  219. ];
  220. const beatSymbol = ref('1');
  221. const beatSymbolOpt = [
  222. {
  223. label: '',
  224. labelHide: '1',
  225. value: '1',
  226. class: 'beatSymbolOptItem'
  227. },
  228. {
  229. label: '',
  230. labelHide: '2',
  231. value: '0.5-0.5',
  232. class: 'beatSymbolOptItem'
  233. },
  234. {
  235. label: '',
  236. labelHide: '3',
  237. value: '0.3333333-0.3333333-0.3333333',
  238. class: 'beatSymbolOptItem'
  239. },
  240. {
  241. label: '',
  242. labelHide: '4',
  243. value: '0.25-0.25-0.25-0.25',
  244. class: 'beatSymbolOptItem'
  245. },
  246. {
  247. label: '',
  248. labelHide: '5',
  249. value: '0.6666666-0.3333333',
  250. class: 'beatSymbolOptItem'
  251. },
  252. {
  253. label: '',
  254. labelHide: '6',
  255. value: '0.75-0.25',
  256. class: 'beatSymbolOptItem'
  257. },
  258. {
  259. label: '',
  260. labelHide: '7',
  261. value: '0.5-0.25-0.25',
  262. class: 'beatSymbolOptItem'
  263. }
  264. ];
  265. const { volumeNum, playState, speedNum, startPlay, pausePlay } = useMetronome(
  266. beatVal,
  267. beatSymbol
  268. );
  269. onMounted(() => {
  270. const cachePos = getCachePos(users.info.id);
  271. if (cachePos) {
  272. beatVal.value = cachePos.beatVal;
  273. beatSymbol.value = cachePos.beatSymbol;
  274. volumeNum.value = cachePos.volumeNum;
  275. speedNum.value = cachePos.speedNum;
  276. }
  277. /* n-input-number 有bug input-props设置maxlength不上去 */
  278. const iptDoms = document.querySelector(
  279. '.Metronome .MetronomeBox .optMid .n-input__input-el'
  280. );
  281. iptDoms?.setAttribute('maxlength', '3');
  282. getCircleBar(speedToScalc(speedNum.value));
  283. });
  284. onUnmounted(() => {
  285. setCachePos(users.info.id, {
  286. beatVal: beatVal.value,
  287. beatSymbol: beatSymbol.value,
  288. volumeNum: volumeNum.value,
  289. speedNum: speedNum.value
  290. });
  291. });
  292. watch(playState, () => {
  293. emits('playStateChange', playState.value);
  294. });
  295. watch(speedNum, () => {
  296. if (playState.value === 'play') {
  297. pausePlay();
  298. }
  299. getCircleBar(speedToScalc(speedNum.value));
  300. });
  301. watch([beatVal, beatSymbol], () => {
  302. if (playState.value === 'play') {
  303. pausePlay();
  304. }
  305. });
  306. function speedToScalc(speed: number) {
  307. return ((speed - 50) / 150) * 100;
  308. }
  309. function scalcToSpeed(scalc: number) {
  310. return Math.round((scalc * 150) / 100 + 50);
  311. }
  312. const handleEventCanvas = (e: MouseEvent | TouchEvent) => {
  313. const circle = mycanvasDom.value!.getBoundingClientRect();
  314. const centerX = circle.left + circle.width / 2;
  315. const centerY = circle.top + circle.height / 2;
  316. const event = isTouchEvent(e) ? e.touches[0] : e;
  317. const angle = Math.atan2(event.clientY - centerY, event.clientX - centerX);
  318. const percentage = (angle * (180 / Math.PI) + 180) / 360;
  319. const scalc = Math.round(percentage * 100) - 25;
  320. speedNum.value = scalcToSpeed(scalc < 0 ? 100 + scalc : scalc);
  321. };
  322. function handleDotMousedown() {
  323. function onMouseup() {
  324. document.removeEventListener('mousemove', onMousemove);
  325. document.removeEventListener('mouseup', onMouseup);
  326. }
  327. document.addEventListener('mousemove', onMousemove);
  328. document.addEventListener('mouseup', onMouseup);
  329. }
  330. function handleDotTouchstart() {
  331. function onTouchend() {
  332. document.removeEventListener('touchmove', onTouchmove);
  333. document.removeEventListener('touchend', onTouchend);
  334. }
  335. document.addEventListener('touchmove', onTouchmove);
  336. document.addEventListener('touchend', onTouchend);
  337. }
  338. function onMousemove(e: MouseEvent) {
  339. handleEventCanvas(e);
  340. }
  341. function onTouchmove(e: TouchEvent) {
  342. handleEventCanvas(e);
  343. }
  344. // 根据百分比画圆
  345. function getCircleBar(steps: number) {
  346. const radius = 121; //半径
  347. const colorList = ['#51DBFF', '#009FFF'];
  348. const mycanvas = mycanvasDom.value!;
  349. const ctx = mycanvas.getContext('2d')!;
  350. // 每次进来清空画布
  351. ctx.clearRect(0, 0, mycanvas.width, mycanvas.height);
  352. //找到画布的中心点
  353. const canvasX = mycanvas.width / 2;
  354. const canvasY = mycanvas.height / 2;
  355. //进度条是100%,所以要把一圈360度分成100份
  356. const progress = (Math.PI * 2) / 100;
  357. const ao = -Math.PI / 2 + steps * progress;
  358. const x1 = radius + Math.cos(ao) * radius;
  359. const y1 = radius + Math.sin(ao) * radius;
  360. // 这里开始算坐标
  361. dotDom.value!.style.left = x1 - 7 + 'Px';
  362. dotDom.value!.style.top = y1 - 7 + 'Px';
  363. // 绘制渐变色
  364. const gradientDirection = {
  365. x1: 0,
  366. y1: 0,
  367. x2: radius * 2, // 半径*2
  368. y2: 0
  369. };
  370. gradientDirection.y2 = radius * 2;
  371. const gradient = ctx.createLinearGradient(
  372. gradientDirection.x1,
  373. gradientDirection.y1,
  374. gradientDirection.x2,
  375. gradientDirection.y2
  376. );
  377. colorList.map((color, index) => {
  378. gradient.addColorStop(index, color);
  379. });
  380. ctx.strokeStyle = gradient;
  381. ctx.lineWidth = 10;
  382. ctx.save();
  383. ctx.beginPath();
  384. ctx.arc(
  385. canvasX,
  386. canvasY,
  387. radius,
  388. -Math.PI / 2,
  389. -Math.PI / 2 + steps * progress,
  390. false
  391. );
  392. ctx.stroke();
  393. ctx.closePath();
  394. ctx.restore();
  395. }
  396. function isTouchEvent(e: MouseEvent | TouchEvent): e is TouchEvent {
  397. return window.TouchEvent && e instanceof window.TouchEvent;
  398. }
  399. defineExpose({
  400. startPlay,
  401. pausePlay,
  402. speedNum,
  403. beatSymbol
  404. });
  405. </script>
  406. <style lang="less" scoped>
  407. .Metronome {
  408. width: 565Px;
  409. height: 554Px;
  410. background: url('./imgs/bg.png') no-repeat;
  411. background-size: 100% 100%;
  412. padding: 26Px 26Px 0;
  413. &:deep(.bom_drag) {
  414. position: absolute;
  415. bottom: 0;
  416. left: 0;
  417. height: 76Px;
  418. padding: 0 28Px;
  419. & > div {
  420. width: 40Px;
  421. height: 40Px;
  422. border-radius: 0 0 18Px 0;
  423. &:first-child {
  424. border-radius: 0 0 0 18Px;
  425. }
  426. }
  427. }
  428. .MetronomeBox {
  429. width: 100%;
  430. position: relative;
  431. display: flex;
  432. flex-direction: column;
  433. align-items: center;
  434. z-index: 2;
  435. }
  436. .headTools {
  437. position: absolute;
  438. right: 20Px;
  439. top: 18Px;
  440. & > img {
  441. margin-left: 18Px;
  442. width: 24Px;
  443. height: 24Px;
  444. cursor: pointer;
  445. }
  446. }
  447. .beatWrap {
  448. margin-top: 30Px;
  449. width: 252Px;
  450. height: 252Px;
  451. position: relative;
  452. display: flex;
  453. justify-content: center;
  454. align-items: center;
  455. .dot {
  456. position: absolute;
  457. width: 24Px;
  458. height: 24Px;
  459. background: url('./imgs/dot.png') no-repeat;
  460. background-size: 100% 100%;
  461. cursor: pointer;
  462. z-index: 3;
  463. }
  464. .round {
  465. position: absolute;
  466. left: 0;
  467. top: 0;
  468. width: 100%;
  469. height: 100%;
  470. border-radius: 50%;
  471. border: 10Px solid #d1d1d1;
  472. z-index: 1;
  473. }
  474. .mycanvas {
  475. position: absolute;
  476. left: 0;
  477. top: 0;
  478. z-index: 2;
  479. }
  480. .beatCon {
  481. border-radius: 50%;
  482. z-index: 4;
  483. width: 200Px;
  484. height: 200Px;
  485. background: url('./imgs/yuan.png') no-repeat;
  486. background-size: 100% 100%;
  487. display: flex;
  488. flex-direction: column;
  489. align-items: center;
  490. justify-content: center;
  491. .optMid {
  492. margin: 5Px 0;
  493. display: flex;
  494. align-items: center;
  495. :deep(.n-input-number) {
  496. width: 74Px;
  497. height: 52Px;
  498. margin-left: 4Px;
  499. .n-input {
  500. height: 100%;
  501. --n-height: 100% !important;
  502. --n-color-focus: initial !important;
  503. --n-color: initial !important;
  504. --n-padding-left: initial !important;
  505. --n-padding-right: initial !important;
  506. --n-color-disabled: initial !important;
  507. --n-caret-color: #3a3939 !important;
  508. .n-input__border,
  509. .n-input__state-border {
  510. display: none;
  511. }
  512. .n-input__input-el {
  513. text-align: center;
  514. font-family: DINA !important;
  515. font-weight: bold !important;
  516. font-size: 45Px !important;
  517. color: #000000 !important;
  518. }
  519. &.n-input--disabled {
  520. cursor: initial;
  521. .n-input__input-el {
  522. cursor: initial;
  523. }
  524. }
  525. }
  526. }
  527. }
  528. .optImg {
  529. cursor: pointer;
  530. width: 35Px;
  531. height: 35Px;
  532. }
  533. }
  534. }
  535. .selectCon {
  536. display: flex;
  537. margin-top: 22Px;
  538. :deep(.n-select) {
  539. width: 130Px;
  540. .n-base-selection--selected {
  541. --n-height: 48Px !important;
  542. --n-border-radius: 24Px !important;
  543. .n-base-selection__border,
  544. .n-base-selection__state-border {
  545. display: none;
  546. }
  547. .n-base-selection-input {
  548. padding: 0;
  549. .n-base-selection-input__content {
  550. .beatName {
  551. display: flex;
  552. justify-content: center;
  553. align-items: center;
  554. padding-top: 2Px;
  555. & > div:first-child {
  556. font-weight: 500;
  557. font-size: 30Px;
  558. color: #333333;
  559. }
  560. & > div:last-child {
  561. margin-left: 2Px;
  562. font-weight: 500;
  563. font-size: 14Px;
  564. color: #333333;
  565. margin-top: 4Px;
  566. }
  567. }
  568. }
  569. }
  570. }
  571. }
  572. :deep(.beatSymbolSel.n-select) {
  573. margin-left: 15Px;
  574. .n-base-selection-input__content {
  575. display: flex;
  576. justify-content: center;
  577. .beatSymbolImg {
  578. width: 44Px;
  579. height: 46Px;
  580. &.beatSymbolImg1 {
  581. background: url('./imgs/b1.png') no-repeat;
  582. background-size: 100% 100%;
  583. }
  584. &.beatSymbolImg2 {
  585. background: url('./imgs/b2.png') no-repeat;
  586. background-size: 100% 100%;
  587. }
  588. &.beatSymbolImg3 {
  589. background: url('./imgs/b3.png') no-repeat;
  590. background-size: 100% 100%;
  591. }
  592. &.beatSymbolImg4 {
  593. background: url('./imgs/b4.png') no-repeat;
  594. background-size: 100% 100%;
  595. }
  596. &.beatSymbolImg5 {
  597. background: url('./imgs/b5.png') no-repeat;
  598. background-size: 100% 100%;
  599. }
  600. &.beatSymbolImg6 {
  601. background: url('./imgs/b6.png') no-repeat;
  602. background-size: 100% 100%;
  603. }
  604. &.beatSymbolImg7 {
  605. background: url('./imgs/b7.png') no-repeat;
  606. background-size: 100% 100%;
  607. }
  608. }
  609. }
  610. }
  611. }
  612. .sliderList {
  613. margin-top: 24Px;
  614. display: flex;
  615. align-items: center;
  616. & > img {
  617. width: 18Px;
  618. height: 18Px;
  619. margin-right: 16Px;
  620. }
  621. .sliderText {
  622. width: 32Px;
  623. font-weight: 500;
  624. font-size: 16Px;
  625. color: #1cacf1;
  626. margin-left: 16Px;
  627. }
  628. :deep(.n-slider-rail) {
  629. height: 6Px;
  630. line-height: 6Px;
  631. background: #ffffff;
  632. border-radius: 4Px;
  633. width: 194Px;
  634. .n-slider-rail__fill {
  635. background: linear-gradient(90deg, #63daff 0%, #1798ff 100%);
  636. border-radius: 4Px;
  637. }
  638. }
  639. .thumbDot {
  640. width: 21Px;
  641. height: 21Px;
  642. }
  643. }
  644. .playBtn {
  645. cursor: pointer;
  646. margin-top: 20Px;
  647. width: 272Px;
  648. height: 54Px;
  649. background: #00acff;
  650. border-radius: 27Px;
  651. display: flex;
  652. justify-content: center;
  653. align-items: center;
  654. font-weight: 600;
  655. font-size: 18Px;
  656. color: #ffffff;
  657. & > img {
  658. margin-left: 14Px;
  659. width: 13Px;
  660. height: 14Px;
  661. &.pauseImg {
  662. width: 12Px;
  663. height: 13Px;
  664. }
  665. }
  666. }
  667. }
  668. </style>
  669. <style lang="less">
  670. .n-base-select-menu.n-select-menu {
  671. .beatValOptItem {
  672. padding: 0 9Px !important;
  673. display: flex;
  674. justify-content: center;
  675. &.n-base-select-option::before {
  676. transition: initial;
  677. }
  678. &.n-base-select-option--selected {
  679. .n-base-select-option__content {
  680. color: #47a7fe;
  681. }
  682. }
  683. &.n-base-select-option--pending {
  684. .n-base-select-option__content {
  685. color: #ffffff;
  686. }
  687. &::before {
  688. background: #47a7fe !important;
  689. border-radius: 6Px !important;
  690. left: 9Px;
  691. right: 9Px;
  692. }
  693. }
  694. .n-base-select-option__content {
  695. font-weight: 500;
  696. font-size: 18Px;
  697. color: #777777;
  698. }
  699. }
  700. .beatSymbolOptItem {
  701. display: flex;
  702. justify-content: center;
  703. &.n-base-select-option::before {
  704. transition: initial;
  705. }
  706. &.n-base-select-option--selected {
  707. .n-base-select-option__content {
  708. .beatSymbolImg {
  709. &.beatSymbolImg1 {
  710. background: url('./imgs/a1.png') no-repeat;
  711. background-size: 100% 100%;
  712. }
  713. &.beatSymbolImg2 {
  714. background: url('./imgs/a2.png') no-repeat;
  715. background-size: 100% 100%;
  716. }
  717. &.beatSymbolImg3 {
  718. background: url('./imgs/a3.png') no-repeat;
  719. background-size: 100% 100%;
  720. }
  721. &.beatSymbolImg4 {
  722. background: url('./imgs/a4.png') no-repeat;
  723. background-size: 100% 100%;
  724. }
  725. &.beatSymbolImg5 {
  726. background: url('./imgs/a5.png') no-repeat;
  727. background-size: 100% 100%;
  728. }
  729. &.beatSymbolImg6 {
  730. background: url('./imgs/a6.png') no-repeat;
  731. background-size: 100% 100%;
  732. }
  733. &.beatSymbolImg7 {
  734. background: url('./imgs/a7.png') no-repeat;
  735. background-size: 100% 100%;
  736. }
  737. }
  738. }
  739. }
  740. &.n-base-select-option--pending {
  741. .n-base-select-option__content {
  742. .beatSymbolImg {
  743. &.beatSymbolImg1 {
  744. background: url('./imgs/c1.png') no-repeat;
  745. background-size: 100% 100%;
  746. }
  747. &.beatSymbolImg2 {
  748. background: url('./imgs/c2.png') no-repeat;
  749. background-size: 100% 100%;
  750. }
  751. &.beatSymbolImg3 {
  752. background: url('./imgs/c3.png') no-repeat;
  753. background-size: 100% 100%;
  754. }
  755. &.beatSymbolImg4 {
  756. background: url('./imgs/c4.png') no-repeat;
  757. background-size: 100% 100%;
  758. }
  759. &.beatSymbolImg5 {
  760. background: url('./imgs/c5.png') no-repeat;
  761. background-size: 100% 100%;
  762. }
  763. &.beatSymbolImg6 {
  764. background: url('./imgs/c6.png') no-repeat;
  765. background-size: 100% 100%;
  766. }
  767. &.beatSymbolImg7 {
  768. background: url('./imgs/c7.png') no-repeat;
  769. background-size: 100% 100%;
  770. }
  771. }
  772. }
  773. &::before {
  774. background: #47a7fe !important;
  775. border-radius: 6Px !important;
  776. left: 9Px;
  777. right: 9Px;
  778. }
  779. }
  780. .beatSymbolImg {
  781. width: 44Px;
  782. height: 46Px;
  783. &.beatSymbolImg1 {
  784. background: url('./imgs/b1.png') no-repeat;
  785. background-size: 100% 100%;
  786. }
  787. &.beatSymbolImg2 {
  788. background: url('./imgs/b2.png') no-repeat;
  789. background-size: 100% 100%;
  790. }
  791. &.beatSymbolImg3 {
  792. background: url('./imgs/b3.png') no-repeat;
  793. background-size: 100% 100%;
  794. }
  795. &.beatSymbolImg4 {
  796. background: url('./imgs/b4.png') no-repeat;
  797. background-size: 100% 100%;
  798. }
  799. &.beatSymbolImg5 {
  800. background: url('./imgs/b5.png') no-repeat;
  801. background-size: 100% 100%;
  802. }
  803. &.beatSymbolImg6 {
  804. background: url('./imgs/b6.png') no-repeat;
  805. background-size: 100% 100%;
  806. }
  807. &.beatSymbolImg7 {
  808. background: url('./imgs/b7.png') no-repeat;
  809. background-size: 100% 100%;
  810. }
  811. }
  812. }
  813. }
  814. .metronomeConBoxClass_drag
  815. .v-binder-follower-container
  816. .n-base-select-menu.n-select-menu {
  817. --n-border-radius: 10Px !important;
  818. .n-scrollbar-rail.n-scrollbar-rail--vertical {
  819. right: 3Px;
  820. --n-scrollbar-width: 3Px !important;
  821. opacity: 0.4;
  822. }
  823. }
  824. </style>