index.ts 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import { Transform } from "konva/lib/Util";
  2. import { themeColor } from "@/constant";
  3. import {
  4. BaseItem,
  5. generateSnapInfos,
  6. getBaseItem,
  7. getRectSnapPoints,
  8. } from "../util.ts";
  9. import { getMouseColors } from "@/utils/colors.ts";
  10. import { InteractiveFix, InteractiveTo, MatResponseProps } from "../index.ts";
  11. import { numEq, Size } from "@/utils/math.ts";
  12. import { copy } from "@/utils/shared.ts";
  13. import { MathUtils } from "three";
  14. export { default as Component } from "./table.vue";
  15. export { default as TempComponent } from "./temp-table.vue";
  16. export const shapeName = "表格";
  17. export const defaultStyle = {
  18. stroke: '#000',
  19. strokeWidth: 1,
  20. fontSize: 16,
  21. align: "center",
  22. fontStyle: "normal",
  23. fontColor: '#000',
  24. };
  25. export const defaultCollData = {
  26. fontFamily: "Calibri",
  27. fontSize: 16,
  28. align: "center",
  29. fontStyle: "normal",
  30. fontColor: themeColor
  31. };
  32. export const addMode = "area";
  33. export type TableCollData = Partial<typeof defaultCollData> &
  34. Size & {
  35. content: string;
  36. padding: number;
  37. readonly?: boolean;
  38. notdel?: boolean;
  39. };
  40. export type TableData = Partial<typeof defaultStyle> &
  41. BaseItem &
  42. Size & {
  43. fill?: string
  44. notaddRow?: boolean;
  45. notaddCol?: boolean;
  46. mat: number[];
  47. content: TableCollData[][];
  48. };
  49. export const getMouseStyle = (data: TableData) => {
  50. const strokeStatus = getMouseColors(data.stroke || defaultStyle.stroke);
  51. return {
  52. default: { stroke: data.stroke || defaultStyle.stroke },
  53. hover: { stroke: strokeStatus.hover },
  54. press: { stroke: strokeStatus.press },
  55. select: { select: strokeStatus.select },
  56. };
  57. };
  58. export const getSnapPoints = (data: TableData) => {
  59. const tf = new Transform(data.mat);
  60. const points = getRectSnapPoints(data.width, data.height, 0, 0).map((v) =>
  61. tf.point(v)
  62. );
  63. return points;
  64. };
  65. export const getSnapInfos = (data: TableData) => {
  66. return generateSnapInfos(getSnapPoints(data), true, false);
  67. };
  68. export const interactiveToData: InteractiveTo<"table"> = ({
  69. info,
  70. preset = {},
  71. ...args
  72. }) => {
  73. if (info.cur) {
  74. const item = {
  75. ...defaultStyle,
  76. ...getBaseItem(),
  77. ...preset,
  78. } as unknown as TableData;
  79. return interactiveFixData({ ...args, info, data: item });
  80. }
  81. };
  82. export const autoCollWidth = 100;
  83. export const autoCollHeight = 50;
  84. export const interactiveFixData: InteractiveFix<"table"> = ({
  85. data,
  86. info,
  87. notdraw,
  88. }) => {
  89. if (info.cur) {
  90. const area = info.cur!;
  91. const origin = {
  92. x: Math.min(area[0].x, area[1].x),
  93. y: Math.min(area[0].y, area[1].y),
  94. };
  95. data.width = Math.abs(area[0].x - area[1].x);
  96. data.height = Math.abs(area[0].y - area[1].y);
  97. if (!notdraw || !(data.content?.length && data.content[0].length)) {
  98. const colNum = Math.floor(data.width / autoCollWidth) || 1;
  99. const rawNum = Math.floor(data.height / autoCollHeight) || 1;
  100. const temp = data.content?.[0]?.[0] || {
  101. content: "",
  102. };
  103. data.content = Array.from({ length: rawNum }, () =>
  104. Array.from({ length: colNum }, () => ({
  105. ...temp,
  106. width: data.width / colNum,
  107. height: data.height / rawNum,
  108. padding: 8,
  109. }))
  110. );
  111. } else {
  112. const colHeight = data.height / data.content.length;
  113. const colWidth = data.width / data.content[0].length;
  114. data.content.forEach((row) => {
  115. row.forEach((col) => {
  116. col.width = colWidth;
  117. col.height = colHeight;
  118. col.padding = 8;
  119. console.log(col.content);
  120. });
  121. });
  122. }
  123. data.mat = new Transform().translate(origin.x, origin.y).m;
  124. }
  125. return data;
  126. };
  127. export const getColMinSize = (col: TableCollData) => {
  128. const minw = (col.padding || 0) * 2 + (col.fontSize || 12) + 4;
  129. const minh = (col.padding || 0) * 2 + (col.fontSize || 12) ;
  130. return { w: minw, h: minh };
  131. };
  132. export const matResponse = (
  133. { data, mat, operType, increment }: MatResponseProps<"table">,
  134. initData?: TableData
  135. ) => {
  136. if (!initData) {
  137. initData = copy(data);
  138. }
  139. if (increment) {
  140. mat = mat.copy().multiply(new Transform(data.mat))
  141. }
  142. const dec = mat.decompose();
  143. const oldData = copy(data);
  144. data.height = dec.scaleY * initData.height;
  145. data.width = dec.scaleX * initData.width;
  146. let minwNdxs: number[] = []
  147. let minhNdxs: number[] = []
  148. let w = 0;
  149. let h = 0;
  150. const updateColSize = () => {
  151. // 调整最小值
  152. let curMinwNdxs = [...minwNdxs]
  153. let curMinhNdxs = [...minhNdxs]
  154. const getNewWidth = (ndx: number) => {
  155. // data.width * (initCol.width / initData.width)
  156. const initCol = initData.content[0][ndx]
  157. let initWidth = initData.width
  158. const index = minwNdxs.indexOf(ndx)
  159. const spMinwNdxs = ~index ? minwNdxs.slice(0, index) : minwNdxs
  160. spMinwNdxs.forEach(ndx => initWidth -= initData.content[0][ndx].width)
  161. const width = (data.width - w) * (initCol.width / initWidth);
  162. return width
  163. }
  164. const getNewHeight = (ndx: number) => {
  165. const initCol = initData.content[ndx][0]
  166. let initHeight = initData.height
  167. const index = minhNdxs.indexOf(ndx)
  168. const spMinhNdxs = ~index ? minhNdxs.slice(0, index) : minhNdxs
  169. spMinhNdxs.forEach(ndx => initHeight -= initData.content[ndx][0].height)
  170. const height = (data.height - h) * (initCol.height / initHeight)
  171. return height
  172. }
  173. data.content.forEach((row, rndx) => {
  174. row.forEach((col, cndx) => {
  175. const initCol = initData.content[rndx][cndx];
  176. const minSize = getColMinSize(initCol);
  177. if (!curMinwNdxs.includes(cndx)) {
  178. const neww = getNewWidth(cndx)
  179. if (neww < minSize.w) {
  180. col.width = minSize.w
  181. if (rndx === 0) {
  182. minwNdxs.push(cndx)
  183. console.log('===>', col.width)
  184. w += col.width
  185. }
  186. }
  187. }
  188. if (!curMinhNdxs.includes(rndx)) {
  189. const newh = getNewHeight(rndx)
  190. if (newh < minSize.h) {
  191. col.height = minSize.h
  192. if (cndx === 0) {
  193. minhNdxs.push(rndx)
  194. h += col.height
  195. }
  196. }
  197. }
  198. });
  199. });
  200. if (curMinwNdxs.length !== minwNdxs.length || curMinhNdxs.length !== minhNdxs.length) {
  201. return updateColSize()
  202. }
  203. const needUpdateH = curMinhNdxs.length !== data.content.length
  204. const needUpdateW = curMinwNdxs.length !== data.content[0].length
  205. if (!needUpdateH && !needUpdateW) return;
  206. data.content.forEach((row, rndx) => {
  207. row.forEach((col, cndx) => {
  208. if (needUpdateW && !minwNdxs.includes(cndx)) {
  209. col.width = getNewWidth(cndx)
  210. }
  211. if (needUpdateH && !minhNdxs.includes(rndx)) {
  212. col.height = getNewHeight(rndx)
  213. }
  214. })
  215. })
  216. data.content.forEach((row, rndx) => {
  217. row.forEach((col, cndx) => {
  218. if (needUpdateW && !minwNdxs.includes(cndx) && rndx === 0) {
  219. w += col.width
  220. }
  221. if (needUpdateH &&!minhNdxs.includes(rndx) && cndx === 0) {
  222. h += col.height
  223. }
  224. })
  225. })
  226. }
  227. updateColSize()
  228. const eqW = numEq(w, data.width);
  229. const eqH = numEq(h, data.height);
  230. if (!eqW || !eqH) {
  231. if (operType) {
  232. Object.assign(data, oldData);
  233. } else {
  234. data.width = w;
  235. data.height = h;
  236. const initDec = new Transform(initData.mat).decompose();
  237. data.mat = new Transform()
  238. .translate(eqW ? dec.x : initDec.x, eqH ? dec.y : initDec.y)
  239. .rotate(MathUtils.degToRad(dec.rotation)).m;
  240. }
  241. } else {
  242. data.mat = new Transform()
  243. .translate(dec.x, dec.y)
  244. .rotate(MathUtils.degToRad(dec.rotation)).m;
  245. }
  246. return data;
  247. };
  248. export const getPredefine = (key: keyof TableData) => {
  249. if (key === 'fill') {
  250. return { canun: true }
  251. }
  252. }