@idraw/renderer 0.4.0-beta.39 → 0.4.0-beta.40

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.
@@ -0,0 +1,43 @@
1
+ import type { Point, Data, Element, ElementType, ViewCalculator, ViewCalculatorOptions, ViewScaleInfo, ViewSizeInfo, ViewRectInfo, ModifyOptions, VirtualFlatItem } from '@idraw/types';
2
+ export declare class Calculator implements ViewCalculator {
3
+ #private;
4
+ constructor(opts: ViewCalculatorOptions);
5
+ toGridNum(num: number, opts?: {
6
+ ignore?: boolean;
7
+ }): number;
8
+ destroy(): void;
9
+ needRender(elem: Element<ElementType>): boolean;
10
+ getPointElement(p: Point, opts: {
11
+ data: Data;
12
+ viewScaleInfo: ViewScaleInfo;
13
+ viewSizeInfo: ViewSizeInfo;
14
+ }): {
15
+ index: number;
16
+ element: null | Element<ElementType>;
17
+ groupQueueIndex: number;
18
+ };
19
+ resetVirtualFlatItemMap(data: Data, opts: {
20
+ viewScaleInfo: ViewScaleInfo;
21
+ viewSizeInfo: ViewSizeInfo;
22
+ }): void;
23
+ updateVisiableStatus(opts: {
24
+ viewScaleInfo: ViewScaleInfo;
25
+ viewSizeInfo: ViewSizeInfo;
26
+ }): void;
27
+ calcViewRectInfoFromOrigin(uuid: string, opts: {
28
+ checkVisible?: boolean;
29
+ viewScaleInfo: ViewScaleInfo;
30
+ viewSizeInfo: ViewSizeInfo;
31
+ }): ViewRectInfo | null;
32
+ calcViewRectInfoFromRange(uuid: string, opts: {
33
+ checkVisible?: boolean;
34
+ viewScaleInfo: ViewScaleInfo;
35
+ viewSizeInfo: ViewSizeInfo;
36
+ }): ViewRectInfo | null;
37
+ modifyVirtualFlatItemMap(data: Data, opts: {
38
+ modifyOptions: ModifyOptions;
39
+ viewScaleInfo: ViewScaleInfo;
40
+ viewSizeInfo: ViewSizeInfo;
41
+ }): void;
42
+ getVirtualFlatItem(uuid: string): VirtualFlatItem | null;
43
+ }
@@ -0,0 +1,168 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _Calculator_opts, _Calculator_store;
13
+ import { is, getViewPointAtElement, Store, calcViewPointSize, findElementFromListByPosition, getGroupQueueByElementPosition, calcElementOriginRectInfo, originRectInfoToRangeRectInfo } from '@idraw/util';
14
+ import { sortElementsViewVisiableInfoMap, updateVirtualFlatItemMapStatus } from './view-visible';
15
+ import { calcVirtualFlatDetail } from './virtual-flat';
16
+ export class Calculator {
17
+ constructor(opts) {
18
+ _Calculator_opts.set(this, void 0);
19
+ _Calculator_store.set(this, void 0);
20
+ __classPrivateFieldSet(this, _Calculator_opts, opts, "f");
21
+ __classPrivateFieldSet(this, _Calculator_store, new Store({
22
+ defaultStorage: {
23
+ virtualFlatItemMap: {},
24
+ visibleCount: 0,
25
+ invisibleCount: 0
26
+ }
27
+ }), "f");
28
+ }
29
+ toGridNum(num, opts) {
30
+ if ((opts === null || opts === void 0 ? void 0 : opts.ignore) === true) {
31
+ return num;
32
+ }
33
+ return Math.round(num);
34
+ }
35
+ destroy() {
36
+ __classPrivateFieldSet(this, _Calculator_opts, null, "f");
37
+ }
38
+ needRender(elem) {
39
+ const virtualFlatItemMap = __classPrivateFieldGet(this, _Calculator_store, "f").get('virtualFlatItemMap');
40
+ const info = virtualFlatItemMap[elem.uuid];
41
+ if (!info) {
42
+ return true;
43
+ }
44
+ return info.isVisibleInView;
45
+ }
46
+ getPointElement(p, opts) {
47
+ const context2d = __classPrivateFieldGet(this, _Calculator_opts, "f").tempContext;
48
+ return getViewPointAtElement(p, Object.assign(Object.assign({}, opts), { context2d }));
49
+ }
50
+ resetVirtualFlatItemMap(data, opts) {
51
+ if (data) {
52
+ const { virtualFlatItemMap, invisibleCount, visibleCount } = sortElementsViewVisiableInfoMap(data.elements, Object.assign(Object.assign({}, opts), {
53
+ tempContext: __classPrivateFieldGet(this, _Calculator_opts, "f").tempContext
54
+ }));
55
+ __classPrivateFieldGet(this, _Calculator_store, "f").set('virtualFlatItemMap', virtualFlatItemMap);
56
+ __classPrivateFieldGet(this, _Calculator_store, "f").set('invisibleCount', invisibleCount);
57
+ __classPrivateFieldGet(this, _Calculator_store, "f").set('visibleCount', visibleCount);
58
+ }
59
+ }
60
+ updateVisiableStatus(opts) {
61
+ const { virtualFlatItemMap, invisibleCount, visibleCount } = updateVirtualFlatItemMapStatus(__classPrivateFieldGet(this, _Calculator_store, "f").get('virtualFlatItemMap'), opts);
62
+ __classPrivateFieldGet(this, _Calculator_store, "f").set('virtualFlatItemMap', virtualFlatItemMap);
63
+ __classPrivateFieldGet(this, _Calculator_store, "f").set('invisibleCount', invisibleCount);
64
+ __classPrivateFieldGet(this, _Calculator_store, "f").set('visibleCount', visibleCount);
65
+ }
66
+ calcViewRectInfoFromOrigin(uuid, opts) {
67
+ const infoData = __classPrivateFieldGet(this, _Calculator_store, "f").get('virtualFlatItemMap')[uuid];
68
+ if (!(infoData === null || infoData === void 0 ? void 0 : infoData.originRectInfo)) {
69
+ return null;
70
+ }
71
+ const { checkVisible, viewScaleInfo, viewSizeInfo } = opts;
72
+ const { center, left, right, bottom, top, topLeft, topRight, bottomLeft, bottomRight } = infoData.originRectInfo;
73
+ if (checkVisible === true && infoData.isVisibleInView === false) {
74
+ return null;
75
+ }
76
+ const calcOpts = { viewScaleInfo, viewSizeInfo };
77
+ const viewRectInfo = {
78
+ center: calcViewPointSize(center, calcOpts),
79
+ left: calcViewPointSize(left, calcOpts),
80
+ right: calcViewPointSize(right, calcOpts),
81
+ bottom: calcViewPointSize(bottom, calcOpts),
82
+ top: calcViewPointSize(top, calcOpts),
83
+ topLeft: calcViewPointSize(topLeft, calcOpts),
84
+ topRight: calcViewPointSize(topRight, calcOpts),
85
+ bottomLeft: calcViewPointSize(bottomLeft, calcOpts),
86
+ bottomRight: calcViewPointSize(bottomRight, calcOpts)
87
+ };
88
+ return viewRectInfo;
89
+ }
90
+ calcViewRectInfoFromRange(uuid, opts) {
91
+ const infoData = __classPrivateFieldGet(this, _Calculator_store, "f").get('virtualFlatItemMap')[uuid];
92
+ if (!(infoData === null || infoData === void 0 ? void 0 : infoData.originRectInfo)) {
93
+ return null;
94
+ }
95
+ const { checkVisible, viewScaleInfo, viewSizeInfo } = opts;
96
+ const { center, left, right, bottom, top, topLeft, topRight, bottomLeft, bottomRight } = infoData.rangeRectInfo;
97
+ if (checkVisible === true && infoData.isVisibleInView === false) {
98
+ return null;
99
+ }
100
+ const calcOpts = { viewScaleInfo, viewSizeInfo };
101
+ const viewRectInfo = {
102
+ center: calcViewPointSize(center, calcOpts),
103
+ left: calcViewPointSize(left, calcOpts),
104
+ right: calcViewPointSize(right, calcOpts),
105
+ bottom: calcViewPointSize(bottom, calcOpts),
106
+ top: calcViewPointSize(top, calcOpts),
107
+ topLeft: calcViewPointSize(topLeft, calcOpts),
108
+ topRight: calcViewPointSize(topRight, calcOpts),
109
+ bottomLeft: calcViewPointSize(bottomLeft, calcOpts),
110
+ bottomRight: calcViewPointSize(bottomRight, calcOpts)
111
+ };
112
+ return viewRectInfo;
113
+ }
114
+ modifyVirtualFlatItemMap(data, opts) {
115
+ const { modifyOptions, viewScaleInfo, viewSizeInfo } = opts;
116
+ const { type, content } = modifyOptions;
117
+ const list = data.elements;
118
+ const virtualFlatItemMap = __classPrivateFieldGet(this, _Calculator_store, "f").get('virtualFlatItemMap');
119
+ if (type === 'deleteElement') {
120
+ const { element } = content;
121
+ const uuids = [];
122
+ const _walk = (e) => {
123
+ uuids.push(e.uuid);
124
+ if (e.type === 'group' && Array.isArray(e.detail.children)) {
125
+ e.detail.children.forEach((child) => {
126
+ _walk(child);
127
+ });
128
+ }
129
+ };
130
+ _walk(element);
131
+ uuids.forEach((uuid) => {
132
+ delete virtualFlatItemMap[uuid];
133
+ });
134
+ __classPrivateFieldGet(this, _Calculator_store, "f").set('virtualFlatItemMap', virtualFlatItemMap);
135
+ }
136
+ else if (type === 'addElement' || type === 'updateElement') {
137
+ const { position } = content;
138
+ const element = findElementFromListByPosition(position, data.elements);
139
+ const groupQueue = getGroupQueueByElementPosition(list, position);
140
+ if (element) {
141
+ if (type === 'updateElement' && element.type === 'group') {
142
+ this.resetVirtualFlatItemMap(data, { viewScaleInfo, viewSizeInfo });
143
+ }
144
+ else {
145
+ const originRectInfo = calcElementOriginRectInfo(element, {
146
+ groupQueue: groupQueue || []
147
+ });
148
+ const newVirtualFlatItem = Object.assign({ type: element.type, originRectInfo, rangeRectInfo: is.angle(element.angle) ? originRectInfoToRangeRectInfo(originRectInfo) : originRectInfo, isVisibleInView: true, position: [...position] }, calcVirtualFlatDetail(element, {
149
+ tempContext: __classPrivateFieldGet(this, _Calculator_opts, "f").tempContext
150
+ }));
151
+ virtualFlatItemMap[element.uuid] = newVirtualFlatItem;
152
+ __classPrivateFieldGet(this, _Calculator_store, "f").set('virtualFlatItemMap', virtualFlatItemMap);
153
+ if (type === 'updateElement') {
154
+ this.updateVisiableStatus({ viewScaleInfo, viewSizeInfo });
155
+ }
156
+ }
157
+ }
158
+ }
159
+ else if (type === 'moveElement') {
160
+ this.resetVirtualFlatItemMap(data, { viewScaleInfo, viewSizeInfo });
161
+ }
162
+ }
163
+ getVirtualFlatItem(uuid) {
164
+ const itemMap = __classPrivateFieldGet(this, _Calculator_store, "f").get('virtualFlatItemMap');
165
+ return itemMap[uuid] || null;
166
+ }
167
+ }
168
+ _Calculator_opts = new WeakMap(), _Calculator_store = new WeakMap();
@@ -1,4 +1,5 @@
1
1
  import { ViewContext2D, Element, ElementType, ElementSize, ViewScaleInfo, ViewSizeInfo } from '@idraw/types';
2
+ import { Calculator } from '../calculator';
2
3
  export declare function getOpacity(elem: Element): number;
3
4
  export declare function drawBox(ctx: ViewContext2D, viewElem: Element, opts: {
4
5
  originElem: Element;
@@ -15,8 +16,10 @@ export declare function drawBoxBackground(ctx: ViewContext2D, viewElem: Element<
15
16
  viewSizeInfo: ViewSizeInfo;
16
17
  }): void;
17
18
  export declare function drawBoxBorder(ctx: ViewContext2D, viewElem: Element<ElementType>, opts: {
19
+ originElem: Element;
18
20
  viewScaleInfo: ViewScaleInfo;
19
21
  viewSizeInfo: ViewSizeInfo;
22
+ calculator?: Calculator;
20
23
  }): void;
21
24
  export declare function drawBoxShadow(ctx: ViewContext2D, viewElem: Element<ElementType>, opts: {
22
25
  viewScaleInfo: ViewScaleInfo;
@@ -18,7 +18,7 @@ export function drawBox(ctx, viewElem, opts) {
18
18
  ctx.globalAlpha = opacity;
19
19
  drawBoxBackground(ctx, viewElem, { pattern, viewScaleInfo, viewSizeInfo });
20
20
  renderContent === null || renderContent === void 0 ? void 0 : renderContent();
21
- drawBoxBorder(ctx, viewElem, { viewScaleInfo, viewSizeInfo });
21
+ drawBoxBorder(ctx, viewElem, { originElem, viewScaleInfo, viewSizeInfo });
22
22
  ctx.globalAlpha = parentOpacity;
23
23
  };
24
24
  if (clipPath) {
@@ -79,7 +79,12 @@ function drawClipPathStroke(ctx, viewElem, opts) {
79
79
  const { renderContent, originElem, calcElemSize, viewSizeInfo, parentOpacity } = opts;
80
80
  const totalScale = viewSizeInfo.devicePixelRatio;
81
81
  const { clipPath, clipPathStrokeColor, clipPathStrokeWidth } = (originElem === null || originElem === void 0 ? void 0 : originElem.detail) || {};
82
- if (clipPath && calcElemSize && clipPath.commands && typeof clipPathStrokeWidth === 'number' && clipPathStrokeWidth > 0 && clipPathStrokeColor) {
82
+ if (clipPath &&
83
+ calcElemSize &&
84
+ clipPath.commands &&
85
+ typeof clipPathStrokeWidth === 'number' &&
86
+ clipPathStrokeWidth > 0 &&
87
+ clipPathStrokeColor) {
83
88
  const { x, y, w, h } = calcElemSize;
84
89
  const { originW, originH, originX, originY } = clipPath;
85
90
  const scaleW = w / originW;
@@ -182,12 +187,17 @@ export function drawBoxBorder(ctx, viewElem, opts) {
182
187
  if (isColorStr(viewElem.detail.borderColor) === true) {
183
188
  borderColor = viewElem.detail.borderColor;
184
189
  }
185
- const { borderWidth, borderRadius, borderDash, boxSizing = defaultElemConfig.boxSizing } = viewElem.detail;
186
- let bw = 0;
187
- if (typeof borderWidth === 'number') {
188
- bw = borderWidth || 1;
190
+ const { borderDash, borderWidth, borderRadius, boxSizing = defaultElemConfig.boxSizing } = viewElem.detail;
191
+ let viewBorderDash = [];
192
+ if (Array.isArray(borderDash) && borderDash.length > 0) {
193
+ viewBorderDash = borderDash.map((num) => Math.ceil(num * scale));
194
+ }
195
+ if (viewBorderDash.length > 0) {
196
+ ctx.lineCap = 'butt';
197
+ }
198
+ else {
199
+ ctx.lineCap = 'square';
189
200
  }
190
- bw = bw * scale;
191
201
  let radiusList = [0, 0, 0, 0];
192
202
  if (typeof borderRadius === 'number') {
193
203
  const br = borderRadius * scale;
@@ -196,11 +206,12 @@ export function drawBoxBorder(ctx, viewElem, opts) {
196
206
  else if (Array.isArray(borderRadius) && (borderRadius === null || borderRadius === void 0 ? void 0 : borderRadius.length) === 4) {
197
207
  radiusList = [borderRadius[0] * scale, borderRadius[1] * scale, borderRadius[2] * scale, borderRadius[3] * scale];
198
208
  }
199
- ctx.strokeStyle = borderColor;
200
- let viewBorderDash = [];
201
- if (Array.isArray(borderDash) && borderDash.length > 0) {
202
- viewBorderDash = borderDash.map((num) => Math.ceil(num * scale));
209
+ let bw = 0;
210
+ if (typeof borderWidth === 'number') {
211
+ bw = borderWidth || 1;
203
212
  }
213
+ bw = bw * scale;
214
+ ctx.strokeStyle = borderColor;
204
215
  let borderTop = 0;
205
216
  let borderRight = 0;
206
217
  let borderBottom = 0;
@@ -285,12 +296,6 @@ export function drawBoxBorder(ctx, viewElem, opts) {
285
296
  w = viewElem.w;
286
297
  h = viewElem.h;
287
298
  }
288
- if (viewBorderDash.length > 0) {
289
- ctx.lineCap = 'butt';
290
- }
291
- else {
292
- ctx.lineCap = 'square';
293
- }
294
299
  w = Math.max(w, 1);
295
300
  h = Math.max(h, 1);
296
301
  radiusList = radiusList.map((r) => {
@@ -28,8 +28,6 @@ export function drawCircle(ctx, elem, opts) {
28
28
  const radiusB = b;
29
29
  if (bw > 0) {
30
30
  if (boxSizing === 'content-box') {
31
- a = a;
32
- b = b;
33
31
  }
34
32
  else if (boxSizing === 'center-line') {
35
33
  a = a - bw / 2;
@@ -39,6 +39,6 @@ export function drawLayout(ctx, layout, opts, renderContent) {
39
39
  if (layout.detail.overflow === 'hidden') {
40
40
  ctx.restore();
41
41
  }
42
- drawBoxBorder(ctx, viewElem, { viewScaleInfo, viewSizeInfo });
42
+ drawBoxBorder(ctx, viewElem, { originElem: elem, viewScaleInfo, viewSizeInfo });
43
43
  ctx.globalAlpha = parentOpacity;
44
44
  }
@@ -2,19 +2,12 @@ import { rotateElement, calcViewElementSize, enhanceFontFamliy } from '@idraw/ut
2
2
  import { is, isColorStr, getDefaultElementDetailConfig } from '@idraw/util';
3
3
  import { drawBox, drawBoxShadow } from './box';
4
4
  const detailConfig = getDefaultElementDetailConfig();
5
- function isTextWidthWithinErrorRange(w0, w1, scale) {
6
- if (scale < 0.5) {
7
- if (w0 < w1 && (w0 - w1) / w0 > -0.15) {
8
- return true;
9
- }
10
- }
11
- return w0 >= w1;
12
- }
13
5
  export function drawText(ctx, elem, opts) {
14
- const { viewScaleInfo, viewSizeInfo, parentOpacity } = opts;
6
+ const { viewScaleInfo, viewSizeInfo, parentOpacity, calculator } = opts;
15
7
  const { x, y, w, h, angle } = calcViewElementSize(elem, { viewScaleInfo }) || elem;
16
8
  const viewElem = Object.assign(Object.assign({}, elem), { x, y, w, h, angle });
17
9
  rotateElement(ctx, { x, y, w, h, angle }, () => {
10
+ var _a, _b;
18
11
  drawBoxShadow(ctx, viewElem, {
19
12
  viewScaleInfo,
20
13
  viewSizeInfo,
@@ -35,8 +28,6 @@ export function drawText(ctx, elem, opts) {
35
28
  if (fontSize < 2) {
36
29
  return;
37
30
  }
38
- const originLineHeight = detail.lineHeight || originFontSize;
39
- const lineHeight = originLineHeight * viewScaleInfo.scale;
40
31
  ctx.fillStyle = elem.detail.color || detailConfig.color;
41
32
  ctx.textBaseline = 'top';
42
33
  ctx.$setFont({
@@ -44,123 +35,25 @@ export function drawText(ctx, elem, opts) {
44
35
  fontSize: fontSize,
45
36
  fontFamily: enhanceFontFamliy(detail.fontFamily)
46
37
  });
47
- let detailText = detail.text.replace(/\r\n/gi, '\n');
48
- if (detail.textTransform === 'lowercase') {
49
- detailText = detailText.toLowerCase();
50
- }
51
- else if (detail.textTransform === 'uppercase') {
52
- detailText = detailText.toUpperCase();
53
- }
54
- const fontHeight = lineHeight;
55
- const detailTextList = detailText.split('\n');
56
- const lines = [];
57
- let lineNum = 0;
58
- detailTextList.forEach((itemText, idx) => {
59
- if (detail.minInlineSize === 'maxContent') {
60
- lines.push({
61
- text: itemText,
62
- width: ctx.$undoPixelRatio(ctx.measureText(itemText).width)
63
- });
64
- }
65
- else {
66
- let lineText = '';
67
- let splitStr = '';
68
- let tempStrList = itemText.split(splitStr);
69
- if (detail.wordBreak === 'normal') {
70
- const splitStr = ' ';
71
- const wordList = itemText.split(splitStr);
72
- tempStrList = [];
73
- wordList.forEach((word, idx) => {
74
- tempStrList.push(word);
75
- if (idx < wordList.length - 1) {
76
- tempStrList.push(splitStr);
77
- }
78
- });
38
+ {
39
+ const virtualTextDetail = calculator.getVirtualFlatItem(elem.uuid);
40
+ if (Array.isArray(virtualTextDetail === null || virtualTextDetail === void 0 ? void 0 : virtualTextDetail.textLines) && ((_a = virtualTextDetail === null || virtualTextDetail === void 0 ? void 0 : virtualTextDetail.textLines) === null || _a === void 0 ? void 0 : _a.length) > 0) {
41
+ if (detail.textShadowColor !== undefined && isColorStr(detail.textShadowColor)) {
42
+ ctx.shadowColor = detail.textShadowColor;
79
43
  }
80
- if (tempStrList.length === 1 && detail.overflow === 'visible') {
81
- lines.push({
82
- text: tempStrList[0],
83
- width: ctx.$undoPixelRatio(ctx.measureText(tempStrList[0]).width)
84
- });
44
+ if (detail.textShadowOffsetX !== undefined && is.number(detail.textShadowOffsetX)) {
45
+ ctx.shadowOffsetX = detail.textShadowOffsetX;
85
46
  }
86
- else if (tempStrList.length > 0) {
87
- for (let i = 0; i < tempStrList.length; i++) {
88
- if (isTextWidthWithinErrorRange(ctx.$doPixelRatio(w), ctx.measureText(lineText + tempStrList[i]).width, viewScaleInfo.scale)) {
89
- lineText += tempStrList[i] || '';
90
- }
91
- else {
92
- lines.push({
93
- text: lineText,
94
- width: ctx.$undoPixelRatio(ctx.measureText(lineText).width)
95
- });
96
- lineText = tempStrList[i] || '';
97
- lineNum++;
98
- }
99
- if ((lineNum + 1) * fontHeight > h && detail.overflow === 'hidden') {
100
- break;
101
- }
102
- if (tempStrList.length - 1 === i) {
103
- if ((lineNum + 1) * fontHeight <= h) {
104
- lines.push({
105
- text: lineText,
106
- width: ctx.$undoPixelRatio(ctx.measureText(lineText).width)
107
- });
108
- if (idx < detailTextList.length - 1) {
109
- lineNum++;
110
- }
111
- break;
112
- }
113
- }
114
- }
47
+ if (detail.textShadowOffsetY !== undefined && is.number(detail.textShadowOffsetY)) {
48
+ ctx.shadowOffsetY = detail.textShadowOffsetY;
115
49
  }
116
- else {
117
- lines.push({
118
- text: '',
119
- width: 0
120
- });
50
+ if (detail.textShadowBlur !== undefined && is.number(detail.textShadowBlur)) {
51
+ ctx.shadowBlur = detail.textShadowBlur;
121
52
  }
53
+ (_b = virtualTextDetail === null || virtualTextDetail === void 0 ? void 0 : virtualTextDetail.textLines) === null || _b === void 0 ? void 0 : _b.forEach((line) => {
54
+ ctx.fillText(line.text, x + line.x * viewScaleInfo.scale, y + line.y * viewScaleInfo.scale);
55
+ });
122
56
  }
123
- });
124
- let startY = 0;
125
- let eachLineStartY = 0;
126
- if (fontHeight > fontSize) {
127
- eachLineStartY = (fontHeight - fontSize) / 2;
128
- }
129
- if (lines.length * fontHeight < h) {
130
- if (elem.detail.verticalAlign === 'top') {
131
- startY = 0;
132
- }
133
- else if (elem.detail.verticalAlign === 'bottom') {
134
- startY += h - lines.length * fontHeight;
135
- }
136
- else {
137
- startY += (h - lines.length * fontHeight) / 2;
138
- }
139
- }
140
- {
141
- const _y = y + startY;
142
- if (detail.textShadowColor !== undefined && isColorStr(detail.textShadowColor)) {
143
- ctx.shadowColor = detail.textShadowColor;
144
- }
145
- if (detail.textShadowOffsetX !== undefined && is.number(detail.textShadowOffsetX)) {
146
- ctx.shadowOffsetX = detail.textShadowOffsetX;
147
- }
148
- if (detail.textShadowOffsetY !== undefined && is.number(detail.textShadowOffsetY)) {
149
- ctx.shadowOffsetY = detail.textShadowOffsetY;
150
- }
151
- if (detail.textShadowBlur !== undefined && is.number(detail.textShadowBlur)) {
152
- ctx.shadowBlur = detail.textShadowBlur;
153
- }
154
- lines.forEach((line, i) => {
155
- let _x = x;
156
- if (detail.textAlign === 'center') {
157
- _x = x + (w - line.width) / 2;
158
- }
159
- else if (detail.textAlign === 'right') {
160
- _x = x + (w - line.width);
161
- }
162
- ctx.fillText(line.text, _x, _y + fontHeight * i + eachLineStartY);
163
- });
164
57
  }
165
58
  }
166
59
  });
@@ -2,6 +2,8 @@ import { EventEmitter } from '@idraw/util';
2
2
  import type { LoadItemMap } from '@idraw/types';
3
3
  import { Loader } from './loader';
4
4
  import type { Data, BoardRenderer, RendererOptions, RendererEventMap, RendererDrawOptions } from '@idraw/types';
5
+ import { Calculator } from './calculator';
6
+ export { Calculator };
5
7
  export declare class Renderer extends EventEmitter<RendererEventMap> implements BoardRenderer {
6
8
  #private;
7
9
  constructor(opts: RendererOptions);
@@ -13,5 +15,6 @@ export declare class Renderer extends EventEmitter<RendererEventMap> implements
13
15
  setLoadItemMap(itemMap: LoadItemMap): void;
14
16
  getLoadItemMap(): LoadItemMap;
15
17
  getLoader(): Loader;
18
+ getCalculator(): Calculator;
16
19
  }
17
20
  export { drawCircle, drawRect, drawImage, drawSVG, drawHTML, drawText, drawGroup, drawElement, drawElementList, drawLayout, drawGlobalBackground } from './draw';
package/dist/esm/index.js CHANGED
@@ -9,18 +9,24 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _Renderer_instances, _Renderer_opts, _Renderer_loader, _Renderer_hasDestroyed, _Renderer_init;
12
+ var _Renderer_instances, _Renderer_opts, _Renderer_loader, _Renderer_calculator, _Renderer_hasDestroyed, _Renderer_init;
13
13
  import { EventEmitter } from '@idraw/util';
14
14
  import { drawElementList, drawLayout, drawGlobalBackground } from './draw/index';
15
15
  import { Loader } from './loader';
16
+ import { Calculator } from './calculator';
17
+ export { Calculator };
16
18
  export class Renderer extends EventEmitter {
17
19
  constructor(opts) {
18
20
  super();
19
21
  _Renderer_instances.add(this);
20
22
  _Renderer_opts.set(this, void 0);
21
23
  _Renderer_loader.set(this, new Loader());
24
+ _Renderer_calculator.set(this, void 0);
22
25
  _Renderer_hasDestroyed.set(this, false);
23
26
  __classPrivateFieldSet(this, _Renderer_opts, opts, "f");
27
+ __classPrivateFieldSet(this, _Renderer_calculator, new Calculator({
28
+ tempContext: opts.tempContext
29
+ }), "f");
24
30
  __classPrivateFieldGet(this, _Renderer_instances, "m", _Renderer_init).call(this);
25
31
  }
26
32
  isDestroyed() {
@@ -38,7 +44,8 @@ export class Renderer extends EventEmitter {
38
44
  }
39
45
  drawData(data, opts) {
40
46
  const loader = __classPrivateFieldGet(this, _Renderer_loader, "f");
41
- const { calculator, sharer } = __classPrivateFieldGet(this, _Renderer_opts, "f");
47
+ const calculator = __classPrivateFieldGet(this, _Renderer_calculator, "f");
48
+ const { sharer } = __classPrivateFieldGet(this, _Renderer_opts, "f");
42
49
  const viewContext = __classPrivateFieldGet(this, _Renderer_opts, "f").viewContext;
43
50
  viewContext.clearRect(0, 0, viewContext.canvas.width, viewContext.canvas.height);
44
51
  const parentElementSize = {
@@ -94,8 +101,11 @@ export class Renderer extends EventEmitter {
94
101
  getLoader() {
95
102
  return __classPrivateFieldGet(this, _Renderer_loader, "f");
96
103
  }
104
+ getCalculator() {
105
+ return __classPrivateFieldGet(this, _Renderer_calculator, "f");
106
+ }
97
107
  }
98
- _Renderer_opts = new WeakMap(), _Renderer_loader = new WeakMap(), _Renderer_hasDestroyed = new WeakMap(), _Renderer_instances = new WeakSet(), _Renderer_init = function _Renderer_init() {
108
+ _Renderer_opts = new WeakMap(), _Renderer_loader = new WeakMap(), _Renderer_calculator = new WeakMap(), _Renderer_hasDestroyed = new WeakMap(), _Renderer_instances = new WeakSet(), _Renderer_init = function _Renderer_init() {
99
109
  const loader = __classPrivateFieldGet(this, _Renderer_loader, "f");
100
110
  loader.on('load', (e) => {
101
111
  this.trigger('load', e);
@@ -0,0 +1,22 @@
1
+ import { Elements, ViewScaleInfo, ViewSizeInfo, ViewRectInfo, VirtualFlatItemMap, ViewContext2D } from '@idraw/types';
2
+ export declare function sortElementsViewVisiableInfoMap(elements: Elements, opts: {
3
+ viewScaleInfo: ViewScaleInfo;
4
+ viewSizeInfo: ViewSizeInfo;
5
+ tempContext: ViewContext2D;
6
+ }): {
7
+ virtualFlatItemMap: VirtualFlatItemMap;
8
+ visibleCount: number;
9
+ invisibleCount: number;
10
+ };
11
+ export declare function updateVirtualFlatItemMapStatus(virtualFlatItemMap: VirtualFlatItemMap, opts: {
12
+ viewScaleInfo: ViewScaleInfo;
13
+ viewSizeInfo: ViewSizeInfo;
14
+ }): {
15
+ virtualFlatItemMap: VirtualFlatItemMap;
16
+ visibleCount: number;
17
+ invisibleCount: number;
18
+ };
19
+ export declare function calcVisibleOriginCanvasRectInfo(opts: {
20
+ viewScaleInfo: ViewScaleInfo;
21
+ viewSizeInfo: ViewSizeInfo;
22
+ }): ViewRectInfo;
@@ -0,0 +1,63 @@
1
+ import { calcElementCenter } from '@idraw/util';
2
+ import { elementsToVirtualFlatMap } from '../virtual-flat';
3
+ export function sortElementsViewVisiableInfoMap(elements, opts) {
4
+ const { viewScaleInfo, viewSizeInfo, tempContext } = opts;
5
+ const visibleInfoMap = elementsToVirtualFlatMap(elements, { tempContext });
6
+ return updateVirtualFlatItemMapStatus(visibleInfoMap, { viewScaleInfo, viewSizeInfo });
7
+ }
8
+ function isRangeRectInfoCollide(info1, info2) {
9
+ const rect1MinX = Math.min(info1.topLeft.x, info1.topRight.x, info1.bottomLeft.x, info1.bottomRight.x);
10
+ const rect1MaxX = Math.max(info1.topLeft.x, info1.topRight.x, info1.bottomLeft.x, info1.bottomRight.x);
11
+ const rect1MinY = Math.min(info1.topLeft.y, info1.topRight.y, info1.bottomLeft.y, info1.bottomRight.y);
12
+ const rect1MaxY = Math.max(info1.topLeft.y, info1.topRight.y, info1.bottomLeft.y, info1.bottomRight.y);
13
+ const rect2MinX = Math.min(info2.topLeft.x, info2.topRight.x, info2.bottomLeft.x, info2.bottomRight.x);
14
+ const rect2MaxX = Math.max(info2.topLeft.x, info2.topRight.x, info2.bottomLeft.x, info2.bottomRight.x);
15
+ const rect2MinY = Math.min(info2.topLeft.y, info2.topRight.y, info2.bottomLeft.y, info2.bottomRight.y);
16
+ const rect2MaxY = Math.max(info2.topLeft.y, info2.topRight.y, info2.bottomLeft.y, info2.bottomRight.y);
17
+ if ((rect1MinX <= rect2MaxX && rect1MaxX >= rect2MinX && rect1MinY <= rect2MaxY && rect1MaxY >= rect2MinY) ||
18
+ (rect2MaxX <= rect1MaxY && rect2MaxX >= rect1MaxY && rect2MaxX <= rect1MaxY && rect2MaxX >= rect1MaxY)) {
19
+ return true;
20
+ }
21
+ return false;
22
+ }
23
+ export function updateVirtualFlatItemMapStatus(virtualFlatItemMap, opts) {
24
+ const canvasRectInfo = calcVisibleOriginCanvasRectInfo(opts);
25
+ let visibleCount = 0;
26
+ let invisibleCount = 0;
27
+ Object.keys(virtualFlatItemMap).forEach((uuid) => {
28
+ const info = virtualFlatItemMap[uuid];
29
+ info.isVisibleInView = isRangeRectInfoCollide(info.rangeRectInfo, canvasRectInfo);
30
+ info.isVisibleInView ? visibleCount++ : invisibleCount++;
31
+ });
32
+ return { virtualFlatItemMap, visibleCount, invisibleCount };
33
+ }
34
+ export function calcVisibleOriginCanvasRectInfo(opts) {
35
+ const { viewScaleInfo, viewSizeInfo } = opts;
36
+ const { scale, offsetTop, offsetLeft } = viewScaleInfo;
37
+ const { width, height } = viewSizeInfo;
38
+ const x = 0 - offsetLeft / scale;
39
+ const y = 0 - offsetTop / scale;
40
+ const w = width / scale;
41
+ const h = height / scale;
42
+ const center = calcElementCenter({ x, y, w, h });
43
+ const topLeft = { x, y };
44
+ const topRight = { x: x + w, y };
45
+ const bottomLeft = { x, y: y + h };
46
+ const bottomRight = { x: x + w, y: y + h };
47
+ const left = { x, y: center.y };
48
+ const top = { x: center.x, y };
49
+ const right = { x: x + w, y: center.y };
50
+ const bottom = { x: center.x, y: y + h };
51
+ const rectInfo = {
52
+ center,
53
+ topLeft,
54
+ topRight,
55
+ bottomLeft,
56
+ bottomRight,
57
+ left,
58
+ top,
59
+ right,
60
+ bottom
61
+ };
62
+ return rectInfo;
63
+ }
@@ -0,0 +1,7 @@
1
+ import { Element, Elements, VirtualFlatItemMap, VirtualFlatDetail, ViewContext2D } from '@idraw/types';
2
+ export declare function calcVirtualFlatDetail(elem: Element, opts: {
3
+ tempContext: ViewContext2D;
4
+ }): VirtualFlatDetail;
5
+ export declare function elementsToVirtualFlatMap(elements: Elements, opts: {
6
+ tempContext: ViewContext2D;
7
+ }): VirtualFlatItemMap;