@meta2d/core 1.0.55 → 1.0.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/README.md +13 -0
  2. package/package.build.json +39 -0
  3. package/package.json +38 -38
  4. package/src/canvas/canvas.ts +8639 -0
  5. package/src/canvas/canvasImage.ts +525 -0
  6. package/src/canvas/canvasTemplate.ts +257 -0
  7. package/src/canvas/magnifierCanvas.ts +142 -0
  8. package/src/canvas/offscreen.ts +14 -0
  9. package/src/core.ts +5128 -0
  10. package/src/data.ts +86 -0
  11. package/src/diagrams/arrow.ts +50 -0
  12. package/src/diagrams/circle.ts +19 -0
  13. package/src/diagrams/cloud.ts +34 -0
  14. package/src/diagrams/cube.ts +94 -0
  15. package/src/diagrams/diamond.ts +14 -0
  16. package/src/diagrams/file.ts +19 -0
  17. package/src/diagrams/gif.ts +105 -0
  18. package/src/diagrams/{hexagon.js → hexagon.ts} +19 -14
  19. package/src/diagrams/iframe.ts +365 -0
  20. package/src/diagrams/{index.js → index.ts} +36 -34
  21. package/src/diagrams/line/arrow.ts +175 -0
  22. package/src/diagrams/line/curve.ts +260 -0
  23. package/src/diagrams/line/line.ts +409 -0
  24. package/src/diagrams/line/polyline.ts +676 -0
  25. package/src/diagrams/line/smooth.ts +133 -0
  26. package/src/diagrams/message.ts +17 -0
  27. package/src/diagrams/mindLine.ts +31 -0
  28. package/src/diagrams/mindNode.ts +177 -0
  29. package/src/diagrams/panel.ts +149 -0
  30. package/src/diagrams/pentagon.ts +48 -0
  31. package/src/diagrams/pentagram.ts +63 -0
  32. package/src/diagrams/people.ts +23 -0
  33. package/src/diagrams/rectangle.ts +29 -0
  34. package/src/diagrams/svg/parse.ts +319 -0
  35. package/src/diagrams/svgPath.ts +53 -0
  36. package/src/diagrams/triangle.ts +43 -0
  37. package/src/diagrams/video.ts +202 -0
  38. package/src/dialog/dialog.ts +177 -0
  39. package/src/event/event.ts +142 -0
  40. package/src/map/map.ts +239 -0
  41. package/src/options.ts +205 -0
  42. package/src/pen/arrow.ts +259 -0
  43. package/src/pen/math.ts +253 -0
  44. package/src/pen/model.ts +785 -0
  45. package/src/pen/plugin.ts +57 -0
  46. package/src/pen/render.ts +3725 -0
  47. package/src/pen/text.ts +341 -0
  48. package/src/pen/utils.ts +21 -0
  49. package/src/point/point.ts +232 -0
  50. package/src/rect/rect.ts +507 -0
  51. package/src/rect/triangle.ts +16 -0
  52. package/src/scroll/scroll.ts +277 -0
  53. package/src/store/global.ts +38 -0
  54. package/src/store/store.ts +293 -0
  55. package/src/theme.ts +35 -0
  56. package/src/title/title.ts +115 -0
  57. package/src/tooltip/tooltip.ts +199 -0
  58. package/src/utils/clone.ts +79 -0
  59. package/src/utils/color.ts +126 -0
  60. package/src/utils/error.ts +7 -0
  61. package/src/utils/file.ts +46 -0
  62. package/src/utils/{index.d.ts → index.ts} +1 -0
  63. package/src/utils/math.ts +120 -0
  64. package/src/utils/object.ts +23 -0
  65. package/src/utils/padding.ts +48 -0
  66. package/src/utils/time.ts +25 -0
  67. package/src/utils/url.ts +30 -0
  68. package/src/utils/uuid.ts +15 -0
  69. package/index.js +0 -10
  70. package/index.js.map +0 -1
  71. package/src/canvas/canvas.d.ts +0 -456
  72. package/src/canvas/canvas.js +0 -8187
  73. package/src/canvas/canvas.js.map +0 -1
  74. package/src/canvas/canvasImage.d.ts +0 -28
  75. package/src/canvas/canvasImage.js +0 -503
  76. package/src/canvas/canvasImage.js.map +0 -1
  77. package/src/canvas/canvasTemplate.d.ts +0 -19
  78. package/src/canvas/canvasTemplate.js +0 -229
  79. package/src/canvas/canvasTemplate.js.map +0 -1
  80. package/src/canvas/index.js +0 -3
  81. package/src/canvas/index.js.map +0 -1
  82. package/src/canvas/magnifierCanvas.d.ts +0 -20
  83. package/src/canvas/magnifierCanvas.js +0 -101
  84. package/src/canvas/magnifierCanvas.js.map +0 -1
  85. package/src/canvas/offscreen.d.ts +0 -2
  86. package/src/canvas/offscreen.js +0 -14
  87. package/src/canvas/offscreen.js.map +0 -1
  88. package/src/core.d.ts +0 -479
  89. package/src/core.js +0 -5199
  90. package/src/core.js.map +0 -1
  91. package/src/data.d.ts +0 -34
  92. package/src/data.js +0 -85
  93. package/src/data.js.map +0 -1
  94. package/src/diagrams/arrow.d.ts +0 -4
  95. package/src/diagrams/arrow.js +0 -47
  96. package/src/diagrams/arrow.js.map +0 -1
  97. package/src/diagrams/circle.d.ts +0 -2
  98. package/src/diagrams/circle.js +0 -9
  99. package/src/diagrams/circle.js.map +0 -1
  100. package/src/diagrams/cloud.d.ts +0 -2
  101. package/src/diagrams/cloud.js +0 -12
  102. package/src/diagrams/cloud.js.map +0 -1
  103. package/src/diagrams/cube.d.ts +0 -2
  104. package/src/diagrams/cube.js +0 -70
  105. package/src/diagrams/cube.js.map +0 -1
  106. package/src/diagrams/diamond.d.ts +0 -2
  107. package/src/diagrams/diamond.js +0 -13
  108. package/src/diagrams/diamond.js.map +0 -1
  109. package/src/diagrams/file.d.ts +0 -2
  110. package/src/diagrams/file.js +0 -18
  111. package/src/diagrams/file.js.map +0 -1
  112. package/src/diagrams/gif.d.ts +0 -5
  113. package/src/diagrams/gif.js +0 -90
  114. package/src/diagrams/gif.js.map +0 -1
  115. package/src/diagrams/hexagon.d.ts +0 -2
  116. package/src/diagrams/hexagon.js.map +0 -1
  117. package/src/diagrams/iframe.d.ts +0 -2
  118. package/src/diagrams/iframe.js +0 -356
  119. package/src/diagrams/iframe.js.map +0 -1
  120. package/src/diagrams/index.d.ts +0 -71
  121. package/src/diagrams/index.js.map +0 -1
  122. package/src/diagrams/line/arrow.d.ts +0 -2
  123. package/src/diagrams/line/arrow.js +0 -128
  124. package/src/diagrams/line/arrow.js.map +0 -1
  125. package/src/diagrams/line/curve.d.ts +0 -16
  126. package/src/diagrams/line/curve.js +0 -236
  127. package/src/diagrams/line/curve.js.map +0 -1
  128. package/src/diagrams/line/index.js +0 -6
  129. package/src/diagrams/line/index.js.map +0 -1
  130. package/src/diagrams/line/line.d.ts +0 -42
  131. package/src/diagrams/line/line.js +0 -431
  132. package/src/diagrams/line/line.js.map +0 -1
  133. package/src/diagrams/line/polyline.d.ts +0 -10
  134. package/src/diagrams/line/polyline.js +0 -657
  135. package/src/diagrams/line/polyline.js.map +0 -1
  136. package/src/diagrams/line/smooth.d.ts +0 -3
  137. package/src/diagrams/line/smooth.js +0 -174
  138. package/src/diagrams/line/smooth.js.map +0 -1
  139. package/src/diagrams/message.d.ts +0 -2
  140. package/src/diagrams/message.js +0 -15
  141. package/src/diagrams/message.js.map +0 -1
  142. package/src/diagrams/mindLine.d.ts +0 -3
  143. package/src/diagrams/mindLine.js +0 -31
  144. package/src/diagrams/mindLine.js.map +0 -1
  145. package/src/diagrams/mindNode.d.ts +0 -3
  146. package/src/diagrams/mindNode.js +0 -189
  147. package/src/diagrams/mindNode.js.map +0 -1
  148. package/src/diagrams/panel.d.ts +0 -2
  149. package/src/diagrams/panel.js +0 -131
  150. package/src/diagrams/panel.js.map +0 -1
  151. package/src/diagrams/pentagon.d.ts +0 -3
  152. package/src/diagrams/pentagon.js +0 -46
  153. package/src/diagrams/pentagon.js.map +0 -1
  154. package/src/diagrams/pentagram.d.ts +0 -3
  155. package/src/diagrams/pentagram.js +0 -77
  156. package/src/diagrams/pentagram.js.map +0 -1
  157. package/src/diagrams/people.d.ts +0 -2
  158. package/src/diagrams/people.js +0 -19
  159. package/src/diagrams/people.js.map +0 -1
  160. package/src/diagrams/rectangle.d.ts +0 -3
  161. package/src/diagrams/rectangle.js +0 -26
  162. package/src/diagrams/rectangle.js.map +0 -1
  163. package/src/diagrams/svg/parse.d.ts +0 -15
  164. package/src/diagrams/svg/parse.js +0 -326
  165. package/src/diagrams/svg/parse.js.map +0 -1
  166. package/src/diagrams/svgPath.d.ts +0 -2
  167. package/src/diagrams/svgPath.js +0 -30
  168. package/src/diagrams/svgPath.js.map +0 -1
  169. package/src/diagrams/triangle.d.ts +0 -3
  170. package/src/diagrams/triangle.js +0 -41
  171. package/src/diagrams/triangle.js.map +0 -1
  172. package/src/diagrams/video.d.ts +0 -5
  173. package/src/diagrams/video.js +0 -185
  174. package/src/diagrams/video.js.map +0 -1
  175. package/src/dialog/dialog.d.ts +0 -21
  176. package/src/dialog/dialog.js +0 -98
  177. package/src/dialog/dialog.js.map +0 -1
  178. package/src/dialog/index.js +0 -2
  179. package/src/dialog/index.js.map +0 -1
  180. package/src/event/event.d.ts +0 -102
  181. package/src/event/event.js +0 -22
  182. package/src/event/event.js.map +0 -1
  183. package/src/event/index.js +0 -2
  184. package/src/event/index.js.map +0 -1
  185. package/src/map/index.js +0 -2
  186. package/src/map/index.js.map +0 -1
  187. package/src/map/map.d.ts +0 -21
  188. package/src/map/map.js +0 -210
  189. package/src/map/map.js.map +0 -1
  190. package/src/options.d.ts +0 -130
  191. package/src/options.js +0 -80
  192. package/src/options.js.map +0 -1
  193. package/src/pen/arrow.d.ts +0 -4
  194. package/src/pen/arrow.js +0 -188
  195. package/src/pen/arrow.js.map +0 -1
  196. package/src/pen/index.js +0 -7
  197. package/src/pen/index.js.map +0 -1
  198. package/src/pen/math.d.ts +0 -28
  199. package/src/pen/math.js +0 -304
  200. package/src/pen/math.js.map +0 -1
  201. package/src/pen/model.d.ts +0 -514
  202. package/src/pen/model.js +0 -210
  203. package/src/pen/model.js.map +0 -1
  204. package/src/pen/plugin.d.ts +0 -5
  205. package/src/pen/plugin.js +0 -88
  206. package/src/pen/plugin.js.map +0 -1
  207. package/src/pen/render.d.ts +0 -147
  208. package/src/pen/render.js +0 -3236
  209. package/src/pen/render.js.map +0 -1
  210. package/src/pen/text.d.ts +0 -8
  211. package/src/pen/text.js +0 -375
  212. package/src/pen/text.js.map +0 -1
  213. package/src/pen/utils.d.ts +0 -2
  214. package/src/pen/utils.js +0 -41
  215. package/src/pen/utils.js.map +0 -1
  216. package/src/point/index.js +0 -2
  217. package/src/point/index.js.map +0 -1
  218. package/src/point/point.d.ts +0 -65
  219. package/src/point/point.js +0 -179
  220. package/src/point/point.js.map +0 -1
  221. package/src/rect/index.js +0 -2
  222. package/src/rect/index.js.map +0 -1
  223. package/src/rect/rect.d.ts +0 -52
  224. package/src/rect/rect.js +0 -486
  225. package/src/rect/rect.js.map +0 -1
  226. package/src/rect/triangle.d.ts +0 -2
  227. package/src/rect/triangle.js +0 -10
  228. package/src/rect/triangle.js.map +0 -1
  229. package/src/scroll/index.js +0 -2
  230. package/src/scroll/index.js.map +0 -1
  231. package/src/scroll/scroll.d.ts +0 -35
  232. package/src/scroll/scroll.js +0 -221
  233. package/src/scroll/scroll.js.map +0 -1
  234. package/src/store/global.d.ts +0 -25
  235. package/src/store/global.js +0 -18
  236. package/src/store/global.js.map +0 -1
  237. package/src/store/index.js +0 -3
  238. package/src/store/index.js.map +0 -1
  239. package/src/store/store.d.ts +0 -228
  240. package/src/store/store.js +0 -121
  241. package/src/store/store.js.map +0 -1
  242. package/src/theme.d.ts +0 -13
  243. package/src/theme.js +0 -23
  244. package/src/theme.js.map +0 -1
  245. package/src/title/index.js +0 -2
  246. package/src/title/index.js.map +0 -1
  247. package/src/title/title.d.ts +0 -30
  248. package/src/title/title.js +0 -99
  249. package/src/title/title.js.map +0 -1
  250. package/src/tooltip/index.js +0 -2
  251. package/src/tooltip/index.js.map +0 -1
  252. package/src/tooltip/tooltip.d.ts +0 -40
  253. package/src/tooltip/tooltip.js +0 -167
  254. package/src/tooltip/tooltip.js.map +0 -1
  255. package/src/utils/browser.d.ts +0 -1
  256. package/src/utils/browser.js +0 -4
  257. package/src/utils/browser.js.map +0 -1
  258. package/src/utils/clone.d.ts +0 -8
  259. package/src/utils/clone.js +0 -88
  260. package/src/utils/clone.js.map +0 -1
  261. package/src/utils/color.d.ts +0 -3
  262. package/src/utils/color.js +0 -126
  263. package/src/utils/color.js.map +0 -1
  264. package/src/utils/error.d.ts +0 -2
  265. package/src/utils/error.js +0 -6
  266. package/src/utils/error.js.map +0 -1
  267. package/src/utils/file.d.ts +0 -3
  268. package/src/utils/file.js +0 -92
  269. package/src/utils/file.js.map +0 -1
  270. package/src/utils/index.js +0 -9
  271. package/src/utils/index.js.map +0 -1
  272. package/src/utils/math.d.ts +0 -18
  273. package/src/utils/math.js +0 -152
  274. package/src/utils/math.js.map +0 -1
  275. package/src/utils/object.d.ts +0 -2
  276. package/src/utils/object.js +0 -21
  277. package/src/utils/object.js.map +0 -1
  278. package/src/utils/padding.d.ts +0 -7
  279. package/src/utils/padding.js +0 -47
  280. package/src/utils/padding.js.map +0 -1
  281. package/src/utils/time.d.ts +0 -1
  282. package/src/utils/time.js +0 -17
  283. package/src/utils/time.js.map +0 -1
  284. package/src/utils/url.d.ts +0 -4
  285. package/src/utils/url.js +0 -27
  286. package/src/utils/url.js.map +0 -1
  287. package/src/utils/uuid.d.ts +0 -4
  288. package/src/utils/uuid.js +0 -13
  289. package/src/utils/uuid.js.map +0 -1
  290. /package/{index.d.ts → index.ts} +0 -0
  291. /package/src/canvas/{index.d.ts → index.ts} +0 -0
  292. /package/src/diagrams/line/{index.d.ts → index.ts} +0 -0
  293. /package/src/dialog/{index.d.ts → index.ts} +0 -0
  294. /package/src/event/{index.d.ts → index.ts} +0 -0
  295. /package/src/map/{index.d.ts → index.ts} +0 -0
  296. /package/src/pen/{index.d.ts → index.ts} +0 -0
  297. /package/src/point/{index.d.ts → index.ts} +0 -0
  298. /package/src/rect/{index.d.ts → index.ts} +0 -0
  299. /package/src/scroll/{index.d.ts → index.ts} +0 -0
  300. /package/src/store/{index.d.ts → index.ts} +0 -0
  301. /package/src/title/{index.d.ts → index.ts} +0 -0
  302. /package/src/tooltip/{index.d.ts → index.ts} +0 -0
@@ -0,0 +1,341 @@
1
+ import { Pen } from '.';
2
+ import { Canvas } from '../canvas';
3
+ import { calcRightBottom, Rect } from '../rect';
4
+ import { getFont } from './render';
5
+
6
+ export function calcTextRect(pen: Pen) {
7
+ const {
8
+ paddingTop,
9
+ paddingBottom,
10
+ paddingLeft,
11
+ paddingRight,
12
+ worldRect,
13
+ canvas,
14
+ } = pen.calculative;
15
+ let { textLeft, textTop, textWidth, textHeight } = pen.calculative;
16
+ let x = paddingLeft;
17
+ let y = paddingTop;
18
+ // if (textLeft && Math.abs(textLeft) < 1) {
19
+ // textLeft *= worldRect.width;
20
+ // }
21
+ // if (textTop && Math.abs(textTop) < 1) {
22
+ // textTop *= worldRect.height;
23
+ // }
24
+
25
+ const width =
26
+ worldRect.width -
27
+ paddingLeft -
28
+ paddingRight -
29
+ ((pen.textAlign === 'right' ? -textLeft : textLeft) || 0);
30
+ const height =
31
+ worldRect.height -
32
+ paddingTop -
33
+ paddingBottom -
34
+ ((pen.textBaseline === 'bottom' ? -textTop : textTop) || 0);
35
+ if (textWidth && textWidth < 1) {
36
+ textWidth *= worldRect.width;
37
+ }
38
+ if (textHeight && textHeight < 1) {
39
+ textHeight *= worldRect.height;
40
+ }
41
+ if (textWidth < pen.calculative.fontSize) {
42
+ textWidth = pen.calculative.fontSize;
43
+ }
44
+ // 默认居左,居上
45
+ x += (textLeft || 0) + worldRect.x;
46
+ y += (textTop || 0) + worldRect.y;
47
+ const textAlign = pen.textAlign || canvas.store.options.textAlign;
48
+ const textBaseline = pen.textBaseline || canvas.store.options.textBaseline;
49
+
50
+ switch (textAlign) {
51
+ case 'center':
52
+ x += (width - (textWidth || width)) / 2;
53
+ break;
54
+ case 'right':
55
+ x += width - (textWidth || width);
56
+ break;
57
+ }
58
+
59
+ switch (textBaseline) {
60
+ case 'middle':
61
+ y += (height - (textHeight || height)) / 2;
62
+ break;
63
+ case 'bottom':
64
+ y += height - (textHeight || height);
65
+ break;
66
+ }
67
+
68
+ const rect: Rect = {
69
+ x,
70
+ y,
71
+ width: textWidth || width,
72
+ height: textHeight || height,
73
+ };
74
+ calcRightBottom(rect);
75
+ pen.calculative.worldTextRect = rect;
76
+
77
+ calcTextLines(pen);
78
+ pen.calculative.textDrawRect = undefined;
79
+ }
80
+
81
+ export function calcTextDrawRect(ctx: CanvasRenderingContext2D, pen: Pen) {
82
+ // By default, the text is center aligned.
83
+ const lineHeight = pen.calculative.fontSize * pen.calculative.lineHeight;
84
+ const h = pen.calculative.textLines.length * lineHeight;
85
+ const textWidth = calcTextAdaptionWidth(ctx, pen); // 多行文本最大宽度
86
+ const rect = pen.calculative.worldTextRect;
87
+ let x = rect.x + (rect.width - textWidth) / 2;
88
+ let y = rect.y + (rect.height - h) / 2;
89
+ const options = pen.calculative.canvas.store.options;
90
+ const textAlign = pen.textAlign || options.textAlign;
91
+ switch (textAlign) {
92
+ case 'left':
93
+ x = rect.x;
94
+ break;
95
+ case 'right':
96
+ x = rect.x + rect.width - textWidth;
97
+ break;
98
+ }
99
+ const textBaseline = pen.textBaseline || options.textBaseline;
100
+ switch (textBaseline) {
101
+ case 'top':
102
+ y = rect.y;
103
+ break;
104
+ case 'bottom':
105
+ y = rect.ey - h;
106
+ break;
107
+ }
108
+
109
+ pen.calculative.textDrawRect = {
110
+ x,
111
+ y,
112
+ width: textWidth,
113
+ height: h,
114
+ };
115
+ calcRightBottom(pen.calculative.textDrawRect);
116
+ }
117
+
118
+ export function calcTextLines(pen: Pen, text = pen.calculative.text) {
119
+ if (text == undefined) {
120
+ pen.calculative.textLines = [];
121
+ return;
122
+ }
123
+ text = text.toString();
124
+ let lines: string[] = [];
125
+ const oneRowHeight = pen.calculative.fontSize * pen.calculative.lineHeight;
126
+ const textHeight = pen.calculative.worldTextRect.height;
127
+ const calcRows = Math.floor(textHeight / oneRowHeight);
128
+ // 最小值为 1
129
+ const maxRows = calcRows > 1 ? calcRows : 1;
130
+ switch (pen.whiteSpace) {
131
+ case 'nowrap':
132
+ if (pen.ellipsis !== false) {
133
+ const allLines = wrapLines(text.split(''), pen);
134
+ if (allLines[0]) {
135
+ lines.push(allLines[0]);
136
+ if (allLines.length > 1) {
137
+ // 存在第二行,说明宽度超出
138
+ setEllipsisOnLastLine(lines);
139
+ }
140
+ }
141
+ } else {
142
+ lines.push(text);
143
+ }
144
+ break;
145
+ case 'pre-line':
146
+ lines = text.split(/[\n]/g);
147
+ if (pen.ellipsis !== false && lines.length > maxRows) {
148
+ lines = lines.slice(0, maxRows);
149
+ setEllipsisOnLastLine(lines);
150
+ }
151
+ break;
152
+ case 'break-all':
153
+ default:
154
+ const paragraphs = text.split(/[\n]/g);
155
+ let currentRow = 0;
156
+ outer: for (const paragraph of paragraphs) {
157
+ const words =
158
+ pen.whiteSpace === 'break-all'
159
+ ? paragraph.split('')
160
+ : getWords(paragraph);
161
+ let items = wrapLines(words, pen);
162
+ // 空行换行的情况
163
+ if (items.length === 0) items = [''];
164
+ if (pen.ellipsis != false) {
165
+ for (const l of items) {
166
+ currentRow++;
167
+ if (currentRow > maxRows) {
168
+ setEllipsisOnLastLine(lines);
169
+ break outer;
170
+ } else {
171
+ lines.push(l);
172
+ }
173
+ }
174
+ } else {
175
+ lines.push(...items);
176
+ }
177
+ }
178
+ break;
179
+ }
180
+
181
+ const keepDecimal = pen.calculative.keepDecimal;
182
+ if (keepDecimal != undefined) {
183
+ lines.forEach((text, i) => {
184
+ const textNum = Number(text);
185
+ if (!isNaN(textNum)) {
186
+ lines[i] = textNum.toFixed(keepDecimal);
187
+ }
188
+ });
189
+ }
190
+
191
+ pen.calculative.textLines = lines;
192
+
193
+ return lines;
194
+ }
195
+
196
+ export function getWords(txt: string = '') {
197
+ const words: string[] = [];
198
+ let word = '';
199
+ for (let i = 0; i < txt.length; ++i) {
200
+ const ch = txt.charCodeAt(i);
201
+ if (ch < 33 || ch > 126) {
202
+ if (word) {
203
+ words.push(word);
204
+ word = '';
205
+ }
206
+ words.push(txt[i]);
207
+ } else {
208
+ word += txt[i];
209
+ }
210
+ }
211
+
212
+ if (word) {
213
+ words.push(word);
214
+ }
215
+
216
+ return words;
217
+ }
218
+
219
+ export function wrapLines(words: string[], pen: Pen) {
220
+ const canvas: Canvas = pen.calculative.canvas;
221
+ const ctx = canvas.offscreen.getContext('2d') as CanvasRenderingContext2D;
222
+ const { fontStyle, fontWeight, fontSize, fontFamily, lineHeight } =
223
+ pen.calculative;
224
+ ctx.save();
225
+ const lines: string[] = [];
226
+ let currentLine = words[0] || '';
227
+ for (let i = 1; i < words.length; ++i) {
228
+ const word = words[i] || '';
229
+ const text = currentLine + word;
230
+ let currentWidth = 0;
231
+ if (canvas.store.options.measureTextWidth) {
232
+ ctx.font = getFont({
233
+ fontStyle,
234
+ fontWeight,
235
+ fontFamily: fontFamily || canvas.store.options.fontFamily,
236
+ fontSize,
237
+ lineHeight,
238
+ });
239
+ currentWidth = ctx.measureText(text).width;
240
+ } else {
241
+ // 近似计算
242
+ const chinese = text.match(/[^\x00-\xff]/g) || '';
243
+ const chineseWidth = chinese.length * fontSize; // 中文占用的宽度
244
+ const spaces = text.match(/\s/g) || '';
245
+ const spaceWidth = spaces.length * fontSize * 0.3; // 空格占用的宽度
246
+ const otherWidth =
247
+ (text.length - chinese.length - spaces.length) * fontSize * 0.6; // 其他字符占用的宽度
248
+ currentWidth = chineseWidth + spaceWidth + otherWidth;
249
+ }
250
+ const textWidth = pen.calculative.worldTextRect.width;
251
+ if (currentWidth <= textWidth + 0.1) {
252
+ currentLine += word;
253
+ } else {
254
+ currentLine.length && lines.push(currentLine);
255
+ currentLine = word;
256
+ }
257
+ }
258
+ currentLine.length && lines.push(currentLine);
259
+ ctx.restore();
260
+ return lines;
261
+ }
262
+
263
+ export function calcTextAdaptionWidth(
264
+ ctx: CanvasRenderingContext2D,
265
+ pen: Pen
266
+ ): number {
267
+ let maxWidth = 0;
268
+ pen.calculative.textLineWidths = [];
269
+ pen.calculative.textLines.forEach((text: string) => {
270
+ const width = ctx.measureText(text).width;
271
+ pen.calculative.textLineWidths.push(width);
272
+ maxWidth < width && (maxWidth = width);
273
+ });
274
+ return maxWidth;
275
+ }
276
+ /**
277
+ * 副作用函数,会修改传入的参数
278
+ * 把最后一行的最后变成 ...
279
+ * TODO: 中文的三个字符宽度比 . 大,显示起来像是删多了
280
+ * @param lines
281
+ */
282
+ function setEllipsisOnLastLine(lines: string[]) {
283
+ lines[lines.length - 1] = lines[lines.length - 1].slice(0, -3) + '...';
284
+ }
285
+
286
+ export function calcTextAutoWidth(pen: Pen) {
287
+ let arr = pen.text.split('\n');
288
+ const canvas: Canvas = pen.calculative.canvas;
289
+ const ctx = canvas.offscreen.getContext('2d') as CanvasRenderingContext2D;
290
+ const { fontStyle, fontWeight, fontSize, fontFamily, lineHeight } =
291
+ pen.calculative;
292
+ let textWidth = 0; // pen.calculative.worldTextRect.width;
293
+ let currentWidth = 0; // textWidth;
294
+ ctx.save();
295
+ for (let i = 0; i < arr.length; i++) {
296
+ if (canvas.store.options.measureTextWidth) {
297
+ ctx.font = getFont({
298
+ fontStyle,
299
+ fontWeight,
300
+ fontFamily: fontFamily || canvas.store.options.fontFamily,
301
+ fontSize,
302
+ lineHeight,
303
+ });
304
+ currentWidth = ctx.measureText(arr[i]).width; //* scale;
305
+ } else {
306
+ // 近似计算
307
+ const chinese = arr[i].match(/[^\x00-\xff]/g) || '';
308
+ const chineseWidth = chinese.length * fontSize; // 中文占用的宽度
309
+ const spaces = arr[i].match(/\s/g) || '';
310
+ const spaceWidth = spaces.length * fontSize * 0.3; // 空格占用的宽度
311
+ const otherWidth =
312
+ (arr[i].length - chinese.length - spaces.length) * fontSize * 0.6; // 其他字符占用的宽度
313
+ currentWidth = chineseWidth + spaceWidth + otherWidth;
314
+ }
315
+ if (currentWidth > textWidth) {
316
+ textWidth = currentWidth; //* scale;
317
+ }
318
+ }
319
+ ctx.restore();
320
+ let textHeight = arr.length * fontSize * lineHeight;
321
+ if (pen.textAlign === 'left') {
322
+ // pen.x = pen.x;
323
+ } else if (pen.textAlign === 'right') {
324
+ pen.x = pen.x - (textWidth - pen.width);
325
+ } else {
326
+ pen.x = pen.x - (textWidth - pen.width) / 2;
327
+ }
328
+
329
+ if (pen.textBaseline === 'top') {
330
+ } else if (pen.textBaseline === 'bottom') {
331
+ pen.y = pen.y - (textHeight - pen.height);
332
+ } else {
333
+ pen.y = pen.y - (textHeight - pen.height) / 2;
334
+ }
335
+ // if (textHeight > pen.height) {
336
+ pen.height = textHeight + 2;
337
+ // }
338
+ pen.width = textWidth + 2; //误差
339
+ pen.calculative.canvas.updatePenRect(pen);
340
+ pen.calculative.canvas.calcActiveRect();
341
+ }
@@ -0,0 +1,21 @@
1
+ import { s8 } from '../utils';
2
+ import { Pen } from './model';
3
+
4
+ export function randomId(pen: Pen) {
5
+ pen.id = s8();
6
+ if (Array.isArray(pen.anchors)) {
7
+ for (const pt of pen.anchors) {
8
+ pen.type && (pt.id = s8());
9
+ pt.penId = pen.id;
10
+ if (pt.prev) {
11
+ pen.type && (pt.prev.id = s8());
12
+ pt.prev.penId = pen.id;
13
+ }
14
+
15
+ if (pt.next) {
16
+ pen.type && (pt.next.id = s8());
17
+ pt.next.penId = pen.id;
18
+ }
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,232 @@
1
+ import { Direction } from '../data';
2
+ import { Pen } from '../pen';
3
+ import { pointInRect } from '../rect';
4
+ import { Meta2dStore } from '../store';
5
+
6
+ export enum PrevNextType {
7
+ Mirror,
8
+ Bilateral,
9
+ Free,
10
+ }
11
+
12
+ export enum TwoWay {
13
+ Default,
14
+ In,
15
+ Out,
16
+ DisableConnected, // 禁止被连接
17
+ DisableConnectTo, // 禁止连线锚点连接其他锚点
18
+ Disable = 10,
19
+ }
20
+
21
+ export enum PointType {
22
+ Default,
23
+ Line,
24
+ }
25
+
26
+ export interface Point {
27
+ x: number;
28
+ y: number;
29
+ radius?: number;
30
+ color?: string;
31
+ background?: string;
32
+ id?: string;
33
+ penId?: string;
34
+ // line连接的pen.id
35
+ connectTo?: string;
36
+ // line连接的pen的anchor.id
37
+ anchorId?: string;
38
+ twoWay?: TwoWay;
39
+ prev?: Point;
40
+ next?: Point;
41
+ prevNextType?: PrevNextType;
42
+ start?: boolean;
43
+ lineLength?: number;
44
+ step?: number;
45
+ curvePoints?: Point[];
46
+ rotate?: number; //线锚点 [0,180)
47
+ hidden?: boolean;
48
+ locked?: number;
49
+ flag?: number;
50
+ // 临时绘制的点
51
+ isTemp?: boolean;
52
+ // 拖拽停靠的锚点
53
+ dockAnchorId?: string;
54
+ direction?: Direction; //锚点出线方向
55
+ title?: string; //锚点hover提示文字
56
+ type?: PointType;
57
+ length?: number;
58
+ distance?: number;
59
+ }
60
+
61
+ export function rotatePoint(pt: Point, angle: number, center: Point) {
62
+ if (!angle || angle % 360 === 0) {
63
+ return;
64
+ }
65
+ const a = (angle * Math.PI) / 180;
66
+ const x =
67
+ (pt.x - center.x) * Math.cos(a) -
68
+ (pt.y - center.y) * Math.sin(a) +
69
+ center.x;
70
+ const y =
71
+ (pt.x - center.x) * Math.sin(a) +
72
+ (pt.y - center.y) * Math.cos(a) +
73
+ center.y;
74
+ pt.x = x;
75
+ pt.y = y;
76
+
77
+ pt.prev && rotatePoint(pt.prev, angle, center);
78
+ pt.next && rotatePoint(pt.next, angle, center);
79
+ }
80
+
81
+ export function hitPoint(pt: Point, target: Point, radius = 5, pen?: Pen) {
82
+ if (target.type === PointType.Line) {
83
+ let _rotate = pen.rotate;
84
+ if (pen.flipX) {
85
+ _rotate *= -1;
86
+ }
87
+ if (pen.flipY) {
88
+ _rotate *= -1;
89
+ }
90
+ let rotate = target.rotate + _rotate;
91
+ if (pen.flipX) {
92
+ rotate *= -1;
93
+ }
94
+ if (pen.flipY) {
95
+ rotate *= -1;
96
+ }
97
+ return pointInRect(pt, {
98
+ x:
99
+ target.x -
100
+ (target.length * pen.calculative.canvas.store.data.scale) / 2,
101
+ y: target.y - radius,
102
+ width: target.length * pen.calculative.canvas.store.data.scale,
103
+ height: radius * 2,
104
+ rotate: rotate,
105
+ });
106
+ } else {
107
+ return (
108
+ pt.x > target.x - radius &&
109
+ pt.x < target.x + radius &&
110
+ pt.y > target.y - radius &&
111
+ pt.y < target.y + radius
112
+ );
113
+ }
114
+ }
115
+
116
+ export function scalePoint(pt: Point, scale: number, center: Point) {
117
+ pt.x = center.x - (center.x - pt.x) * scale;
118
+ pt.y = center.y - (center.y - pt.y) * scale;
119
+ }
120
+
121
+ export function calcRotate(pt: Point, center: Point) {
122
+ if (pt.x === center.x) {
123
+ return pt.y <= center.y ? 0 : 180;
124
+ }
125
+
126
+ if (pt.y === center.y) {
127
+ return pt.x < center.x ? 270 : 90;
128
+ }
129
+
130
+ const x = pt.x - center.x;
131
+ const y = pt.y - center.y;
132
+ let angle = (Math.atan(Math.abs(x / y)) / (2 * Math.PI)) * 360;
133
+ if (x > 0 && y > 0) {
134
+ angle = 180 - angle;
135
+ } else if (x < 0 && y > 0) {
136
+ angle += 180;
137
+ } else if (x < 0 && y < 0) {
138
+ angle = 360 - angle;
139
+ }
140
+
141
+ return angle;
142
+ }
143
+
144
+ export function distance(pt1: Point, pt2: Point): number {
145
+ const x = pt1.x - pt2.x;
146
+ const y = pt1.y - pt2.y;
147
+ return Math.sqrt(x * x + y * y);
148
+ }
149
+
150
+ export function facePoint(pt: Point, targetPt?: Point) {
151
+ let d = Direction.None;
152
+ if (!targetPt) {
153
+ return d;
154
+ }
155
+
156
+ const disX = pt.x - targetPt.x;
157
+ const disY = pt.y - targetPt.y;
158
+
159
+ if (Math.abs(disX) > Math.abs(disY)) {
160
+ if (disX > 0) {
161
+ d = Direction.Right;
162
+ } else {
163
+ d = Direction.Left;
164
+ }
165
+ } else {
166
+ if (disY > 0) {
167
+ d = Direction.Bottom;
168
+ } else {
169
+ d = Direction.Up;
170
+ }
171
+ }
172
+
173
+ return d;
174
+ }
175
+
176
+ export function translatePoint(pt: Point, x: number, y: number) {
177
+ if (!pt) {
178
+ return;
179
+ }
180
+
181
+ pt.x += x;
182
+ pt.y += y;
183
+
184
+ if (pt.next) {
185
+ pt.next.x += x;
186
+ pt.next.y += y;
187
+ }
188
+ if (pt.prev) {
189
+ pt.prev.x += x;
190
+ pt.prev.y += y;
191
+ }
192
+ }
193
+
194
+ /**
195
+ * 是否是同一个点
196
+ * @param pt1 点1
197
+ * @param pt2 点2
198
+ * @returns true 相同
199
+ */
200
+ export function samePoint(pt1: Point, pt2: Point): boolean {
201
+ return pt1.anchorId === pt2.anchorId && pt1.connectTo === pt2.connectTo;
202
+ }
203
+
204
+ export function getDistance(form: Point, to: Point, store: Meta2dStore) {
205
+ let dis =
206
+ Math.sqrt(
207
+ (form.x - to.x) * (form.x - to.x) + (form.y - to.y) * (form.y - to.y)
208
+ ) / store.data.scale;
209
+
210
+ if (to.rotate === 0) {
211
+ if (form.x < to.x) {
212
+ if (!store.pens[to.penId].flipX) {
213
+ dis *= -1;
214
+ }
215
+ } else {
216
+ if (store.pens[to.penId].flipX) {
217
+ dis *= -1;
218
+ }
219
+ }
220
+ } else {
221
+ if (form.y < to.y) {
222
+ if (!store.pens[to.penId].flipY) {
223
+ dis *= -1;
224
+ }
225
+ } else {
226
+ if (store.pens[to.penId].flipY) {
227
+ dis *= -1;
228
+ }
229
+ }
230
+ }
231
+ form.distance = dis;
232
+ }