back-grid.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <template>
  2. <v-group ref="grid" v-if="hLines && rect" :config="{ listening: false }">
  3. <template v-for="item in hLines">
  4. <v-line
  5. v-for="l in item.children"
  6. :config="{
  7. points: [rect[0].x, l, rect[1].x, l],
  8. ...style,
  9. strokeWidth: style.strokeWidth * 0.33,
  10. }"
  11. />
  12. </template>
  13. <template v-for="item in vLines">
  14. <v-line
  15. v-for="l in item.children"
  16. :config="{
  17. points: [l, rect[0].y, l, rect[1].y],
  18. ...style,
  19. strokeWidth: style.strokeWidth * 0.33,
  20. }"
  21. />
  22. </template>
  23. <v-line
  24. v-for="item in hLines"
  25. :config="{ points: [rect[0].x, item.dividing, rect[1].x, item.dividing], ...style }"
  26. />
  27. <v-line
  28. v-for="item in vLines"
  29. :config="{ points: [item.dividing, rect[0].y, item.dividing, rect[1].y], ...style }"
  30. />
  31. </v-group>
  32. </template>
  33. <script lang="ts" setup>
  34. import { computed, ref, watch } from "vue";
  35. import { useResize } from "../hook/use-event";
  36. import { useShapeStaticZindex } from "../hook/use-layer";
  37. import {
  38. useViewerInvertTransform,
  39. useViewerTransform,
  40. useViewerTransformConfig,
  41. } from "../hook/use-viewer";
  42. import { DC } from "@/deconstruction";
  43. import { Rect } from "konva/lib/shapes/Rect";
  44. import { lineLen } from "@/utils/math";
  45. import { debounce } from "@/utils/shared";
  46. const grid = ref<DC<Rect>>();
  47. useShapeStaticZindex(grid);
  48. const style = {
  49. stroke: "#ccc",
  50. strokeWidth: 3,
  51. opacity: 0.4,
  52. strokeScaleEnabled: false,
  53. };
  54. const pixelSize = useResize();
  55. const viewerInvertTransform = useViewerInvertTransform();
  56. // 真实rect
  57. const rect = computed(() => {
  58. if (!pixelSize.value) return null;
  59. const start = viewerInvertTransform.value.point({ x: 0, y: 0 });
  60. const end = viewerInvertTransform.value.point({
  61. x: pixelSize.value.width,
  62. y: pixelSize.value.height,
  63. });
  64. return [start, end];
  65. });
  66. // 看大格子的像素,100倍数
  67. const offsetUnit = 100;
  68. const minScalePixel = offsetUnit / 2;
  69. const viewerTransform = useViewerTransform();
  70. const viewerTransformConfig = useViewerTransformConfig();
  71. const offset = ref(offsetUnit);
  72. watch(
  73. () => `${viewerTransformConfig.value.scaleX},${viewerTransformConfig.value.scaleY}`,
  74. () => {
  75. offset.value = offsetUnit;
  76. const start = viewerTransform.value.point({ x: 0, y: 0 });
  77. let i = 0;
  78. while (true) {
  79. const end = viewerTransform.value.point({ x: offset.value, y: 0 });
  80. if (lineLen(start, end) >= minScalePixel) {
  81. break;
  82. }
  83. offset.value *= 2;
  84. i++;
  85. if (i > 200) {
  86. break;
  87. }
  88. }
  89. }
  90. );
  91. const getFinal = (val: number, isTop: boolean) => {
  92. let t = val / offset.value;
  93. t = isTop ? Math.floor(t) : Math.ceil(t);
  94. return offset.value * t;
  95. };
  96. type DireLine = {
  97. dividing: number;
  98. children: number[];
  99. };
  100. const getLines = (min: number, max: number) => {
  101. const isReverse = min > max;
  102. const start = getFinal(min, !isReverse);
  103. const end = getFinal(max, isReverse);
  104. const diff = isReverse ? -offset.value : offset.value;
  105. let current = start;
  106. const lines: DireLine[] = [];
  107. while (diff > 0 ? current <= end : current >= end) {
  108. const item: DireLine = {
  109. dividing: current,
  110. children: [],
  111. };
  112. const cOffset = ((diff > 0 ? -1 : 1) * offset.value) / 5;
  113. for (let i = 1; i < 5; i++) {
  114. item.children.push(current + cOffset * i);
  115. }
  116. lines.push(item);
  117. current += diff;
  118. }
  119. return lines;
  120. };
  121. const hLines = ref<DireLine[]>([]);
  122. const vLines = ref<DireLine[]>([]);
  123. watch(
  124. rect,
  125. debounce(() => {
  126. if (!rect.value) {
  127. hLines.value = [];
  128. vLines.value = [];
  129. } else {
  130. hLines.value = getLines(rect.value[0].y, rect.value[1].y);
  131. vLines.value = getLines(rect.value[0].x, rect.value[1].x);
  132. }
  133. }, 16),
  134. { immediate: true }
  135. );
  136. </script>