import { ObjectDirective } from 'vue'; import { throttle } from 'lodash-es'; export const bindMoveTool = (el: HTMLElement, binding) => { const initScale = binding.value ? binding.value : 1; const targetkey = binding.arg ? Number(binding.arg) : 0; const transInfo = { zoom: initScale, toMove: false, toScale: false, transOriginX: 50, transOriginY: 50, translateX: 0, translateY: 0, distance: 1, mouseInit: { x: 0, y: 0 }, curMousePos: { x: 0, y: 0 }, }; const setBgStyle = () => { el.setAttribute( 'style', `transform-origin: ${transInfo.transOriginX}% ${transInfo.transOriginY}%; transform: translate(${transInfo.translateX}px, ${transInfo.translateY}px) scale(${transInfo.zoom})`, ); }; const calcTransOrigin = (mouseX: number, mouseY: number) => { const mapBgInfo = el.getBoundingClientRect(); if (transInfo.zoom !== initScale) { transInfo.translateX += (1 - 1 / transInfo.zoom) * (mouseX - transInfo.mouseInit.x); transInfo.translateY += (1 - 1 / transInfo.zoom) * (mouseY - transInfo.mouseInit.y); } transInfo.transOriginX = ((mouseX - mapBgInfo!.left!) / mapBgInfo!.width!) * 100; transInfo.transOriginY = ((mouseY - mapBgInfo!.top!) / mapBgInfo!.height!) * 100; transInfo.mouseInit = { x: mouseX, y: mouseY }; }; const scaleProcess = (e) => { if (e.wheelDelta > 0) { const newZoom = transInfo.zoom + 0.2; if (newZoom <= 10) { calcTransOrigin(e.clientX, e.clientY); transInfo.zoom = newZoom; } } else if (e.wheelDelta < 0) { const newZoom = transInfo.zoom - 0.2; if (newZoom >= 0.2) { calcTransOrigin(e.clientX, e.clientY); transInfo.zoom = newZoom; } } setBgStyle(); }; const throttleScale = throttle(scaleProcess, 200); const handleScale = (e) => { if (e.ctrlKey) { e.preventDefault(); throttleScale(e); // if (e.wheelDelta > 0) { // const newZoom = transInfo.zoom + 0.2; // if (newZoom <= 10) { // calcTransOrigin(e.clientX, e.clientY); // transInfo.zoom = newZoom; // } // } else if (e.wheelDelta < 0) { // const newZoom = transInfo.zoom - 0.2; // if (newZoom >= 0.2) { // calcTransOrigin(e.clientX, e.clientY); // transInfo.zoom = newZoom; // } // } // setBgStyle(); } }; const handleMouseDown = (e) => { if (e.button === targetkey) { transInfo.toMove = true; transInfo.curMousePos = { x: e.clientX, y: e.clientY }; } }; const handleMouseMove = (e) => { if (transInfo.toMove) { transInfo.translateX += e.clientX - transInfo.curMousePos.x; transInfo.translateY += e.clientY - transInfo.curMousePos.y; transInfo.mouseInit = { x: transInfo.mouseInit.x + (e.clientX - transInfo.curMousePos.x), y: transInfo.mouseInit.y + (e.clientY - transInfo.curMousePos.y), }; } transInfo.curMousePos = { x: e.clientX, y: e.clientY }; setBgStyle(); }; const handleMouseUp = () => { transInfo.toMove = false; transInfo.curMousePos = { x: 0, y: 0 }; }; // const calcMobileTransOrigin = (mouseX: number, mouseY: number) => { // const mapBgInfo = el.getBoundingClientRect(); // if (transInfo.zoom !== initScale) { // transInfo.translateX += (1 - 1 / transInfo.zoom) * (mouseX - transInfo.mouseInit.x); // transInfo.translateY += (1 - 1 / transInfo.zoom) * (mouseY - transInfo.mouseInit.y); // } // transInfo.transOriginX = ((mouseX - mapBgInfo!.top!) / mapBgInfo!.height!) * 100; // transInfo.transOriginY = (1 - (mouseY - mapBgInfo!.left!) / mapBgInfo!.width!) * 100; // transInfo.mouseInit = { x: mouseX, y: mouseY }; // }; // const handleTouchStart = (e) => { // const touches = e.touches; // if (touches.length == 1) { // transInfo.toMove = true; // transInfo.toScale = false; // transInfo.curMousePos = { x: touches[0].pageY, y: touches[0].pageX }; // } else if (touches.length == 2) { // transInfo.toMove = false; // transInfo.toScale = true; // // 计算中点 // const midX = (touches[0].pageY + touches[1].pageY) / 2; // const midY = (touches[0].pageX + touches[1].pageX) / 2; // calcMobileTransOrigin(midX, midY); // // 计算距离 // const disX = Math.abs(touches[0].pageY - touches[1].pageY); // const disY = Math.abs(touches[0].pageX - touches[1].pageX); // transInfo.distance = Math.sqrt(disX * disX + disY * disY); // } // }; // const handleTouchMove = (e) => { // const touches = e.touches; // if (touches.length == 1 && transInfo.toMove) { // transInfo.toMove = true; // transInfo.toScale = false; // transInfo.translateX += touches[0].pageY - transInfo.curMousePos.x; // transInfo.translateY -= touches[0].pageX - transInfo.curMousePos.y; // transInfo.mouseInit = { // x: transInfo.mouseInit.x + (touches[0].pageY - transInfo.curMousePos.x), // y: transInfo.mouseInit.y - (touches[0].pageX - transInfo.curMousePos.y), // }; // transInfo.curMousePos = { x: touches[0].pageY, y: touches[0].pageX }; // setBgStyle(); // } else if (touches.length == 2 && transInfo.toScale) { // e.preventDefault(); // transInfo.toMove = false; // transInfo.toScale = true; // // 计算距离 // const disX = Math.abs(touches[0].pageY - touches[1].pageY); // const disY = Math.abs(touches[0].pageX - touches[1].pageX); // const curDistance = Math.sqrt(disX * disX + disY * disY); // transInfo.zoom = transInfo.zoom * (curDistance / transInfo.distance); // setBgStyle(); // transInfo.distance = curDistance; // } // }; // const handleTouchEnd = () => { // transInfo.toMove = false; // transInfo.toScale = false; // transInfo.distance = 1; // transInfo.curMousePos = { x: 0, y: 0 }; // }; setBgStyle(); el.addEventListener('mousewheel', handleScale); el.addEventListener('mousedown', handleMouseDown); el.addEventListener('mousemove', handleMouseMove); el.addEventListener('mouseup', handleMouseUp); }; export const moveable: ObjectDirective = { mounted(el: HTMLElement, binding) { bindMoveTool(el, binding); }, };