@meta2d/core 1.1.21 → 1.1.23

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meta2d/core",
3
- "version": "1.1.21",
3
+ "version": "1.1.23",
4
4
  "description": "@meta2d/core: Powerful, Beautiful, Simple, Open - Web-Based 2D At Its Best .",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -81,6 +81,8 @@ export declare class Canvas {
81
81
  private lastAnimateRender;
82
82
  animateRendering: boolean;
83
83
  renderTimer: number;
84
+ private viewAnimation?;
85
+ private viewAnimationTimer?;
84
86
  initPens?: Pen[];
85
87
  pointSize: 8;
86
88
  pasteOffset: boolean;
@@ -153,6 +155,7 @@ export declare class Canvas {
153
155
  dropPens(pens: Pen[], e: Point): Promise<void>;
154
156
  randomCombineId(pen: Pen, pens: Pen[], parentId?: string): Pen;
155
157
  addPens(pens: Pen[], history?: boolean, abs?: boolean): Promise<Pen[]>;
158
+ addPensSync(pens: Pen[], history?: boolean, abs?: boolean): Pen[];
156
159
  ontouchstart: (e: TouchEvent) => void;
157
160
  ontouchmove: (event: TouchEvent) => void;
158
161
  ontouchend: (event: TouchEvent) => void;
@@ -305,6 +308,16 @@ export declare class Canvas {
305
308
  x: number;
306
309
  y: number;
307
310
  }): void;
311
+ animateView(options: {
312
+ x?: number;
313
+ y?: number;
314
+ scale?: number;
315
+ pen?: Pen;
316
+ duration?: number;
317
+ easing?: string;
318
+ center?: Point;
319
+ }): void;
320
+ private animateViewFrame;
308
321
  templateScale(scale: number, center?: {
309
322
  x: number;
310
323
  y: number;
@@ -4,7 +4,7 @@ import { calcRotate, distance, getDistance, hitPoint, PointType, PrevNextType, r
4
4
  import { calcCenter, calcRightBottom, calcRelativePoint, getRect, getRectOfPoints, pointInRect, pointInSimpleRect, rectInRect, rectToPoints, resizeRect, translateRect, pointInPolygon } from '../rect';
5
5
  import { EditType, globalStore, } from '../store';
6
6
  import { deepClone, fileToBase64, uploadFile, formatPadding, rgba, s8, toNumber, } from '../utils';
7
- import { inheritanceProps, defaultCursors, defaultDrawLineFns, HotkeyType, HoverType, MouseRight, rotatedCursors, } from '../data';
7
+ import { inheritanceProps, defaultCursors, defaultDrawLineFns, HotkeyType, HoverType, MouseRight, rotatedCursors, Direction, } from '../data';
8
8
  import { createOffscreen } from './offscreen';
9
9
  import { curve, mind, getLineLength, getLineRect, pointInLine, simplify, smoothLine, lineSegment, getLineR, lineInRect, } from '../diagrams';
10
10
  import { polyline, translatePolylineAnchor } from '../diagrams/line/polyline';
@@ -21,6 +21,8 @@ import { CanvasTemplate } from './canvasTemplate';
21
21
  import { getLinePoints } from '../diagrams/line';
22
22
  import { Popconfirm } from '../popconfirm';
23
23
  import { le5leTheme, themeKeys } from '../theme';
24
+ import { getFont } from '../pen/render';
25
+ import { getEasingFunction } from '../utils/easing';
24
26
  export const movingSuffix = '-moving';
25
27
  export class Canvas {
26
28
  parent;
@@ -81,6 +83,8 @@ export class Canvas {
81
83
  lastAnimateRender = 0;
82
84
  animateRendering = false;
83
85
  renderTimer;
86
+ viewAnimation;
87
+ viewAnimationTimer;
84
88
  initPens;
85
89
  pointSize = 8;
86
90
  pasteOffset = true;
@@ -124,7 +128,7 @@ export class Canvas {
124
128
  this.parent = parent;
125
129
  this.parentElement = parentElement;
126
130
  this.store = store;
127
- this.canvasTemplate = new CanvasTemplate(parentElement, store);
131
+ this.canvasTemplate = new CanvasTemplate(parentElement, store, this);
128
132
  this.canvasTemplate.canvas.style.zIndex = '1';
129
133
  this.canvasImageBottom = new CanvasImage(parentElement, store, true);
130
134
  this.canvasImageBottom.canvas.style.zIndex = '2';
@@ -414,6 +418,7 @@ export class Canvas {
414
418
  }
415
419
  };
416
420
  onwheel = (e) => {
421
+ this.viewAnimation = undefined;
417
422
  //输入模式不允许滚动
418
423
  if (this.inputDiv.contentEditable === 'true') {
419
424
  return;
@@ -1375,7 +1380,37 @@ export class Canvas {
1375
1380
  }
1376
1381
  return list;
1377
1382
  }
1383
+ addPensSync(pens, history, abs) {
1384
+ const list = [];
1385
+ // for (const pen of pens) {
1386
+ // if (!pen.id) {
1387
+ // pen.id = s8();
1388
+ // }
1389
+ // !pen.calculative && (pen.calculative = { canvas: this });
1390
+ // this.store.pens[pen.id] = pen;
1391
+ // }
1392
+ for (const pen of pens) {
1393
+ if (this.beforeAddPen && this.beforeAddPen(pen) != true) {
1394
+ continue;
1395
+ }
1396
+ if (abs && !pen.parentId) {
1397
+ pen.x = pen.x * this.store.data.scale + this.store.data.origin.x;
1398
+ pen.y = pen.y * this.store.data.scale + this.store.data.origin.y;
1399
+ pen.width = pen.width * this.store.data.scale;
1400
+ pen.height = pen.height * this.store.data.scale;
1401
+ }
1402
+ this.makePen(pen);
1403
+ list.push(pen);
1404
+ }
1405
+ this.render();
1406
+ this.store.emitter.emit('add', list);
1407
+ if (history) {
1408
+ this.pushHistory({ type: EditType.Add, pens: deepClone(list, true) });
1409
+ }
1410
+ return list;
1411
+ }
1378
1412
  ontouchstart = (e) => {
1413
+ this.viewAnimation = undefined;
1379
1414
  this.lastTouchY = e.touches[0].clientY;
1380
1415
  if (this.store.data.locked === LockState.Disable) {
1381
1416
  return;
@@ -1637,6 +1672,7 @@ export class Canvas {
1637
1672
  };
1638
1673
  }
1639
1674
  onMouseDown = (e) => {
1675
+ this.viewAnimation = undefined;
1640
1676
  if (e.buttons === 2 && !this.drawingLine) {
1641
1677
  this.mouseRight = MouseRight.Down;
1642
1678
  }
@@ -4366,6 +4402,10 @@ export class Canvas {
4366
4402
  now = performance.now();
4367
4403
  }
4368
4404
  if (!this.patchFlags) {
4405
+ if (this.store.options.gridAlwaysRender && (this.store.options.grid || this.store.data.grid)) {
4406
+ this.canvasTemplate.bgPatchFlags = true;
4407
+ this.canvasTemplate.render();
4408
+ }
4369
4409
  return;
4370
4410
  }
4371
4411
  if (patchFlags != null) {
@@ -4695,7 +4735,9 @@ export class Canvas {
4695
4735
  ctx.translate(0.5, 0.5);
4696
4736
  ctx.strokeStyle = pen.anchorColor || this.store.styles.anchorColor;
4697
4737
  ctx.fillStyle = pen.anchorBackground || this.store.options.anchorBackground;
4698
- pen.calculative.worldAnchors.forEach((anchor) => {
4738
+ const { fontStyle, fontWeight, fontSize, fontFamily, lineHeight } = pen.calculative;
4739
+ const scale = this.store.data.scale;
4740
+ pen.calculative.worldAnchors.forEach((anchor, index) => {
4699
4741
  if (anchor.hidden || anchor.locked > LockState.DisableEdit) {
4700
4742
  return;
4701
4743
  }
@@ -4760,6 +4802,71 @@ export class Canvas {
4760
4802
  else if (anchor.color || anchor.background) {
4761
4803
  ctx.restore();
4762
4804
  }
4805
+ if (anchor.label) {
4806
+ ctx.save();
4807
+ ctx.font = getFont({
4808
+ fontStyle: anchor.labelStyle?.fontStyle || fontStyle,
4809
+ fontWeight: anchor.labelStyle?.fontWeight || fontWeight,
4810
+ fontFamily: anchor.labelStyle?.fontFamily || fontFamily,
4811
+ lineHeight: anchor.labelStyle?.lineHeight || lineHeight,
4812
+ fontSize: anchor.labelStyle?.fontSize * scale || fontSize,
4813
+ });
4814
+ const rX = pen.anchors[index].x;
4815
+ const rY = pen.anchors[index].y;
4816
+ let xGap = 0;
4817
+ let yGap = 0;
4818
+ if (anchor.labelDirection !== undefined) {
4819
+ if (anchor.labelDirection === Direction.Left) {
4820
+ ctx.textAlign = 'right';
4821
+ ctx.textBaseline = 'middle';
4822
+ xGap = -(anchor.labelGap || 10) * scale;
4823
+ }
4824
+ else if (anchor.labelDirection === Direction.Right) {
4825
+ ctx.textAlign = 'left';
4826
+ ctx.textBaseline = 'middle';
4827
+ xGap = (anchor.labelGap || 10) * scale;
4828
+ }
4829
+ else if (anchor.labelDirection === Direction.Up) {
4830
+ ctx.textAlign = 'center';
4831
+ ctx.textBaseline = 'bottom';
4832
+ yGap = -(anchor.labelGap || 5) * scale;
4833
+ }
4834
+ else if (anchor.labelDirection === Direction.Bottom) {
4835
+ ctx.textAlign = 'center';
4836
+ ctx.textBaseline = 'top';
4837
+ yGap = (anchor.labelGap || 5) * scale;
4838
+ }
4839
+ }
4840
+ else {
4841
+ if (rX < 0.1) {
4842
+ ctx.textAlign = 'left';
4843
+ ctx.textBaseline = 'middle';
4844
+ xGap = (anchor.labelGap || 10) * scale;
4845
+ }
4846
+ else if (rX > 0.9) {
4847
+ ctx.textAlign = 'right';
4848
+ ctx.textBaseline = 'middle';
4849
+ xGap = -(anchor.labelGap || 10) * scale;
4850
+ }
4851
+ else {
4852
+ ctx.textAlign = 'center';
4853
+ if (rY < 0.1) {
4854
+ ctx.textBaseline = 'top';
4855
+ yGap = (anchor.labelGap || 5) * scale;
4856
+ }
4857
+ else if (rY > 0.9) {
4858
+ ctx.textBaseline = 'bottom';
4859
+ yGap = -(anchor.labelGap || 5) * scale;
4860
+ }
4861
+ else {
4862
+ ctx.textBaseline = 'middle';
4863
+ }
4864
+ }
4865
+ }
4866
+ ctx.fillStyle = anchor.labelStyle?.textColor || getTextColor(pen, this.store);
4867
+ ctx.fillText(anchor.label, anchor.x + xGap, anchor.y + yGap);
4868
+ ctx.restore();
4869
+ }
4763
4870
  //根父节点
4764
4871
  if (!pen.parentId && pen.children && pen.children.length > 0) {
4765
4872
  if (anchor === this.store.hoverAnchor) {
@@ -4927,6 +5034,184 @@ export class Canvas {
4927
5034
  this.store.emitter.emit('scale', this.store.data.scale);
4928
5035
  // });
4929
5036
  }
5037
+ animateView(options) {
5038
+ if (this.viewAnimationTimer) {
5039
+ cancelAnimationFrame(this.viewAnimationTimer);
5040
+ this.viewAnimationTimer = undefined;
5041
+ }
5042
+ this.viewAnimation = undefined;
5043
+ const duration = options.duration ?? 300;
5044
+ const easingName = options.easing ?? 'easeOutCubic';
5045
+ const center = options.center
5046
+ ? { ...options.center }
5047
+ : {
5048
+ x: this.width / 2,
5049
+ y: this.height / 2,
5050
+ };
5051
+ let toX = options.x !== undefined ? options.x : this.store.data.x;
5052
+ let toY = options.y !== undefined ? options.y : this.store.data.y;
5053
+ let toScale = options.scale !== undefined ? options.scale : this.store.data.scale;
5054
+ const minScale = this.store.data.minScale || this.store.options.minScale;
5055
+ const maxScale = this.store.data.maxScale || this.store.options.maxScale;
5056
+ if (toScale < minScale)
5057
+ toScale = minScale;
5058
+ if (toScale > maxScale)
5059
+ toScale = maxScale;
5060
+ if (options.pen) {
5061
+ const viewCenter = {
5062
+ x: this.width / 2,
5063
+ y: this.height / 2,
5064
+ };
5065
+ toX =
5066
+ viewCenter.x -
5067
+ options.pen.calculative.worldRect.x -
5068
+ options.pen.calculative.worldRect.width / 2;
5069
+ toY =
5070
+ viewCenter.y -
5071
+ options.pen.calculative.worldRect.y -
5072
+ options.pen.calculative.worldRect.height / 2;
5073
+ }
5074
+ if (!options.pen &&
5075
+ Math.abs(toX - this.store.data.x) < 0.5 &&
5076
+ Math.abs(toY - this.store.data.y) < 0.5 &&
5077
+ Math.abs(toScale - this.store.data.scale) < 0.001) {
5078
+ return;
5079
+ }
5080
+ this.calibrateMouse(center);
5081
+ this.viewAnimation = {
5082
+ startTime: performance.now(),
5083
+ duration,
5084
+ fromX: this.store.data.x,
5085
+ fromY: this.store.data.y,
5086
+ fromScale: this.store.data.scale,
5087
+ toX,
5088
+ toY,
5089
+ toScale,
5090
+ easing: getEasingFunction(easingName),
5091
+ center,
5092
+ pen: options.pen,
5093
+ };
5094
+ this.animateViewFrame();
5095
+ }
5096
+ animateViewFrame = () => {
5097
+ if (!this.viewAnimation) {
5098
+ return;
5099
+ }
5100
+ const now = performance.now();
5101
+ const { startTime, duration, fromX, fromY, fromScale, toX, toY, toScale, easing, center, pen, } = this.viewAnimation;
5102
+ let progress = Math.min(1, (now - startTime) / duration);
5103
+ progress = easing(progress);
5104
+ const prevScale = this.store.data.scale;
5105
+ const currentScale = fromScale + (toScale - fromScale) * progress;
5106
+ const s = currentScale / prevScale;
5107
+ if (s !== 1) {
5108
+ this.store.data.scale = currentScale;
5109
+ this.store.data.center = center;
5110
+ scalePoint(this.store.data.origin, s, center);
5111
+ this.store.data.pens.forEach((p) => {
5112
+ p.onScale && p.onScale(p);
5113
+ if (p.parentId) {
5114
+ return;
5115
+ }
5116
+ scalePen(p, s, center);
5117
+ if (p.isRuleLine) {
5118
+ const lineScale = 1 / s;
5119
+ const lineCenter = p.calculative.worldRect.center;
5120
+ if (!p.width) {
5121
+ scalePen(p, lineScale, lineCenter);
5122
+ }
5123
+ else if (!p.height) {
5124
+ scalePen(p, lineScale, lineCenter);
5125
+ }
5126
+ }
5127
+ this.updatePenRect(p, { worldRectIsReady: true });
5128
+ this.execPenResize(p);
5129
+ });
5130
+ this.calcActiveRect();
5131
+ }
5132
+ // Calculate current x, y
5133
+ let currentX;
5134
+ let currentY;
5135
+ if (pen) {
5136
+ // 参考 gotoView 的计算方式,基于当前 worldRect 实时计算
5137
+ const viewCenter = {
5138
+ x: this.width / 2,
5139
+ y: this.height / 2,
5140
+ };
5141
+ const targetX = viewCenter.x -
5142
+ pen.calculative.worldRect.x -
5143
+ pen.calculative.worldRect.width / 2;
5144
+ const targetY = viewCenter.y -
5145
+ pen.calculative.worldRect.y -
5146
+ pen.calculative.worldRect.height / 2;
5147
+ currentX = fromX + (targetX - fromX) * progress;
5148
+ currentY = fromY + (targetY - fromY) * progress;
5149
+ }
5150
+ else {
5151
+ currentX = fromX + (toX - fromX) * progress;
5152
+ currentY = fromY + (toY - fromY) * progress;
5153
+ }
5154
+ const prevX = this.store.data.x;
5155
+ const prevY = this.store.data.y;
5156
+ this.store.data.x = currentX;
5157
+ this.store.data.y = currentY;
5158
+ if (this.scroll && this.scroll.isShow) {
5159
+ this.scroll.translate(currentX - prevX, currentY - prevY);
5160
+ }
5161
+ this.onMovePens();
5162
+ this.canvasTemplate.init();
5163
+ this.canvasImage.init();
5164
+ this.canvasImageBottom.init();
5165
+ this.render();
5166
+ if (progress < 1) {
5167
+ this.viewAnimationTimer = requestAnimationFrame(this.animateViewFrame);
5168
+ }
5169
+ else {
5170
+ // Ensure final values are exact
5171
+ if (!pen) {
5172
+ this.store.data.x = toX;
5173
+ this.store.data.y = toY;
5174
+ }
5175
+ if (Math.abs(this.store.data.scale - toScale) > 0.001) {
5176
+ const finalS = toScale / this.store.data.scale;
5177
+ this.store.data.scale = toScale;
5178
+ this.store.data.center = center;
5179
+ scalePoint(this.store.data.origin, finalS, center);
5180
+ this.store.data.pens.forEach((p) => {
5181
+ p.onScale && p.onScale(p);
5182
+ if (p.parentId) {
5183
+ return;
5184
+ }
5185
+ scalePen(p, finalS, center);
5186
+ if (p.isRuleLine) {
5187
+ const lineScale = 1 / finalS;
5188
+ const lineCenter = p.calculative.worldRect.center;
5189
+ if (!p.width) {
5190
+ scalePen(p, lineScale, lineCenter);
5191
+ }
5192
+ else if (!p.height) {
5193
+ scalePen(p, lineScale, lineCenter);
5194
+ }
5195
+ }
5196
+ this.updatePenRect(p, { worldRectIsReady: true });
5197
+ this.execPenResize(p);
5198
+ });
5199
+ this.calcActiveRect();
5200
+ this.onMovePens();
5201
+ this.canvasTemplate.init();
5202
+ this.canvasImage.init();
5203
+ this.canvasImageBottom.init();
5204
+ this.render();
5205
+ }
5206
+ this.viewAnimation = undefined;
5207
+ this.viewAnimationTimer = undefined;
5208
+ this.store.emitter.emit('scale', this.store.data.scale);
5209
+ this.store.emitter.emit('translate', {
5210
+ x: this.store.data.x,
5211
+ y: this.store.data.y,
5212
+ });
5213
+ }
5214
+ };
4930
5215
  templateScale(scale, center = { x: 0, y: 0 }) {
4931
5216
  const { minScale, maxScale } = this.store.options;
4932
5217
  if (!(scale >= minScale && scale <= maxScale)) {
@@ -6831,11 +7116,10 @@ export class Canvas {
6831
7116
  if (pen.fontWeight) {
6832
7117
  style += `font-weight: ${pen.fontWeight};`;
6833
7118
  }
7119
+ let ml = 0;
6834
7120
  if (pen.textLeft) {
6835
- style += `margin-left:${scale > 1
6836
- ? pen.textLeft * scale
6837
- : (pen.textLeft * scale) // scale
6838
- }px;`;
7121
+ ml = scale > 1 ? pen.textLeft * scale : (pen.textLeft * scale);
7122
+ style += `margin-left:${ml}px;`;
6839
7123
  }
6840
7124
  if (pen.textTop) {
6841
7125
  style += `margin-top:${scale > 1
@@ -6892,7 +7176,7 @@ export class Canvas {
6892
7176
  if (tem < 0) {
6893
7177
  tem = 0;
6894
7178
  }
6895
- style += `width:${pen.fontSize * scale < 12 ? tem * scale : tem * scale}px;`;
7179
+ style += `width:${pen.fontSize * scale < 12 ? tem * scale - ml : tem * scale - ml}px;`;
6896
7180
  }
6897
7181
  // if (pen.whiteSpace === 'pre-line') {
6898
7182
  // //回车换行
@@ -6919,9 +7203,9 @@ export class Canvas {
6919
7203
  Math.floor(pen.calculative.worldRect.height /
6920
7204
  scale /
6921
7205
  (pen.lineHeight * pen.fontSize));
6922
- if (textWidth > contentWidth) {
6923
- style += 'justify-content: start;';
6924
- }
7206
+ // if (textWidth > contentWidth) {
7207
+ // style += 'justify-content: start;';
7208
+ // }
6925
7209
  }
6926
7210
  sheet.deleteRule(0);
6927
7211
  sheet.deleteRule(0);
@@ -7019,7 +7303,9 @@ export class Canvas {
7019
7303
  sheet.insertRule('.meta2d-input ul{position:absolute;top:100%;margin-top:4px; width:calc(100% + 10px);min-height:30px;border-radius: 2px;box-shadow: 0 2px 8px #00000026;list-style-type: none;background-color: #fff;padding: 4px 0;max-height: 105px;overflow-y: auto;}');
7020
7304
  sheet.insertRule('.meta2d-input ul li{padding: 5px 12px;line-height: 22px;white-space: nowrap;cursor: pointer;}');
7021
7305
  sheet.insertRule('.meta2d-input ul li:hover{background: #eeeeee;}');
7022
- sheet.insertRule(`.input-div::-webkit-scrollbar {display:none}`);
7306
+ if (CSS.supports?.('selector(.input-div::-webkit-scrollbar)')) {
7307
+ sheet.insertRule(`.input-div::-webkit-scrollbar {display:none}`);
7308
+ }
7023
7309
  sheet.insertRule(`.input-div{scrollbar-width: none;}`);
7024
7310
  sheet.insertRule('.meta2d-input .input-div{resize:none;border:none;outline:none;background:transparent;flex-grow:1;height:100%;width: 100%;left:0;top:0;display:flex;text-align: center;justify-content: center;flex-direction: column;}');
7025
7311
  sheet.insertRule(`.input-div div{}`);