Ver código fonte

支持鼠标操作拖拽单行谱面

黄琪勇 11 meses atrás
pai
commit
657683ec77

+ 71 - 0
src/view/music-score/HorizontalDragScroll.ts

@@ -0,0 +1,71 @@
+import state from "/src/state"
+interface HorizontalDragScrollOptions {
+   speed?: number // 滚动速度
+   cursorGrab?: string // 抓取前的鼠标样式
+}
+
+class HorizontalDragScroll {
+    private container: HTMLElement
+    private options: HorizontalDragScrollOptions
+    private isDown: boolean
+    private startX: number
+    private scrollLeft: number
+
+    constructor(container: HTMLElement, options: HorizontalDragScrollOptions = {}) {
+        this.container = container
+        this.options = {
+            speed: options.speed || 2,
+            cursorGrab: options.cursorGrab || "grab",
+        }
+
+        this.isDown = false
+        this.startX = 0
+        this.scrollLeft = 0
+
+        this.init()
+    }
+
+    private init() {
+        this.container.style.cursor = this.options.cursorGrab || "grab"
+
+        this.container.addEventListener("mousedown", this.onMouseDown.bind(this))
+        this.container.addEventListener("mouseleave", this.onMouseLeave.bind(this))
+        this.container.addEventListener("mouseup", this.onMouseUp.bind(this))
+        this.container.addEventListener("mousemove", this.onMouseMove.bind(this))
+    }
+
+    private onMouseDown(e: MouseEvent) {
+        // 当播放中或者不是一行谱模式  不起作用
+        if(state.playState === "play" || !state.isSingleLine) {
+            return
+        }
+        this.isDown = true
+        this.startX = e.pageX - this.container.offsetLeft
+        this.scrollLeft = this.container.scrollLeft
+    }
+
+    private onMouseLeave() {
+        this.isDown = false
+    }
+
+    private onMouseUp() {
+        this.isDown = false
+    }
+
+    private onMouseMove(e: MouseEvent) {
+        if (!this.isDown) return
+        e.preventDefault()
+        const x = e.pageX - this.container.offsetLeft
+        const walk = (x - this.startX) * (this.options.speed || 2)
+        this.container.scrollLeft = this.scrollLeft - walk
+    }
+
+    public destroy() {
+        this.container.removeEventListener("mousedown", this.onMouseDown.bind(this))
+        this.container.removeEventListener("mouseleave", this.onMouseLeave.bind(this))
+        this.container.removeEventListener("mouseup", this.onMouseUp.bind(this))
+        this.container.removeEventListener("mousemove", this.onMouseMove.bind(this))
+    }
+    }
+
+export default HorizontalDragScroll

+ 3 - 0
src/view/music-score/index.module.less

@@ -83,6 +83,9 @@
 .notTouch{
     touch-action: none;
 }
+.pcCursorGrab{
+    cursor: initial !important;
+}
 .inGradualRange{
    :global{
         #cursorImg-0{

+ 14 - 3
src/view/music-score/index.tsx

@@ -1,4 +1,4 @@
-import { computed, defineComponent, onMounted, reactive, ref } from "vue";
+import { computed, defineComponent, onMounted, reactive, ref, onUnmounted } from "vue";
 import { formatXML, onlyVisible } from "../../helpers/formateMusic";
 // // @ts-ignore
 import { OpenSheetMusicDisplay } from "/osmd-extended/src";
@@ -12,6 +12,7 @@ import { setGlobalData } from "/src/utils";
 import Loading from "/src/view/audio-list/loading"
 import { storeData } from "/src/store";
 import { isLoadingCss } from "/src/page-instrument/view-detail/loadingCss"
+import HorizontalDragScroll from './HorizontalDragScroll';
 
 export const musicRenderTypeKey = "musicRenderType";
 let osmd: any = null;
@@ -174,14 +175,22 @@ export default defineComponent({
 			musicData.containerWidth = document.getElementById("musicAndSelection")?.offsetWidth || 625;
 			// console.log(musicData.containerWidth)
 		};
+		let horizontalDragScroll:HorizontalDragScroll | null
 		onMounted(async () => {
 			getContainerWidth();
 			//setRenderType();
 			await getXML();
 			await init();
 			musicData.isRenderLoading = false;
+			// pc 端支持 拖动滚动
+			if(state.platform === "PC"){
+				const container = document.querySelector('#musicAndSelection') as HTMLElement;
+				horizontalDragScroll = new HorizontalDragScroll(container);
+			}
 		});
-
+		onUnmounted(() => {
+			horizontalDragScroll?.destroy()
+		})
 		const isInTheGradualRange = computed(() => {
 			let result: boolean = false;
 			const activeMeasureIndex = state.times[state.activeNoteIndex]?.measureListIndex || -1;
@@ -236,7 +245,9 @@ export default defineComponent({
 					state.musicRenderType == EnumMusicRenderType.staff ? "staff" : "jianpuTone",
 					state.isSingleLine && "singleLineMusicBox",
 					(!state.isCreateImg && !state.isPreView && state.musicRenderType === EnumMusicRenderType.staff) ? "blueMusicXml" : "",
-					state.isSingleLine && state.playState ==="play" && styles.notTouch
+					state.isSingleLine && state.playState ==="play" && styles.notTouch,
+					!state.isSingleLine && state.platform === "PC" &&  styles.pcCursorGrab
+
 				]}
 			>
 				{slots.default?.()}