use-viewer.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import { Viewer } from "../viewer.ts";
  2. import { computed, ref, watch, watchEffect } from "vue";
  3. import { dragListener, scaleListener } from "../../utils/event.ts";
  4. import { globalWatch, installGlobalVar, useStage } from "./use-global-vars.ts";
  5. import { useCan } from "./use-status";
  6. import { mergeFuns } from "../../utils/shared.ts";
  7. import { Transform } from "konva/lib/Util";
  8. import { lineLen } from "@/utils/math.ts";
  9. import { useResize } from "./use-event.ts";
  10. import { FixScreen, getFixPosition } from "@/utils/bound.ts";
  11. import { useFormalLayer } from "./use-layer.ts";
  12. import { Group } from "konva/lib/Group";
  13. import { DataGroupId } from "@/constant/index.ts";
  14. import { IRect } from "konva/lib/types";
  15. export const useViewer = installGlobalVar(() => {
  16. const stage = useStage();
  17. const viewer = new Viewer();
  18. const can = useCan();
  19. const size = useResize();
  20. const transform = ref(new Transform());
  21. const disabled = ref(false)
  22. const sizeMat = ref<Transform | null>(null);
  23. const init = (dom: HTMLDivElement) => {
  24. let downEv: PointerEvent;
  25. const onDestroy = mergeFuns(
  26. dragListener(dom, {
  27. down(_, ev) {
  28. downEv = ev;
  29. },
  30. move: ({ end, prev, ev }) => {
  31. if (downEv.button === 2 || disabled.value) return;
  32. if (can.viewMode) {
  33. viewer.movePixel({ x: end.x - prev.x, y: end.y - prev.y });
  34. }
  35. },
  36. notPrevent: true,
  37. }),
  38. scaleListener(dom, (info) => {
  39. if (can.viewMode || disabled.value) {
  40. viewer.scalePixel(info.center, info.scale);
  41. }
  42. }),
  43. watchEffect(() => {
  44. size.value && viewer.setSize(size.value);
  45. })
  46. );
  47. viewer.bus.on("transformChange", (newTransform) => {
  48. transform.value = newTransform;
  49. });
  50. viewer.bus.on("viewSizeChange", () => {
  51. sizeMat.value = viewer.sizeMat;
  52. });
  53. transform.value = viewer.transform;
  54. sizeMat.value = viewer.sizeMat;
  55. return onDestroy;
  56. };
  57. return {
  58. var: {
  59. transform: transform,
  60. viewer,
  61. sizeMat,
  62. disabled
  63. },
  64. onDestroy: globalWatch(
  65. () => can.viewMouseReact,
  66. (can, _, onCleanup) => {
  67. if (can) {
  68. const dom = stage.value!.getNode().container();
  69. onCleanup(init(dom));
  70. }
  71. },
  72. { immediate: true }
  73. ),
  74. };
  75. }, Symbol("viewer"));
  76. export const useViewerTransform = installGlobalVar(() => {
  77. const viewer = useViewer();
  78. return viewer.transform;
  79. }, Symbol("viewTransform"));
  80. export const useViewerTransformConfig = () => {
  81. const transform = useViewerTransform();
  82. return computed(() => transform.value.decompose());
  83. };
  84. export const useViewerInvertTransform = () => {
  85. const transform = useViewerTransform();
  86. return computed(() => transform.value.copy().invert());
  87. };
  88. export const useViewerInvertTransformConfig = () => {
  89. const transform = useViewerInvertTransform();
  90. return computed(() => transform.value.decompose());
  91. };
  92. export const useUnitTransform = installGlobalVar(() => {
  93. const transform = useViewerTransform();
  94. const invTransform = useViewerInvertTransform();
  95. return {
  96. getPixel(real: number) {
  97. return lineLen(
  98. invTransform.value.point({ x: real, y: 0 }),
  99. invTransform.value.point({ x: 0, y: 0 })
  100. );
  101. },
  102. getReal(pixel: number) {
  103. return lineLen(
  104. transform.value.point({ x: pixel, y: 0 }),
  105. transform.value.point({ x: 0, y: 0 })
  106. );
  107. },
  108. };
  109. }, Symbol("unitTransform"));
  110. export const useCacheUnitTransform = installGlobalVar(() => {
  111. const unitTransform = useUnitTransform();
  112. const transform = useViewerTransform();
  113. const invTransform = useViewerInvertTransform();
  114. let pixelCache: Record<string, number> = {};
  115. let realCache: Record<string, number> = {};
  116. watch(transform, () => {
  117. pixelCache = {};
  118. });
  119. watch(invTransform, () => {
  120. realCache = {};
  121. });
  122. return {
  123. getPixel(real: number) {
  124. if (real in pixelCache) {
  125. return pixelCache[real];
  126. } else {
  127. return (pixelCache[real] = unitTransform.getPixel(real));
  128. }
  129. },
  130. getReal(pixel: number) {
  131. if (pixel in realCache) {
  132. return realCache[pixel];
  133. } else {
  134. return (pixelCache[pixel] = unitTransform.getReal(pixel));
  135. }
  136. },
  137. };
  138. }, Symbol("cacheUnitTransform"));
  139. export const useViewSize = installGlobalVar(() => {
  140. const size = useResize();
  141. const { sizeMat, viewer } = useViewer();
  142. return computed(() => {
  143. if (sizeMat.value) {
  144. return viewer.viewSize!;
  145. } else {
  146. return size.value;
  147. }
  148. });
  149. });
  150. export const useViewBoxPixelRect = installGlobalVar(() => {
  151. const size = useResize();
  152. const { sizeMat, viewer, transform } = useViewer();
  153. return computed(() => {
  154. if (sizeMat.value) {
  155. const size = viewer.viewSize!;
  156. const p1 = transform.value.point({ x: 0, y: 0 });
  157. const p2 = transform.value.point({ x: size.width, y: size.height });
  158. return {
  159. ...p1,
  160. width: p2.x - p1.x,
  161. height: p2.y - p1.y,
  162. };
  163. } else {
  164. return {
  165. x: 0,
  166. y: 0,
  167. width: 100,
  168. height: 100,
  169. ...size.value,
  170. };
  171. }
  172. });
  173. });
  174. export const useGetViewBoxPositionPixel = () => {
  175. const size = useResize();
  176. const { sizeMat, viewer, transform } = useViewer();
  177. return (fixPosition: FixScreen, selfSize = { width: 1, height: 1 }) => {
  178. if (sizeMat.value) {
  179. const size = viewer.viewSize!;
  180. const pos = getFixPosition(fixPosition, selfSize, size);
  181. return transform.value.point(pos);
  182. } else {
  183. return getFixPosition(
  184. fixPosition,
  185. selfSize,
  186. size.value || { width: 100, height: 100 }
  187. );
  188. }
  189. };
  190. };
  191. export const useSetViewport = () => {
  192. const formalLayer = useFormalLayer();
  193. const { viewer } = useViewer();
  194. const initViewport = () => {
  195. const rect = formalLayer
  196. .value!.findOne<Group>("#" + DataGroupId)!
  197. .getClientRect();
  198. rect.width > 0 && rect.height > 0 && setViewport(rect);
  199. };
  200. const setViewport = (rect: IRect, padding = 20, isPixel = true) => {
  201. const invMat = viewer.transform.invert();
  202. const lt = isPixel ? invMat.point(rect) : rect;
  203. const rb = isPixel
  204. ? invMat.point({
  205. x: rect.x + rect.width,
  206. y: rect.y + rect.height,
  207. })
  208. : {
  209. x: rect.x + rect.width,
  210. y: rect.y + rect.height,
  211. };
  212. viewer.setBound({
  213. targetBound: {
  214. ...lt,
  215. width: rb.x - lt.x,
  216. height: rb.y - lt.y,
  217. },
  218. padding,
  219. });
  220. };
  221. return {
  222. initViewport,
  223. setViewport,
  224. };
  225. };