use-layer.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import { DC, EntityShape } from "@/deconstruction";
  2. import {
  3. computed,
  4. onUnmounted,
  5. ref,
  6. Ref,
  7. toRaw,
  8. watch,
  9. watchEffect,
  10. } from "vue";
  11. import { DrawItem } from "../components";
  12. import { useStore } from "../store";
  13. import { installGlobalVar, useStage } from "./use-global-vars";
  14. import { Layer } from "konva/lib/Layer";
  15. import { useMouseShapeStatus } from "./use-mouse-status";
  16. // const useRefreshCount = installGlobalVar(() => ref(0));
  17. // const useRefresh = () => {
  18. // useRefreshCount
  19. // }
  20. export const useTempLayer = () => {
  21. const stage = useStage();
  22. return computed(() => stage.value?.getNode().find<Layer>("#temp")[0]);
  23. };
  24. export const useFormalLayer = () => {
  25. const stage = useStage();
  26. return computed(() => stage.value?.getNode().find<Layer>("#formal")[0]);
  27. };
  28. export const useHelperLayer = () => {
  29. const stage = useStage();
  30. return computed(() => stage.value?.getNode().find<Layer>("#helper")[0]);
  31. };
  32. export const useMigrateLayer = (shape: Ref<DC<EntityShape> | undefined>) => {
  33. const formal = useFormalLayer();
  34. const zIndexs = useZIndexsManage();
  35. let rawLayer: Layer;
  36. let toLayer: Layer;
  37. const recovery = () => {
  38. const $shape = shape.value?.getNode();
  39. if (rawLayer && $shape) {
  40. $shape.remove();
  41. rawLayer.add($shape);
  42. if (import.meta.env.DEV) {
  43. setTimeout(() => {
  44. console.log(
  45. `recovery raw:${rawLayer.id()} ${rawLayer.children.length} to:${toLayer.id()} ${toLayer.children.length}`,
  46. );
  47. })
  48. }
  49. if (toRaw(formal.value) === toRaw(rawLayer) && zIndexs.get($shape)) {
  50. zIndexs.refresh();
  51. }
  52. }
  53. };
  54. const migrate = (to: Layer) => {
  55. if (!shape.value) throw "shape不存在";
  56. const $shape = shape.value.getNode();
  57. rawLayer = $shape.getLayer()!;
  58. toLayer = to;
  59. $shape.remove();
  60. to.add($shape);
  61. if (import.meta.env.DEV) {
  62. console.log(
  63. `migrate raw:${rawLayer.id()} ${rawLayer.children.length} to:${toLayer.id()} ${toLayer.children.length}`,
  64. );
  65. }
  66. };
  67. return [migrate, recovery] as const;
  68. };
  69. export const useMouseMigrateTempLayer = (
  70. shape: Ref<DC<EntityShape> | undefined>
  71. ) => {
  72. const status = useMouseShapeStatus(shape);
  73. const tempLayer = useTempLayer();
  74. const [migrate, recovery] = useMigrateLayer(shape);
  75. const isMigrate = computed(() => status.value.active || status.value.hover);
  76. // 鼠标状态改变则迁移图层
  77. watch(
  78. isMigrate,
  79. (isMigrate, _, onCleanup) => {
  80. if (isMigrate && tempLayer.value) {
  81. migrate(tempLayer.value);
  82. onCleanup(recovery);
  83. }
  84. },
  85. { flush: 'sync' }
  86. );
  87. };
  88. const useCurrentStaticZIndex = installGlobalVar(() => ref(0));
  89. export const useStaticZIndex = (refNum = 1) => {
  90. const current = useCurrentStaticZIndex();
  91. let isDestory = false;
  92. const destroy = () => {
  93. if (!isDestory) {
  94. current.value -= refNum;
  95. isDestory = true;
  96. }
  97. };
  98. onUnmounted(destroy);
  99. const result = new Array(refNum).fill(0).map((_, i) => current.value + i + 1);
  100. current.value += refNum;
  101. return result;
  102. };
  103. const useZIndexsManage = installGlobalVar(() => {
  104. const store = useStore();
  105. const map = ref(new Map<EntityShape, DrawItem>());
  106. const current = useCurrentStaticZIndex();
  107. const formal = useFormalLayer();
  108. const sortItems = computed(() => {
  109. const items = Array.from(map.value.values());
  110. return store.getItemsZIndex(items);
  111. })
  112. const setZIndexs = () => {
  113. const shapes = Array.from(map.value.keys());
  114. const raws = Array.from(map.value.values());
  115. let start = current.value;
  116. sortItems.value.forEach((item) => {
  117. const rawNdx = raws.findIndex((raw) => raw === item);
  118. const shape = shapes[rawNdx];
  119. const layer = shape.getLayer();
  120. if (toRaw(layer) !== toRaw(formal.value)) return -1;
  121. shape.zIndex(start++);
  122. });
  123. };
  124. watch(sortItems, setZIndexs)
  125. return {
  126. set(shape: EntityShape, item: DrawItem) {
  127. map.value.set(shape, item);
  128. },
  129. del(shape: EntityShape) {
  130. map.value.delete(shape);
  131. },
  132. get(shape: EntityShape) {
  133. return map.value.get(shape);
  134. },
  135. refresh: setZIndexs,
  136. };
  137. });
  138. export const useZIndex = (
  139. shape: Ref<DC<EntityShape> | undefined>,
  140. atData: Ref<DrawItem>
  141. ) => {
  142. const zIndexs = useZIndexsManage();
  143. watch(shape, (shape, _, onCleanup) => {
  144. const $shape = shape?.getNode();
  145. if ($shape) {
  146. watchEffect(() => {
  147. zIndexs.set($shape, atData.value);
  148. });
  149. onCleanup(() => {
  150. zIndexs.del($shape);
  151. });
  152. }
  153. });
  154. };