import { Viewer } from "../viewer.ts"; import { computed, nextTick, ref, watch, watchEffect } from "vue"; import { dragListener, scaleListener } from "../../utils/event.ts"; import { globalWatch, installGlobalVar, useStage } from "./use-global-vars.ts"; import { useCan } from "./use-status"; import { mergeFuns } from "../../utils/shared.ts"; import { Transform } from "konva/lib/Util"; import { lineLen } from "@/utils/math.ts"; import { useResize } from "./use-event.ts"; import { FixScreen, getFixPosition } from "@/utils/bound.ts"; import { useFormalLayer } from "./use-layer.ts"; import { Group } from "konva/lib/Group"; import { DataGroupId } from "@/constant/index.ts"; import { IRect } from "konva/lib/types"; import { MathUtils } from "three"; export const useViewer = installGlobalVar(() => { const stage = useStage(); const viewer = new Viewer(); const can = useCan(); const size = useResize(); const transform = ref(new Transform()); const disabled = ref(false); const sizeMat = ref(null); const init = (dom: HTMLDivElement) => { let downEv: PointerEvent; const onDestroy = mergeFuns( dragListener(dom, { down(_, ev) { downEv = ev; }, move: ({ end, prev, ev }) => { if (downEv.button === 2 || disabled.value) return; if (can.viewMode) { viewer.movePixel({ x: end.x - prev.x, y: end.y - prev.y }); } }, notPrevent: true, }), scaleListener(dom, (info) => { if (can.viewMode || disabled.value) { viewer.scalePixel(info.center, info.scale); } }), watchEffect(() => { size.value && viewer.setSize(size.value); }) ); viewer.bus.on("transformChange", (newTransform) => { transform.value = newTransform; }); viewer.bus.on("viewSizeChange", () => { sizeMat.value = viewer.sizeMat; }); transform.value = viewer.transform; sizeMat.value = viewer.sizeMat; return onDestroy; }; return { var: { transform: transform, viewer, sizeMat, disabled, }, onDestroy: globalWatch( () => can.viewMouseReact, (can, _, onCleanup) => { if (can) { const dom = stage.value!.getNode().container(); onCleanup(init(dom)); } }, { immediate: true } ), }; }, Symbol("viewer")); export const useViewerTransform = installGlobalVar(() => { const viewer = useViewer(); return viewer.transform; }, Symbol("viewTransform")); export const useViewerTransformConfig = () => { const transform = useViewerTransform(); return computed(() => transform.value.decompose()); }; export const useViewerInvertTransform = () => { const transform = useViewerTransform(); return computed(() => transform.value.copy().invert()); }; export const useViewerInvertTransformConfig = () => { const transform = useViewerInvertTransform(); return computed(() => transform.value.decompose()); }; export const useUnitTransform = installGlobalVar(() => { const transform = useViewerTransform(); const invTransform = useViewerInvertTransform(); return { getPixel(real: number) { return lineLen( invTransform.value.point({ x: real, y: 0 }), invTransform.value.point({ x: 0, y: 0 }) ); }, getReal(pixel: number) { return lineLen( transform.value.point({ x: pixel, y: 0 }), transform.value.point({ x: 0, y: 0 }) ); }, }; }, Symbol("unitTransform")); export const useCacheUnitTransform = installGlobalVar(() => { const unitTransform = useUnitTransform(); const transform = useViewerTransform(); const invTransform = useViewerInvertTransform(); let pixelCache: Record = {}; let realCache: Record = {}; watch(transform, () => { pixelCache = {}; }); watch(invTransform, () => { realCache = {}; }); return { getPixel(real: number) { if (real in pixelCache) { return pixelCache[real]; } else { return (pixelCache[real] = unitTransform.getPixel(real)); } }, getReal(pixel: number) { if (pixel in realCache) { return realCache[pixel]; } else { return (pixelCache[pixel] = unitTransform.getReal(pixel)); } }, }; }, Symbol("cacheUnitTransform")); export const useViewSize = installGlobalVar(() => { const size = useResize(); const { sizeMat, viewer } = useViewer(); return computed(() => { if (sizeMat.value) { return viewer.viewSize!; } else { return size.value; } }); }); export const useViewBoxPixelRect = installGlobalVar(() => { const size = useResize(); const { sizeMat, viewer, transform } = useViewer(); return computed(() => { if (sizeMat.value) { const size = viewer.viewSize!; const p1 = transform.value.point({ x: 0, y: 0 }); const p2 = transform.value.point({ x: size.width, y: size.height }); return { ...p1, width: p2.x - p1.x, height: p2.y - p1.y, }; } else { return { x: 0, y: 0, width: 100, height: 100, ...size.value, }; } }); }); export const useGetViewBoxPositionPixel = () => { const size = useResize(); const { sizeMat, viewer, transform } = useViewer(); return (fixPosition: FixScreen, selfSize = { width: 1, height: 1 }) => { if (sizeMat.value) { const size = viewer.viewSize!; const pos = getFixPosition(fixPosition, selfSize, size); return transform.value.point(pos); } else { return getFixPosition( fixPosition, selfSize, size.value || { width: 100, height: 100 } ); } }; }; export const useSetViewport = () => { const formalLayer = useFormalLayer(); const { viewer } = useViewer(); const config = useViewerTransformConfig(); const initViewport = () => { const rect = formalLayer .value!.findOne("#" + DataGroupId)! .getClientRect(); if (!(rect.width > 0 && rect.height > 0)) return; const center = { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2, }; const mat = new Transform() .translate(center.x, center.y) .rotate(MathUtils.degToRad(config.value.rotation)) .translate(-center.x, -center.y); const start = mat.point({x: rect.x, y: rect.y}); const end = mat.point({ x: rect.x + rect.width, y: rect.y + rect.height, }); let width = end.x - start.x; let height = end.y - start.y; setViewport({ ...start, width, height }); }; const setViewport = (rect: IRect, padding = 20, isPixel = true) => { const invMat = viewer.transform.invert(); const lt = isPixel ? invMat.point(rect) : rect; const rb = isPixel ? invMat.point({ x: rect.x + rect.width, y: rect.y + rect.height, }) : { x: rect.x + rect.width, y: rect.y + rect.height, }; viewer.setBound({ targetBound: { ...lt, width: rb.x - lt.x, height: rb.y - lt.y, }, padding, }); }; return { initViewport, setViewport, }; };