@idraw/util 0.4.0-alpha.3 → 0.4.0-alpha.5

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.
@@ -1,6 +1,6 @@
1
1
  export { delay, compose, throttle } from './lib/time';
2
- export { downloadImageFromCanvas } from './lib/file';
3
- export { toColorHexStr, toColorHexNum, isColorStr, colorNameToHex } from './lib/color';
2
+ export { downloadImageFromCanvas, parseFileToBase64, pickFile, parseFileToText } from './lib/file';
3
+ export { toColorHexStr, toColorHexNum, isColorStr, colorNameToHex, colorToCSS, colorToLinearGradientCSS, mergeHexColorAlpha } from './lib/color';
4
4
  export { createUUID, isAssetId, createAssetId } from './lib/uuid';
5
5
  export { deepClone, sortDataAsserts } from './lib/data';
6
6
  export { istype } from './lib/istype';
@@ -14,13 +14,16 @@ export { Store } from './lib/store';
14
14
  export { getViewScaleInfoFromSnapshot, getViewSizeInfoFromSnapshot } from './lib/middleware';
15
15
  export { Context2D } from './lib/context2d';
16
16
  export { rotateElement, parseRadianToAngle, parseAngleToRadian, rotateElementVertexes, getElementRotateVertexes, calcElementCenter, calcElementCenterFromVertexes, rotatePointInGroup, limitAngle } from './lib/rotate';
17
- export { getSelectedElementUUIDs, validateElements, calcElementsContextSize, calcElementsViewInfo, getElemenetsAssetIds, findElementFromList, findElementsFromList, updateElementInList, getGroupQueueFromList } from './lib/element';
17
+ export { getSelectedElementUUIDs, validateElements, calcElementsContextSize, calcElementsViewInfo, getElemenetsAssetIds, findElementFromList, findElementsFromList, updateElementInList, getGroupQueueFromList, getElementSize, mergeElementAsset, filterElementAsset, isResourceElement } from './lib/element';
18
18
  export { checkRectIntersect } from './lib/rect';
19
19
  export { viewScale, viewScroll, calcViewElementSize, calcViewPointSize, calcViewVertexes, isViewPointInElement, getViewPointAtElement, isElementInView } from './lib/view-calc';
20
- export { rotatePoint, rotateVertexes } from './lib/rotate';
20
+ export { rotatePoint, rotateVertexes, rotateByCenter } from './lib/rotate';
21
21
  export { getElementVertexes, calcElementVertexesInGroup, calcElementVertexesQueueInGroup, calcElementQueueVertexesQueueInGroup } from './lib/vertex';
22
22
  export { calcElementSizeController } from './lib/controller';
23
23
  export { generateSVGPath, parseSVGPath } from './lib/svg-path';
24
24
  export { generateHTML, parseHTML } from './lib/html';
25
25
  export { compressImage } from './lib/image';
26
26
  export { formatNumber } from './lib/number';
27
+ export { matrixToAngle, matrixToRadian } from './lib/matrix';
28
+ export { getDefaultElementDetailConfig } from './lib/config';
29
+ export { calcViewBoxSize } from './lib/view-box';
package/dist/esm/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { delay, compose, throttle } from './lib/time';
2
- export { downloadImageFromCanvas } from './lib/file';
3
- export { toColorHexStr, toColorHexNum, isColorStr, colorNameToHex } from './lib/color';
2
+ export { downloadImageFromCanvas, parseFileToBase64, pickFile, parseFileToText } from './lib/file';
3
+ export { toColorHexStr, toColorHexNum, isColorStr, colorNameToHex, colorToCSS, colorToLinearGradientCSS, mergeHexColorAlpha } from './lib/color';
4
4
  export { createUUID, isAssetId, createAssetId } from './lib/uuid';
5
5
  export { deepClone, sortDataAsserts } from './lib/data';
6
6
  export { istype } from './lib/istype';
@@ -14,13 +14,16 @@ export { Store } from './lib/store';
14
14
  export { getViewScaleInfoFromSnapshot, getViewSizeInfoFromSnapshot } from './lib/middleware';
15
15
  export { Context2D } from './lib/context2d';
16
16
  export { rotateElement, parseRadianToAngle, parseAngleToRadian, rotateElementVertexes, getElementRotateVertexes, calcElementCenter, calcElementCenterFromVertexes, rotatePointInGroup, limitAngle } from './lib/rotate';
17
- export { getSelectedElementUUIDs, validateElements, calcElementsContextSize, calcElementsViewInfo, getElemenetsAssetIds, findElementFromList, findElementsFromList, updateElementInList, getGroupQueueFromList } from './lib/element';
17
+ export { getSelectedElementUUIDs, validateElements, calcElementsContextSize, calcElementsViewInfo, getElemenetsAssetIds, findElementFromList, findElementsFromList, updateElementInList, getGroupQueueFromList, getElementSize, mergeElementAsset, filterElementAsset, isResourceElement } from './lib/element';
18
18
  export { checkRectIntersect } from './lib/rect';
19
19
  export { viewScale, viewScroll, calcViewElementSize, calcViewPointSize, calcViewVertexes, isViewPointInElement, getViewPointAtElement, isElementInView } from './lib/view-calc';
20
- export { rotatePoint, rotateVertexes } from './lib/rotate';
20
+ export { rotatePoint, rotateVertexes, rotateByCenter } from './lib/rotate';
21
21
  export { getElementVertexes, calcElementVertexesInGroup, calcElementVertexesQueueInGroup, calcElementQueueVertexesQueueInGroup } from './lib/vertex';
22
22
  export { calcElementSizeController } from './lib/controller';
23
23
  export { generateSVGPath, parseSVGPath } from './lib/svg-path';
24
24
  export { generateHTML, parseHTML } from './lib/html';
25
25
  export { compressImage } from './lib/image';
26
26
  export { formatNumber } from './lib/number';
27
+ export { matrixToAngle, matrixToRadian } from './lib/matrix';
28
+ export { getDefaultElementDetailConfig } from './lib/config';
29
+ export { calcViewBoxSize } from './lib/view-box';
@@ -26,8 +26,10 @@ export function createBoardContexts(ctx, opts) {
26
26
  };
27
27
  const viewContext = createContext2D(ctxOpts);
28
28
  const helperContext = createContext2D(ctxOpts);
29
+ const underContext = createContext2D(ctxOpts);
29
30
  const boardContext = createContext2D(Object.assign({ ctx }, ctxOpts));
30
31
  const content = {
32
+ underContext,
31
33
  viewContext,
32
34
  helperContext,
33
35
  boardContext
@@ -1,4 +1,8 @@
1
+ import type { LinearGradientColor, RadialGradientColor } from '@idraw/types';
1
2
  export declare function toColorHexNum(color: string): number;
2
3
  export declare function toColorHexStr(color: number): string;
3
4
  export declare function isColorStr(color?: string): boolean;
4
5
  export declare function colorNameToHex(name: string): string | null;
6
+ export declare function colorToCSS(color?: string | LinearGradientColor | RadialGradientColor): string;
7
+ export declare function colorToLinearGradientCSS(color?: string | LinearGradientColor | RadialGradientColor): string;
8
+ export declare function mergeHexColorAlpha(hex: string, alpha: number): string;
@@ -158,3 +158,75 @@ export function colorNameToHex(name) {
158
158
  }
159
159
  return null;
160
160
  }
161
+ export function colorToCSS(color) {
162
+ let css = 'transparent';
163
+ if (typeof color === 'string') {
164
+ css = color;
165
+ }
166
+ else if ((color === null || color === void 0 ? void 0 : color.type) === 'linear-gradient') {
167
+ const items = [];
168
+ if (typeof color.angle === 'number') {
169
+ items.push(`${color.angle}deg`);
170
+ }
171
+ else {
172
+ items.push(`180deg`);
173
+ }
174
+ if (Array.isArray(color.stops)) {
175
+ color.stops.forEach((stop) => {
176
+ items.push(`${stop.color} ${stop.offset * 100}%`);
177
+ });
178
+ }
179
+ css = `linear-gradient(${items.join(', ')})`;
180
+ }
181
+ else if ((color === null || color === void 0 ? void 0 : color.type) === 'radial-gradient') {
182
+ const items = [];
183
+ if (Array.isArray(color.stops)) {
184
+ color.stops.forEach((stop) => {
185
+ items.push(`${stop.color} ${stop.offset * 100}%`);
186
+ });
187
+ }
188
+ css = `radial-gradient(circle, ${items.join(', ')})`;
189
+ }
190
+ return css;
191
+ }
192
+ export function colorToLinearGradientCSS(color) {
193
+ let css = 'transparent';
194
+ if (typeof color === 'string') {
195
+ css = color;
196
+ }
197
+ else if ((color === null || color === void 0 ? void 0 : color.type) === 'radial-gradient' || (color === null || color === void 0 ? void 0 : color.type) === 'linear-gradient') {
198
+ const items = [];
199
+ if (Array.isArray(color.stops) && color.stops.length > 0) {
200
+ color.stops.forEach((stop, i) => {
201
+ items.push(`${stop.color} ${stop.offset * 100}%`);
202
+ if (i === color.stops.length - 1 && stop.offset < 1) {
203
+ items.push(`${stop.color} ${stop.offset * 100}%`);
204
+ }
205
+ });
206
+ css = `linear-gradient(90deg, ${items.join(', ')})`;
207
+ }
208
+ }
209
+ return css;
210
+ }
211
+ export function mergeHexColorAlpha(hex, alpha) {
212
+ if (alpha === 1) {
213
+ return hex;
214
+ }
215
+ let hexAlpha = 1;
216
+ const regHex1 = /^\#[0-9a-f]{6,6}$/i;
217
+ const regHex2 = /^\#[0-9a-f]{8,8}$/i;
218
+ let result = hex;
219
+ if (regHex1.test(hex)) {
220
+ hexAlpha = parseInt(hex.substring(5, 7).replace(/^\#/, '0x'));
221
+ }
222
+ else if (regHex2.test(hex)) {
223
+ hexAlpha = parseInt(hex.substring(7, 9).replace(/^\#/, '0x'));
224
+ result = hex.substring(0, 7);
225
+ }
226
+ hexAlpha = hexAlpha * alpha;
227
+ if (regHex1.test(result) && hexAlpha > 0 && hexAlpha < 1) {
228
+ const aHexNum = Math.max(0, Math.min(255, Math.ceil(hexAlpha * 256)));
229
+ result = `${result.toUpperCase()}${aHexNum.toString(16).toUpperCase()}`;
230
+ }
231
+ return result;
232
+ }
@@ -0,0 +1,2 @@
1
+ import type { DefaultElementDetailConfig } from '@idraw/types';
2
+ export declare function getDefaultElementDetailConfig(): DefaultElementDetailConfig;
@@ -0,0 +1,22 @@
1
+ export function getDefaultElementDetailConfig() {
2
+ const config = {
3
+ boxSizing: 'center-line',
4
+ borderWidth: 0,
5
+ borderColor: '#000000',
6
+ shadowColor: '#000000',
7
+ borderRadius: 0,
8
+ borderDash: [],
9
+ shadowOffsetX: 0,
10
+ shadowOffsetY: 0,
11
+ shadowBlur: 0,
12
+ opacity: 1,
13
+ color: '#000000',
14
+ textAlign: 'left',
15
+ verticalAlign: 'top',
16
+ fontSize: 16,
17
+ lineHeight: 20,
18
+ fontFamily: 'sans-serif',
19
+ fontWeight: 400
20
+ };
21
+ return config;
22
+ }
@@ -139,7 +139,8 @@ export class Context2D {
139
139
  return this._ctx.getLineDash();
140
140
  }
141
141
  setLineDash(nums) {
142
- return this._ctx.setLineDash(nums.map((n) => this.$doPixelRatio(n)));
142
+ const dash = nums.map((n) => this.$doPixelRatio(n));
143
+ return this._ctx.setLineDash(dash);
143
144
  }
144
145
  stroke(path) {
145
146
  return path ? this._ctx.stroke(path) : this._ctx.stroke();
@@ -44,54 +44,58 @@ export function calcElementSizeController(elemSize, opts) {
44
44
  const topRightCenter = vertexes[1];
45
45
  const bottomRightCenter = vertexes[2];
46
46
  const bottomLeftCenter = vertexes[3];
47
- const topSize = createControllerElementSizeFromCenter(topCenter, { size: ctrlSize, angle: totalAngle });
48
- const rightSize = createControllerElementSizeFromCenter(rightCenter, { size: ctrlSize, angle: totalAngle });
49
- const bottomSize = createControllerElementSizeFromCenter(bottomCenter, { size: ctrlSize, angle: totalAngle });
50
- const leftSize = createControllerElementSizeFromCenter(leftCenter, { size: ctrlSize, angle: totalAngle });
51
47
  const topLeftSize = createControllerElementSizeFromCenter(topLeftCenter, { size: ctrlSize, angle: totalAngle });
52
48
  const topRightSize = createControllerElementSizeFromCenter(topRightCenter, { size: ctrlSize, angle: totalAngle });
53
49
  const bottomLeftSize = createControllerElementSizeFromCenter(bottomLeftCenter, { size: ctrlSize, angle: totalAngle });
54
50
  const bottomRightSize = createControllerElementSizeFromCenter(bottomRightCenter, { size: ctrlSize, angle: totalAngle });
51
+ const topLeftVertexes = calcElementVertexes(topLeftSize);
52
+ const topRightVertexes = calcElementVertexes(topRightSize);
53
+ const bottomLeftVertexes = calcElementVertexes(bottomLeftSize);
54
+ const bottomRightVertexes = calcElementVertexes(bottomRightSize);
55
+ const topVertexes = [topLeftVertexes[1], topRightVertexes[0], topRightVertexes[3], topLeftVertexes[2]];
56
+ const rightVertexes = [topRightVertexes[3], topRightVertexes[2], bottomRightVertexes[1], bottomRightVertexes[0]];
57
+ const bottomVertexes = [bottomLeftVertexes[1], bottomRightVertexes[0], bottomRightVertexes[3], bottomLeftVertexes[2]];
58
+ const leftVertexes = [topLeftVertexes[3], topLeftVertexes[2], bottomLeftVertexes[1], bottomLeftVertexes[0]];
55
59
  const sizeController = {
56
60
  elementWrapper: vertexes,
57
61
  left: {
58
62
  type: 'left',
59
- vertexes: calcElementVertexes(leftSize),
63
+ vertexes: leftVertexes,
60
64
  center: leftCenter
61
65
  },
62
66
  right: {
63
67
  type: 'right',
64
- vertexes: calcElementVertexes(rightSize),
68
+ vertexes: rightVertexes,
65
69
  center: rightCenter
66
70
  },
67
71
  top: {
68
72
  type: 'top',
69
- vertexes: calcElementVertexes(topSize),
73
+ vertexes: topVertexes,
70
74
  center: topCenter
71
75
  },
72
76
  bottom: {
73
77
  type: 'bottom',
74
- vertexes: calcElementVertexes(bottomSize),
78
+ vertexes: bottomVertexes,
75
79
  center: bottomCenter
76
80
  },
77
81
  topLeft: {
78
82
  type: 'top-left',
79
- vertexes: calcElementVertexes(topLeftSize),
83
+ vertexes: topLeftVertexes,
80
84
  center: topLeftCenter
81
85
  },
82
86
  topRight: {
83
87
  type: 'top-right',
84
- vertexes: calcElementVertexes(topRightSize),
88
+ vertexes: topRightVertexes,
85
89
  center: topRightCenter
86
90
  },
87
91
  bottomLeft: {
88
92
  type: 'bottom-left',
89
- vertexes: calcElementVertexes(bottomLeftSize),
93
+ vertexes: bottomLeftVertexes,
90
94
  center: bottomLeftCenter
91
95
  },
92
96
  bottomRight: {
93
97
  type: 'bottom-right',
94
- vertexes: calcElementVertexes(bottomRightSize),
98
+ vertexes: bottomRightVertexes,
95
99
  center: bottomRightCenter
96
100
  }
97
101
  };
@@ -1,4 +1,4 @@
1
- import type { Data, Element, Elements, ElementType, ViewContextSize, ViewSizeInfo, RecursivePartial } from '@idraw/types';
1
+ import type { Data, Element, Elements, ElementType, ElementSize, ViewContextSize, ViewSizeInfo, RecursivePartial, ElementAssets, ElementAssetsItem, LoadElementType } from '@idraw/types';
2
2
  export declare function getSelectedElementUUIDs(data: Data, indexes: Array<number | string>): string[];
3
3
  export declare function validateElements(elements: Array<Element<ElementType>>): boolean;
4
4
  export declare function calcElementsContextSize(elements: Array<Element<ElementType>>, opts?: {
@@ -15,4 +15,12 @@ export declare function getElemenetsAssetIds(elements: Elements): string[];
15
15
  export declare function findElementFromList(uuid: string, list: Element<ElementType>[]): Element<ElementType> | null;
16
16
  export declare function findElementsFromList(uuids: string[], list: Element<ElementType>[]): Element<ElementType>[];
17
17
  export declare function getGroupQueueFromList(uuid: string, elements: Element<ElementType>[]): Element<'group'>[];
18
- export declare function updateElementInList(uuid: string, updateContent: RecursivePartial<Element<ElementType>>, elements: Element<ElementType>[]): Element<ElementType>[];
18
+ export declare function updateElementInList(uuid: string, updateContent: RecursivePartial<Element<ElementType>>, elements: Element[]): Element | null;
19
+ export declare function getElementSize(elem: Element): ElementSize;
20
+ export declare function mergeElementAsset<T extends Element<LoadElementType>>(element: T, assets: ElementAssets): T;
21
+ export declare function filterElementAsset<T extends Element<LoadElementType>>(element: T): {
22
+ element: T;
23
+ assetId: string | null;
24
+ assetItem: ElementAssetsItem | null;
25
+ };
26
+ export declare function isResourceElement(elem: Element): boolean;
@@ -1,5 +1,6 @@
1
1
  import { rotateElementVertexes } from './rotate';
2
- import { isAssetId } from './uuid';
2
+ import { isAssetId, createAssetId } from './uuid';
3
+ import { istype } from './istype';
3
4
  function getGroupUUIDs(elements, index) {
4
5
  var _a;
5
6
  const uuids = [];
@@ -208,6 +209,7 @@ export function getGroupQueueFromList(uuid, elements) {
208
209
  return groupQueue;
209
210
  }
210
211
  function mergeElement(originElem, updateContent) {
212
+ var _a;
211
213
  const commonKeys = Object.keys(updateContent);
212
214
  for (let i = 0; i < commonKeys.length; i++) {
213
215
  const commonKey = commonKeys[i];
@@ -215,11 +217,24 @@ function mergeElement(originElem, updateContent) {
215
217
  originElem[commonKey] = updateContent[commonKey];
216
218
  }
217
219
  else if (['detail', 'operations'].includes(commonKey)) {
218
- if (istype.json(updateContent[commonKey]) && istype.json(originElem[commonKey])) {
219
- originElem[commonKey] = Object.assign(Object.assign({}, originElem[commonKey]), updateContent[commonKey]);
220
+ if (istype.json(updateContent[commonKey])) {
221
+ if (!(originElem === null || originElem === void 0 ? void 0 : originElem.hasOwnProperty(commonKey))) {
222
+ originElem[commonKey] = {};
223
+ }
224
+ if (istype.json(originElem[commonKey])) {
225
+ originElem[commonKey] = Object.assign(Object.assign({}, originElem[commonKey]), updateContent[commonKey]);
226
+ }
220
227
  }
221
- else if (istype.array(updateContent[commonKey]) && istype.array(originElem[commonKey])) {
222
- originElem[commonKey] = Object.assign(Object.assign({}, originElem[commonKey]), updateContent[commonKey]);
228
+ else if (istype.array(updateContent[commonKey])) {
229
+ if (!(originElem === null || originElem === void 0 ? void 0 : originElem.hasOwnProperty(commonKey))) {
230
+ originElem[commonKey] = [];
231
+ }
232
+ if (istype.array(originElem[commonKey])) {
233
+ (_a = updateContent === null || updateContent === void 0 ? void 0 : updateContent[commonKey]) === null || _a === void 0 ? void 0 : _a.forEach((item, i) => {
234
+ originElem[commonKey][i] = item;
235
+ });
236
+ originElem[commonKey] = [...originElem[commonKey], ...updateContent[commonKey]];
237
+ }
223
238
  }
224
239
  }
225
240
  }
@@ -227,15 +242,89 @@ function mergeElement(originElem, updateContent) {
227
242
  }
228
243
  export function updateElementInList(uuid, updateContent, elements) {
229
244
  var _a;
245
+ let targetElement = null;
230
246
  for (let i = 0; i < elements.length; i++) {
231
247
  const elem = elements[i];
232
248
  if (elem.uuid === uuid) {
233
249
  mergeElement(elem, updateContent);
250
+ targetElement = elem;
234
251
  break;
235
252
  }
236
253
  else if (elem.type === 'group') {
237
- updateElementInList(uuid, updateContent, ((_a = elem === null || elem === void 0 ? void 0 : elem.detail) === null || _a === void 0 ? void 0 : _a.children) || []);
254
+ targetElement = updateElementInList(uuid, updateContent, ((_a = elem === null || elem === void 0 ? void 0 : elem.detail) === null || _a === void 0 ? void 0 : _a.children) || []);
238
255
  }
239
256
  }
240
- return elements;
257
+ return targetElement;
258
+ }
259
+ export function getElementSize(elem) {
260
+ const { x, y, w, h, angle } = elem;
261
+ const size = { x, y, w, h, angle };
262
+ return size;
263
+ }
264
+ export function mergeElementAsset(element, assets) {
265
+ const elem = element;
266
+ let assetId = null;
267
+ let assetItem = null;
268
+ if (elem.type === 'image') {
269
+ assetId = elem.detail.src;
270
+ }
271
+ else if (elem.type === 'svg') {
272
+ assetId = elem.detail.svg;
273
+ }
274
+ else if (elem.type === 'html') {
275
+ assetId = elem.detail.html;
276
+ }
277
+ if (assetId && (assetId === null || assetId === void 0 ? void 0 : assetId.startsWith('@assets/'))) {
278
+ assetItem = assets[assetId];
279
+ }
280
+ if ((assetItem === null || assetItem === void 0 ? void 0 : assetItem.type) === elem.type && typeof (assetItem === null || assetItem === void 0 ? void 0 : assetItem.value) === 'string' && (assetItem === null || assetItem === void 0 ? void 0 : assetItem.value)) {
281
+ if (elem.type === 'image') {
282
+ elem.detail.src = assetItem.value;
283
+ }
284
+ else if (elem.type === 'svg') {
285
+ elem.detail.svg = assetItem.value;
286
+ }
287
+ else if (elem.type === 'html') {
288
+ elem.detail.html = assetItem.value;
289
+ }
290
+ }
291
+ return elem;
292
+ }
293
+ export function filterElementAsset(element) {
294
+ let assetId = null;
295
+ let assetItem = null;
296
+ let resource = null;
297
+ if (element.type === 'image') {
298
+ resource = element.detail.src;
299
+ }
300
+ else if (element.type === 'svg') {
301
+ resource = element.detail.svg;
302
+ }
303
+ else if (element.type === 'html') {
304
+ resource = element.detail.html;
305
+ }
306
+ if (typeof resource === 'string' && !isAssetId(resource)) {
307
+ assetId = createAssetId(resource);
308
+ assetItem = {
309
+ type: element.type,
310
+ value: resource
311
+ };
312
+ if (element.type === 'image') {
313
+ element.detail.src = assetId;
314
+ }
315
+ else if (element.type === 'svg') {
316
+ element.detail.svg = assetId;
317
+ }
318
+ else if (element.type === 'html') {
319
+ element.detail.html = assetId;
320
+ }
321
+ }
322
+ return {
323
+ element,
324
+ assetId,
325
+ assetItem
326
+ };
327
+ }
328
+ export function isResourceElement(elem) {
329
+ return ['image', 'svg', 'html'].includes(elem === null || elem === void 0 ? void 0 : elem.type);
241
330
  }
@@ -3,4 +3,12 @@ export declare function downloadImageFromCanvas(canvas: HTMLCanvasElement, opts:
3
3
  filename: string;
4
4
  type: ImageType;
5
5
  }): void;
6
+ export declare function pickFile(opts: {
7
+ success: (data: {
8
+ file: File;
9
+ }) => void;
10
+ error?: (err: ErrorEvent) => void;
11
+ }): void;
12
+ export declare function parseFileToBase64(file: File): Promise<string | ArrayBuffer>;
13
+ export declare function parseFileToText(file: File): Promise<string | ArrayBuffer>;
6
14
  export {};
@@ -8,3 +8,59 @@ export function downloadImageFromCanvas(canvas, opts) {
8
8
  downloadClickEvent.initEvent('click', true, false);
9
9
  downloadLink.dispatchEvent(downloadClickEvent);
10
10
  }
11
+ export function pickFile(opts) {
12
+ const { success, error } = opts;
13
+ let input = document.createElement('input');
14
+ input.type = 'file';
15
+ input.addEventListener('change', function () {
16
+ var _a;
17
+ const file = (_a = input.files) === null || _a === void 0 ? void 0 : _a[0];
18
+ success({
19
+ file: file
20
+ });
21
+ input = null;
22
+ });
23
+ input.addEventListener('error', function (err) {
24
+ if (typeof error === 'function') {
25
+ error(err);
26
+ }
27
+ input = null;
28
+ });
29
+ input.click();
30
+ }
31
+ export function parseFileToBase64(file) {
32
+ return new Promise(function (resolve, reject) {
33
+ let reader = new FileReader();
34
+ reader.addEventListener('load', function () {
35
+ resolve(reader.result);
36
+ reader = null;
37
+ });
38
+ reader.addEventListener('error', function (err) {
39
+ reject(err);
40
+ reader = null;
41
+ });
42
+ reader.addEventListener('abort', function () {
43
+ reject(new Error('abort'));
44
+ reader = null;
45
+ });
46
+ reader.readAsDataURL(file);
47
+ });
48
+ }
49
+ export function parseFileToText(file) {
50
+ return new Promise(function (resolve, reject) {
51
+ let reader = new FileReader();
52
+ reader.addEventListener('load', function () {
53
+ resolve(reader.result);
54
+ reader = null;
55
+ });
56
+ reader.addEventListener('error', function (err) {
57
+ reject(err);
58
+ reader = null;
59
+ });
60
+ reader.addEventListener('abort', function () {
61
+ reject(new Error('abort'));
62
+ reader = null;
63
+ });
64
+ reader.readAsText(file);
65
+ });
66
+ }
@@ -0,0 +1,3 @@
1
+ import type { Matrix } from '@idraw/types';
2
+ export declare function matrixToRadian(matrix: Matrix): number | null;
3
+ export declare function matrixToAngle(matrix: Matrix): number | null;
@@ -0,0 +1,16 @@
1
+ export function matrixToRadian(matrix) {
2
+ if (matrix[1] != -1 * matrix[3] || matrix[4] != matrix[0] || matrix[0] * matrix[4] - matrix[3] * matrix[1] != 1) {
3
+ return null;
4
+ }
5
+ else {
6
+ return Math.acos(matrix[0]);
7
+ }
8
+ }
9
+ export function matrixToAngle(matrix) {
10
+ const radian = matrixToRadian(matrix);
11
+ if (typeof radian === 'number') {
12
+ const angle = (radian * 180) / Math.PI;
13
+ return angle;
14
+ }
15
+ return radian;
16
+ }
@@ -1,4 +1,7 @@
1
1
  export function formatNumber(num, opts) {
2
- const decimalPlaces = (opts === null || opts === void 0 ? void 0 : opts.decimalPlaces) || 2;
2
+ let decimalPlaces = 2;
3
+ if (typeof (opts === null || opts === void 0 ? void 0 : opts.decimalPlaces) !== 'undefined' && (opts === null || opts === void 0 ? void 0 : opts.decimalPlaces) >= 0) {
4
+ decimalPlaces = opts.decimalPlaces;
5
+ }
3
6
  return parseFloat(num.toFixed(decimalPlaces));
4
7
  }
@@ -1,6 +1,7 @@
1
1
  import type { ViewContext2D, PointSize, ElementSize, ViewRectVertexes, Element } from '@idraw/types';
2
2
  export declare function parseRadianToAngle(radian: number): number;
3
3
  export declare function parseAngleToRadian(angle: number): number;
4
+ export declare function rotateByCenter(ctx: ViewContext2D | CanvasRenderingContext2D | ViewContext2D, angle: number, center: PointSize, callback: (ctx: ViewContext2D | CanvasRenderingContext2D) => void): void;
4
5
  export declare function rotateElement(ctx: ViewContext2D | CanvasRenderingContext2D | ViewContext2D, elemSize: ElementSize, callback: (ctx: ViewContext2D | CanvasRenderingContext2D) => void): void;
5
6
  export declare function calcElementCenter(elem: ElementSize): PointSize;
6
7
  export declare function calcElementCenterFromVertexes(ves: ViewRectVertexes): PointSize;
@@ -5,9 +5,8 @@ export function parseRadianToAngle(radian) {
5
5
  export function parseAngleToRadian(angle) {
6
6
  return (angle / 180) * Math.PI;
7
7
  }
8
- export function rotateElement(ctx, elemSize, callback) {
9
- const center = calcElementCenter(elemSize);
10
- const radian = parseAngleToRadian(elemSize.angle || 0);
8
+ export function rotateByCenter(ctx, angle, center, callback) {
9
+ const radian = parseAngleToRadian(angle || 0);
11
10
  if (center && (radian > 0 || radian < 0)) {
12
11
  ctx.translate(center.x, center.y);
13
12
  ctx.rotate(radian);
@@ -20,6 +19,12 @@ export function rotateElement(ctx, elemSize, callback) {
20
19
  ctx.translate(-center.x, -center.y);
21
20
  }
22
21
  }
22
+ export function rotateElement(ctx, elemSize, callback) {
23
+ const center = calcElementCenter(elemSize);
24
+ rotateByCenter(ctx, elemSize.angle || 0, center, () => {
25
+ callback(ctx);
26
+ });
27
+ }
23
28
  export function calcElementCenter(elem) {
24
29
  const p = {
25
30
  x: elem.x + elem.w / 2,
@@ -0,0 +1,5 @@
1
+ import type { Element, ViewScaleInfo, ViewSizeInfo, ViewBoxSize } from '@idraw/types';
2
+ export declare function calcViewBoxSize(viewElem: Element, opts: {
3
+ viewScaleInfo: ViewScaleInfo;
4
+ viewSizeInfo: ViewSizeInfo;
5
+ }): ViewBoxSize;
@@ -0,0 +1,48 @@
1
+ import { getDefaultElementDetailConfig } from './config';
2
+ const defaultElemConfig = getDefaultElementDetailConfig();
3
+ export function calcViewBoxSize(viewElem, opts) {
4
+ const { viewScaleInfo } = opts;
5
+ const { scale } = viewScaleInfo;
6
+ let { borderRadius, boxSizing = defaultElemConfig.boxSizing, borderWidth } = viewElem.detail;
7
+ if (typeof borderWidth !== 'number') {
8
+ borderRadius = 0;
9
+ }
10
+ let { x, y, w, h } = viewElem;
11
+ let radiusList = [0, 0, 0, 0];
12
+ if (typeof borderRadius === 'number') {
13
+ const br = borderRadius * scale;
14
+ radiusList = [br, br, br, br];
15
+ }
16
+ else if (Array.isArray(borderRadius) && (borderRadius === null || borderRadius === void 0 ? void 0 : borderRadius.length) === 4) {
17
+ radiusList = [borderRadius[0] * scale, borderRadius[1] * scale, borderRadius[2] * scale, borderRadius[3] * scale];
18
+ }
19
+ let bw = 0;
20
+ if (typeof borderWidth === 'number') {
21
+ bw = (borderWidth || 1) * scale;
22
+ }
23
+ if (boxSizing === 'border-box') {
24
+ x = viewElem.x + bw / 2;
25
+ y = viewElem.y + bw / 2;
26
+ w = viewElem.w - bw;
27
+ h = viewElem.h - bw;
28
+ }
29
+ else if (boxSizing === 'content-box') {
30
+ x = viewElem.x - bw / 2;
31
+ y = viewElem.y - bw / 2;
32
+ w = viewElem.w + bw;
33
+ h = viewElem.h + bw;
34
+ }
35
+ else {
36
+ x = viewElem.x;
37
+ y = viewElem.y;
38
+ w = viewElem.w;
39
+ h = viewElem.h;
40
+ }
41
+ return {
42
+ x,
43
+ y,
44
+ w,
45
+ h,
46
+ radiusList
47
+ };
48
+ }