Browse Source

切换合奏

liushengqiang 1 year ago
parent
commit
a79111c649

+ 3 - 0
src/subpages/colexiu/app.css

@@ -91,3 +91,6 @@
   overflow: hidden;
   border-radius: 5px;
 }
+.vf-StaveSection{
+  display: none;
+}

+ 228 - 0
src/subpages/colexiu/helpers/instruments.ts

@@ -0,0 +1,228 @@
+const instruments: {[_:string]: any} = {
+  'Acoustic Grand Piano': '大钢琴',
+  'Bright Acoustic Piano': '明亮的钢琴',
+  'Electric Grand Piano': '电钢琴',
+  'Rhodes Piano': '柔和的电钢琴',
+  'Chorused Piano': '加合唱效果的电钢琴',
+  Harpsichord: '羽管键琴',
+  Clavichord: '科拉维科特琴',
+  Celesta: '钢片琴',
+  Glockenspiel: '钢片琴',
+  'Music box': '八音盒',
+  Vibraphone: '颤音琴',
+  Marimba: '马林巴',
+  Xylophone: '木琴',
+  'Tubular Bells': '管钟',
+  Dulcimer: '大扬琴',
+  'Hammond Organ': '击杆风琴',
+  'Percussive Organ': '打击式风琴',
+  'Rock Organ': '摇滚风琴',
+  'Church Organ': '教堂风琴',
+  'Reed Organ': '簧管风琴',
+  Accordian: '手风琴',
+  Harmonica: '口琴',
+  'Tango Accordian': '探戈手风琴',
+  'Acoustic Guitar': '钢弦吉他',
+  'Electric Guitar': '闷音电吉他',
+  'Overdriven Guitar': '加驱动效果的电吉他',
+  'Distortion Guitar': '加失真效果的电吉他',
+  'Guitar Harmonics': '吉他和音',
+  'Acoustic Bass': '大贝司',
+  'Electric Bass': '电贝司',
+  'Fretless Bass': '无品贝司',
+  'Slap Bass': '掌击',
+  'Synth Bass': '电子合成',
+  Violin: '小提琴',
+  Viola: '中提琴',
+  Cello: '大提琴',
+  Contrabass: '低音大提琴',
+  'Tremolo Strings': '弦乐群颤音音色',
+  'Pizzicato Strings': '弦乐群拨弦音色',
+  'Orchestral Harp': '竖琴',
+  Timpani: '定音鼓',
+  'String Ensemble': '弦乐合奏音色',
+  'Synth Strings': '合成弦乐合奏音色',
+  'Choir Aahs': '人声合唱',
+  'Voice Oohs': '人声',
+  'Synth Voice': '合成人声',
+  'Orchestra Hit': '管弦乐敲击齐奏',
+  Trumpet: '小号',
+  Trombone: '长号',
+  Tuba: '大号',
+  'Muted Trumpet': '加弱音器小号',
+  'French Horn': '法国号',
+  'Brass Section': '铜管组',
+  'Synth Brass': '合成铜管音色',
+  'Soprano Sax': '高音萨克斯管',
+  'Alto Sax': '中音萨克斯管',
+  'Tenor Sax': '次中音萨克斯管',
+  'Baritone Sax': '低音萨克斯管',
+  Oboe: '双簧管',
+  'English Horn': '英国管',
+  Bassoon: '巴松',
+  Clarinet: '单簧管',
+  'Soprano Saxophone': '高音萨克斯管',
+  'Alto Saxophone': '中音萨克斯管',
+  'Tenor Saxophone': '次中音萨克斯管',
+  'Baritone Saxophone': '低音萨克斯管',
+  Piccolo: '短笛',
+  Flute: '长笛',
+  Recorder: '竖笛',
+  'Soprano Recorder': '高音竖笛',
+  'Pan Flute': '排箫',
+  'Bottle Blow': '瓶木管',
+  Whistle: '口哨声',
+  Ocarina: '陶笛',
+  Lead: '合成主音',
+  'Lead lead': '合成主音',
+  'Pad age': '合成音色',
+  Pad: '合成音色',
+  FX: '合成效果  科幻',
+  Sitar: '西塔尔',
+  Banjo: '班卓琴',
+  Shamisen: '三昧线',
+  Koto: '十三弦筝',
+  Kalimba: '卡林巴',
+  Bagpipe: '风笛',
+  Fiddle: '民族提琴',
+  Shanai: '山奈',
+  'Tinkle Bell': '叮当铃',
+  Agogos: '阿戈戈铃',
+  'Steel Drums': '钢鼓',
+  'Taiko Drum': '太鼓',
+  'Melodic Toms': '嗵嗵鼓',
+  'Synth Drums': '合成鼓',
+  'Reverse Cymbals': '反向镲',
+  'Agogo Bells': '阿戈戈铃',
+  'Taiko Drums': '太鼓',
+  Bongos: '邦戈鼓',
+  'Bongo Bell': '邦戈铃',
+  Congas: '康加鼓',
+  Guiro: '刮壶',
+  'Guitar Fret Noise': '吉他换把杂音',
+  'Breath Noise': '呼吸声',
+  Seashore: '海浪声',
+  'Bird Tweet': '鸟鸣',
+  'Telephone Ring': '电话铃',
+  Helicopter: '直升机',
+  Applause: '鼓掌声',
+  Gunshot: '枪声',
+  'Acoustic Bass Drum': '大鼓',
+  'Bass Drum': '大鼓',
+  'Side Drum': '小鼓鼓边',
+  'Acoustic Snare': '小鼓',
+  'Hand Claps': '拍手',
+  'Electric Snare': '小鼓',
+  'Low Floor Tom': '低音嗵鼓',
+  'Closed Hi-Hat': '闭合踩镲',
+  'High Floor Tom': '高音落地嗵鼓',
+  'Pedal Hi-Hat': '脚踏踩镲',
+  'Low Tom': '低音嗵鼓',
+  'Open Hi-Hat': '开音踩镲',
+  'Low-Mid Tom': '中低音嗵鼓',
+  'Hi Mid Tom': '高音鼓',
+  'Crash Cymbals': '对镲',
+  'High Tom': '高音嗵鼓',
+  'Ride Cymbals': '叮叮镲',
+  'Chinese Cymbals': '中国镲',
+  'Ride Bell': '圆铃',
+  Tambourine: '铃鼓',
+  'Splash Cymbal': '溅音镲',
+  Cowbell: '牛铃',
+  'Crash Cymbal': '强音钹',
+  'Vibra-Slap': '颤音器',
+  'Ride Cymbal': '打点钹',
+  'Hi Bongo': '高音邦戈鼓',
+  'Low Bongo': '低音邦戈鼓',
+  'Mute Hi Conga': '弱音高音康加鼓',
+  'Open Hi Conga': '强音高音康加鼓',
+  'Low Conga': '低音康加鼓',
+  'High Timbale': '高音天巴鼓',
+  'Low Timbale': '低音天巴鼓',
+  'High Agogo': '高音阿戈戈铃',
+  'Low Agogo': '低音阿戈戈铃',
+  Cabasa: '卡巴萨',
+  Maracas: '沙锤',
+  'Short Whistle': '短口哨',
+  'Long Whistle': '长口哨',
+  'Short Guiro': '短刮壶',
+  'Long Guiro': '长刮壶',
+  Claves: '响棒',
+  'Hi Wood Block': '高音木鱼',
+  'Low Wood Block': '低音木鱼',
+  'Mute Triangle': '弱音三角铁',
+  'Open Triangle': '强音三角铁',
+  'Drum Set': '架子鼓',
+  'Hulusi flute': '葫芦丝',
+  Melodica: '口风琴',
+  'Snare Drum': '小军鼓',
+  Cymbal: '镲',
+  Cymbals: '镲',
+  'Horn in F': '圆号',
+  Triangle: '三角铁',
+  Vibrato: '颤音琴',
+  'Suspend Cymbals': '吊镲',
+  'Suspended Cymbals': '吊镲',
+  'Tom-Toms': '嗵嗵鼓',
+  Bell: '铃铛',
+  Bells: '铃铛',
+  'Alto Clarinet': '中音单簧管',
+  'Bass Clarinet': '低音单簧管',
+  Cornet: '短号',
+  Euphonium: '上低音号',
+  'crash cymbals': '对镲',
+  Castanets: '响板',
+  Shaker: '沙锤',
+  'Mark tree': '音树',
+  Chimes: '管钟',
+  'Mark Tree': '音树',
+  'Tom-toms': '嗵嗵鼓',
+  'Hi-Hat': '踩镲',
+  'Sleigh Bells': '雪橇铃',
+  Flexatone: '弹音器',
+  'Brake drum': '闸鼓',
+  Gong: '锣',
+  'concert tom': '音乐会嗵嗵鼓',
+  'brake drum': '车轮鼓',
+  'finger cymbal': '指钹',
+  'ride cymbal': '叮叮镲',
+  'Concert Toms': '音乐会嗵嗵鼓',
+  Vibraslap: '弹音器',
+  'Wood Blocks': '木鱼',
+  'Temple Blocks': '木鱼',
+  'Wood Block': '木鱼',
+  'Field Drum': '军鼓',
+  'Quad-Toms': '筒鼓',
+  Quads: '筒鼓',
+  'Drums set': '架子鼓',
+  'High Bongo': '邦戈',
+  Timbales: '天巴鼓',
+  'rain stick': '雨棒',
+  'String Bass': '弦乐低音',
+  'Floor Tom': '侧嗵鼓',
+  'Brake Drum': '闸鼓',
+  'Tam-tam': '大锣'
+}
+
+/**
+ * 获取乐器名称
+ * @param instrumentName 乐器code
+ * @returns 
+ */
+export const getInstrumentName = (instrumentName: string) => {
+  const _instrumentName = instrumentName.replace(/ /g, ' ').toLocaleLowerCase()
+  const _instrument = Object.keys(instruments)
+  for (let i = 0; i < _instrument.length; i++) {
+    const _name = _instrument[i].replace(/ /g, ' ').toLocaleLowerCase()
+    if (_name === _instrumentName) {
+      return instruments[_instrument[i]] || ''
+    }
+  }
+  for (let i = 0; i < _instrument.length; i++) {
+    const _name = _instrument[i].replace(/ /g, ' ').toLocaleLowerCase()
+    if (_instrumentName.includes(_name)) {
+      return instruments[_instrument[i]] || ''
+    }
+  }
+  return ''
+}

+ 17 - 12
src/subpages/colexiu/index.tsx

@@ -46,6 +46,7 @@ import Follow from './popups/follow'
 import UnitTest from './unitTest'
 import { renderError } from './App'
 import { musicInfo } from './state'
+import ToggleMusicSheet from './plugins/toggleMusicSheet'
 
 // json化曲谱的note信息和svg
 export const musicJSON = reactive({
@@ -270,14 +271,17 @@ export default defineComponent({
     }
 
     /** 是否评测模式,并且有指法监听变化 */
-    watch(() => runtime.evaluatingStatus, () => {
-      // 指法开启的时候
-      if (SettingState.sett.fingering && (fingeringDetail.value as any)?.direction === 'vertical') {
-        nextTick(() => {
-          MusicSheetRef.value.reRender()
-        })
+    watch(
+      () => runtime.evaluatingStatus,
+      () => {
+        // 指法开启的时候
+        if (SettingState.sett.fingering && (fingeringDetail.value as any)?.direction === 'vertical') {
+          nextTick(() => {
+            MusicSheetRef.value.reRender()
+          })
+        }
       }
-    })
+    )
 
     return () => {
       const loading = renderLoading.value || detailStatus.value === 'loading'
@@ -355,11 +359,7 @@ export default defineComponent({
                     onRenderError={onRenderError}
                     onRerender={onRerender}
                   />
-                  {needFingering && (
-                    <Fingering
-                      code={detail.value.code}
-                    />
-                  )}
+                  {needFingering && <Fingering code={detail.value.code} />}
                 </>
               )}
               {modelType.value === 'follow' && <Follow ref={followRef} />}
@@ -399,6 +399,11 @@ export default defineComponent({
 
           {/* 单元测验选段 */}
           {!renderLoading.value && <UnitTest />}
+
+          {/* 切换曲谱 */}
+          {!search.lessonTrainingId && !search.questionId && detailState.activeDetail?.background?.length > 2 && (
+            <ToggleMusicSheet />
+          )}
         </>
       )
     }

+ 39 - 0
src/subpages/colexiu/plugins/toggleMusicSheet/choosePartName/index.module.less

@@ -0,0 +1,39 @@
+.container {
+  display: flex;
+  flex-direction: column;
+  width: 50vw;
+  height: 80vh;
+  max-height: 500px;
+  background-color: #fff;
+  overflow: hidden;
+
+  .top {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 8px 4px 8px 8px;
+    position: relative;
+    font-size: 14Px;
+    &::before {
+      content: '';
+      position: absolute;
+      left: 4px;
+      top: 50%;
+      height: 30%;
+      transform: translateY(-50%);
+      width: 2px;
+      background-color: var(--van-primary-color);
+      border-radius: 2px;
+    }
+  }
+
+  .picker {
+    flex: 1;
+  }
+
+  .button {
+    width: 50%;
+    height: 40Px;
+    margin: 10Px auto;
+  }
+}

+ 47 - 0
src/subpages/colexiu/plugins/toggleMusicSheet/choosePartName/index.tsx

@@ -0,0 +1,47 @@
+import { PropType, computed, defineComponent, ref, toRefs } from 'vue'
+import { Picker, Button, Icon } from 'vant'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'choosePartName',
+  props: {
+    partListNames: {
+      type: Array as PropType<string[]>,
+      default: () => [],
+    },
+    partIndex: {
+      type: Number,
+      default: 0,
+    }
+  },
+  emits: ['close'],
+  setup(props, { emit }) {
+    const { partListNames, partIndex } = toRefs(props)
+    const selectIndex = ref(0)
+    const columns = computed(() => {
+      return partListNames.value
+    })
+    return () => (
+      <div class={styles.container}>
+        <div class={styles.top}>
+          <div class={styles.title}>请选择您练习的乐器</div>
+          <Icon name="cross" size={24} onClick={() => emit('close')} />
+        </div>
+        <Picker
+          class={styles.picker}
+          defaultIndex={partIndex.value}
+          showToolbar={false}
+          columns={columns.value}
+		  visibleItemCount={Math.ceil(document.body.clientHeight / 44 / 3)}
+          onChange={(row) => {
+			console.log(row)
+            selectIndex.value = row.value
+          }}
+        />
+        <Button class={styles.button} type="primary" round block onClick={() => emit('close', selectIndex.value)}>
+          确定
+        </Button>
+      </div>
+    )
+  },
+})

+ 15 - 0
src/subpages/colexiu/plugins/toggleMusicSheet/index.module.less

@@ -0,0 +1,15 @@
+.iconToggle {
+    position: fixed;
+    left: 0;
+    bottom: 20%;
+    transform: scaleX(-1);
+    z-index: 10;
+    margin: 0;
+    background: rgba(0, 0, 0, 0.24);
+    border-radius: 5px 0px 0px 5px;
+    padding: 7px 3px;
+}
+.popup{
+    border-radius: 4px;
+    overflow: hidden;
+}

+ 73 - 0
src/subpages/colexiu/plugins/toggleMusicSheet/index.tsx

@@ -0,0 +1,73 @@
+import { computed, defineComponent, reactive } from 'vue'
+import styles from './index.module.less'
+import { Icon, Popup } from 'vant'
+import ChoosePartName from './choosePartName'
+import state from '/src/pages/detail/state'
+import runtime, * as RuntimeUtils from '/src/pages/detail/runtime'
+import qs from 'query-string'
+import { useOriginSearch } from '../../uses'
+import { getInstrumentName } from '../../helpers/instruments'
+
+export default defineComponent({
+  name: 'ToggleMusicSheet',
+  setup() {
+    const search = useOriginSearch()
+    const musicSheet = reactive({
+      show: false,
+    })
+    const partListNames = computed(() => {
+      const partList = state.activeDetail?.background || []
+      return partList.map((item: any, index: number) => {
+        const instrumentName = getInstrumentName(item.track)
+        return {
+          text: item.track + (instrumentName ? `(${instrumentName})` : ''),
+          value: index,
+        }
+      })
+    })
+
+    const switchMusic = (index: number) => {
+        // 暂停播放
+        RuntimeUtils.pause()
+        // 销毁播放器
+        postMessage({
+          api: 'cloudDestroy'
+        })
+        postMessage({
+          api: 'cloudLoading',
+          content: {
+            show: true,
+            type: 'fullscreen',
+          },
+        })
+        const _url =
+          location.origin +
+          location.pathname +
+          '?' +
+          qs.stringify({
+            ...search,
+            behaviorId: sessionStorage.getItem('behaviorId') || '',
+            _t: new Date().valueOf(),
+            "part-index": index,
+          })
+        console.log( _url)
+        location.href = _url
+      }
+
+    return () => (
+      <>
+        <div style={{display: runtime.playState == 'play' ? 'none' : ''}} class={styles.iconToggle} onClick={() => (musicSheet.show = true)}>
+          <Icon size="20px" color='#fff' name="exchange" />
+        </div>
+        <Popup class={styles.popup} v-model:show={musicSheet.show}>
+          <ChoosePartName partIndex={state.partIndex || 0} partListNames={partListNames.value} onClose={(value) => {
+            musicSheet.show = false
+            if (value !== undefined) {
+                switchMusic(value)
+            }
+          }} />
+        </Popup>
+      </>
+    )
+  },
+})