moveable.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import { ObjectDirective } from 'vue';
  2. import { throttle } from 'lodash-es';
  3. export const bindMoveTool = (el: HTMLElement, binding) => {
  4. const initScale = binding.value ? binding.value : 1;
  5. const targetkey = binding.arg ? Number(binding.arg) : 0;
  6. const transInfo = {
  7. zoom: initScale,
  8. toMove: false,
  9. toScale: false,
  10. transOriginX: 50,
  11. transOriginY: 50,
  12. translateX: 0,
  13. translateY: 0,
  14. distance: 1,
  15. mouseInit: { x: 0, y: 0 },
  16. curMousePos: { x: 0, y: 0 },
  17. };
  18. const setBgStyle = () => {
  19. el.setAttribute(
  20. 'style',
  21. `transform-origin: ${transInfo.transOriginX}% ${transInfo.transOriginY}%; transform: translate(${transInfo.translateX}px, ${transInfo.translateY}px) scale(${transInfo.zoom})`,
  22. );
  23. };
  24. const calcTransOrigin = (mouseX: number, mouseY: number) => {
  25. const mapBgInfo = el.getBoundingClientRect();
  26. if (transInfo.zoom !== initScale) {
  27. transInfo.translateX += (1 - 1 / transInfo.zoom) * (mouseX - transInfo.mouseInit.x);
  28. transInfo.translateY += (1 - 1 / transInfo.zoom) * (mouseY - transInfo.mouseInit.y);
  29. }
  30. transInfo.transOriginX = ((mouseX - mapBgInfo!.left!) / mapBgInfo!.width!) * 100;
  31. transInfo.transOriginY = ((mouseY - mapBgInfo!.top!) / mapBgInfo!.height!) * 100;
  32. transInfo.mouseInit = { x: mouseX, y: mouseY };
  33. };
  34. const scaleProcess = (e) => {
  35. if (e.wheelDelta > 0) {
  36. const newZoom = transInfo.zoom + 0.2;
  37. if (newZoom <= 10) {
  38. calcTransOrigin(e.clientX, e.clientY);
  39. transInfo.zoom = newZoom;
  40. }
  41. } else if (e.wheelDelta < 0) {
  42. const newZoom = transInfo.zoom - 0.2;
  43. if (newZoom >= 0.2) {
  44. calcTransOrigin(e.clientX, e.clientY);
  45. transInfo.zoom = newZoom;
  46. }
  47. }
  48. setBgStyle();
  49. };
  50. const throttleScale = throttle(scaleProcess, 200);
  51. const handleScale = (e) => {
  52. if (e.ctrlKey) {
  53. e.preventDefault();
  54. throttleScale(e);
  55. // if (e.wheelDelta > 0) {
  56. // const newZoom = transInfo.zoom + 0.2;
  57. // if (newZoom <= 10) {
  58. // calcTransOrigin(e.clientX, e.clientY);
  59. // transInfo.zoom = newZoom;
  60. // }
  61. // } else if (e.wheelDelta < 0) {
  62. // const newZoom = transInfo.zoom - 0.2;
  63. // if (newZoom >= 0.2) {
  64. // calcTransOrigin(e.clientX, e.clientY);
  65. // transInfo.zoom = newZoom;
  66. // }
  67. // }
  68. // setBgStyle();
  69. }
  70. };
  71. const handleMouseDown = (e) => {
  72. if (e.button === targetkey) {
  73. transInfo.toMove = true;
  74. transInfo.curMousePos = { x: e.clientX, y: e.clientY };
  75. }
  76. };
  77. const handleMouseMove = (e) => {
  78. if (transInfo.toMove) {
  79. transInfo.translateX += e.clientX - transInfo.curMousePos.x;
  80. transInfo.translateY += e.clientY - transInfo.curMousePos.y;
  81. transInfo.mouseInit = {
  82. x: transInfo.mouseInit.x + (e.clientX - transInfo.curMousePos.x),
  83. y: transInfo.mouseInit.y + (e.clientY - transInfo.curMousePos.y),
  84. };
  85. }
  86. transInfo.curMousePos = { x: e.clientX, y: e.clientY };
  87. setBgStyle();
  88. };
  89. const handleMouseUp = () => {
  90. transInfo.toMove = false;
  91. transInfo.curMousePos = { x: 0, y: 0 };
  92. };
  93. // const calcMobileTransOrigin = (mouseX: number, mouseY: number) => {
  94. // const mapBgInfo = el.getBoundingClientRect();
  95. // if (transInfo.zoom !== initScale) {
  96. // transInfo.translateX += (1 - 1 / transInfo.zoom) * (mouseX - transInfo.mouseInit.x);
  97. // transInfo.translateY += (1 - 1 / transInfo.zoom) * (mouseY - transInfo.mouseInit.y);
  98. // }
  99. // transInfo.transOriginX = ((mouseX - mapBgInfo!.top!) / mapBgInfo!.height!) * 100;
  100. // transInfo.transOriginY = (1 - (mouseY - mapBgInfo!.left!) / mapBgInfo!.width!) * 100;
  101. // transInfo.mouseInit = { x: mouseX, y: mouseY };
  102. // };
  103. // const handleTouchStart = (e) => {
  104. // const touches = e.touches;
  105. // if (touches.length == 1) {
  106. // transInfo.toMove = true;
  107. // transInfo.toScale = false;
  108. // transInfo.curMousePos = { x: touches[0].pageY, y: touches[0].pageX };
  109. // } else if (touches.length == 2) {
  110. // transInfo.toMove = false;
  111. // transInfo.toScale = true;
  112. // // 计算中点
  113. // const midX = (touches[0].pageY + touches[1].pageY) / 2;
  114. // const midY = (touches[0].pageX + touches[1].pageX) / 2;
  115. // calcMobileTransOrigin(midX, midY);
  116. // // 计算距离
  117. // const disX = Math.abs(touches[0].pageY - touches[1].pageY);
  118. // const disY = Math.abs(touches[0].pageX - touches[1].pageX);
  119. // transInfo.distance = Math.sqrt(disX * disX + disY * disY);
  120. // }
  121. // };
  122. // const handleTouchMove = (e) => {
  123. // const touches = e.touches;
  124. // if (touches.length == 1 && transInfo.toMove) {
  125. // transInfo.toMove = true;
  126. // transInfo.toScale = false;
  127. // transInfo.translateX += touches[0].pageY - transInfo.curMousePos.x;
  128. // transInfo.translateY -= touches[0].pageX - transInfo.curMousePos.y;
  129. // transInfo.mouseInit = {
  130. // x: transInfo.mouseInit.x + (touches[0].pageY - transInfo.curMousePos.x),
  131. // y: transInfo.mouseInit.y - (touches[0].pageX - transInfo.curMousePos.y),
  132. // };
  133. // transInfo.curMousePos = { x: touches[0].pageY, y: touches[0].pageX };
  134. // setBgStyle();
  135. // } else if (touches.length == 2 && transInfo.toScale) {
  136. // e.preventDefault();
  137. // transInfo.toMove = false;
  138. // transInfo.toScale = true;
  139. // // 计算距离
  140. // const disX = Math.abs(touches[0].pageY - touches[1].pageY);
  141. // const disY = Math.abs(touches[0].pageX - touches[1].pageX);
  142. // const curDistance = Math.sqrt(disX * disX + disY * disY);
  143. // transInfo.zoom = transInfo.zoom * (curDistance / transInfo.distance);
  144. // setBgStyle();
  145. // transInfo.distance = curDistance;
  146. // }
  147. // };
  148. // const handleTouchEnd = () => {
  149. // transInfo.toMove = false;
  150. // transInfo.toScale = false;
  151. // transInfo.distance = 1;
  152. // transInfo.curMousePos = { x: 0, y: 0 };
  153. // };
  154. setBgStyle();
  155. el.addEventListener('mousewheel', handleScale);
  156. el.addEventListener('mousedown', handleMouseDown);
  157. el.addEventListener('mousemove', handleMouseMove);
  158. el.addEventListener('mouseup', handleMouseUp);
  159. };
  160. export const moveable: ObjectDirective = {
  161. mounted(el: HTMLElement, binding) {
  162. bindMoveTool(el, binding);
  163. },
  164. };