@libs-ui/components-draw-line 0.2.356-4 → 0.2.356-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.
- package/draw-line.directive.d.ts +3 -2
- package/draw-line.interface.d.ts +1 -1
- package/esm2022/draw-line.directive.mjs +41 -6
- package/esm2022/draw-line.interface.mjs +1 -1
- package/esm2022/util/calculator-diretion-element.until.mjs +10 -12
- package/esm2022/util/connect-navigation-new-element.util.mjs +2 -3
- package/esm2022/util/line-connect-bottom-left.until.mjs +1 -2
- package/fesm2022/libs-ui-components-draw-line.mjs +50 -19
- package/fesm2022/libs-ui-components-draw-line.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -178,32 +178,32 @@ class MoCanvasCalculatorDirectionElementUtil {
|
|
|
178
178
|
}
|
|
179
179
|
return false;
|
|
180
180
|
});
|
|
181
|
-
if (!elementBlockRoad
|
|
181
|
+
if (!elementBlockRoad?.length) {
|
|
182
182
|
return undefined;
|
|
183
183
|
}
|
|
184
184
|
if (returnAllElementBlockRoad) {
|
|
185
185
|
return elementBlockRoad;
|
|
186
186
|
}
|
|
187
187
|
if (direction === 'y') {
|
|
188
|
-
return elementBlockRoad.reduce((a, b) => (Math.abs((a.y ?? 0) - start) < Math.abs((b.y ?? 0) - start) ? a : b));
|
|
188
|
+
return elementBlockRoad.reduce((a, b) => (Math.abs((a.y ?? 0) - start) < Math.abs((b.y ?? 0) - start) ? a : b), elementBlockRoad[0]);
|
|
189
189
|
}
|
|
190
|
-
return elementBlockRoad.reduce((a, b) => (Math.abs((a.x ?? 0) - start) < Math.abs((b.x ?? 0) - start) ? a : b));
|
|
190
|
+
return elementBlockRoad.reduce((a, b) => (Math.abs((a.x ?? 0) - start) < Math.abs((b.x ?? 0) - start) ? a : b), elementBlockRoad[0]);
|
|
191
191
|
}
|
|
192
192
|
// kiểm tra hướng thẳng vẽ về điểm end xem có bị chắn bởi khối nào không, nếu có thì phải lùi lại điểm end nhé.
|
|
193
193
|
static checkBlocksElementStraightY(startX, startY, endPosition, obstacleRect) {
|
|
194
194
|
const elementBlockRoad = this.checkLinePassBlockHorizontal(startY, endPosition.y, startX, 'y', obstacleRect, true);
|
|
195
|
-
if (!elementBlockRoad
|
|
195
|
+
if (!elementBlockRoad?.length) {
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
198
|
-
return elementBlockRoad.reduce((a, b) => (Math.abs(a.x ?? 0 - startX) < Math.abs(b.x ?? 0 - startX) ? a : b));
|
|
198
|
+
return elementBlockRoad.reduce((a, b) => (Math.abs(a.x ?? 0 - startX) < Math.abs(b.x ?? 0 - startX) ? a : b), elementBlockRoad[0]);
|
|
199
199
|
}
|
|
200
200
|
// kiểm tra hướng ngang vẽ về điểm end xem có bị chắn bởi khối nào không, nếu có thì phải lùi lại điểm end nhé.
|
|
201
201
|
static checkBlocksElementX(startX, startY, endPosition, obstacleRect) {
|
|
202
202
|
const elementBlockRoad = this.checkLinePassBlockHorizontal(startX, endPosition.x, startY, 'x', obstacleRect, true);
|
|
203
|
-
if (!elementBlockRoad
|
|
203
|
+
if (!elementBlockRoad?.length) {
|
|
204
204
|
return;
|
|
205
205
|
}
|
|
206
|
-
return elementBlockRoad.reduce((a, b) => (Math.abs((a.y ?? 0) - startY) < Math.abs((b.y ?? 0) - startY) ? a : b));
|
|
206
|
+
return elementBlockRoad.reduce((a, b) => (Math.abs((a.y ?? 0) - startY) < Math.abs((b.y ?? 0) - startY) ? a : b), elementBlockRoad[0]);
|
|
207
207
|
}
|
|
208
208
|
// kiểm tra hướng sang phải là tránh khối
|
|
209
209
|
static checkAndAvoidBlocksLeft(startX, startY, lineCurve, endPosition, obstacleRect, separatedPoints) {
|
|
@@ -258,7 +258,7 @@ class MoCanvasCalculatorDirectionElementUtil {
|
|
|
258
258
|
}
|
|
259
259
|
const directionX = MoCanvasCalculatorDirectionElementUtil.checkUpDownLeftRight(startX, endPosition.x, 'x');
|
|
260
260
|
coordLX.x = (elementBlockRoad.x ?? 0) - MoCanvasConnectNavigationNewElementUtil.ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT / 2 - lineCurve / 2;
|
|
261
|
-
|
|
261
|
+
const separatedPointsByPassElementOnRightSide = [];
|
|
262
262
|
const { pathByPassQ, endPath } = MoCanvasCalculatorDirectionElementUtil.byPassElementOnRightSide(coordLX.x, coordLX.y ?? 0, endPosition.y, lineCurve, elementBlockRoad, directionX, separatedPointsByPassElementOnRightSide, 'checkAndAvoidBlocks', coordLX.x);
|
|
263
263
|
let line = pathPre ? `${pathPre} L ${coordLX.x} ${coordLX.y} ${pathByPassQ}` : `L ${coordLX.x} ${coordLX.y} ${pathByPassQ}`;
|
|
264
264
|
// tính trước trường hợp sau để lùi line
|
|
@@ -268,7 +268,6 @@ class MoCanvasCalculatorDirectionElementUtil {
|
|
|
268
268
|
if (elementBlockRoadStraightLineY) {
|
|
269
269
|
const XNew = (elementBlockRoadStraightLineY.x ?? 0) - MoCanvasConnectNavigationNewElementUtil.ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT / 2 - lineCurve / 2;
|
|
270
270
|
if (XNew < (endPath.x ?? 0)) {
|
|
271
|
-
separatedPointsByPassElementOnRightSide = [];
|
|
272
271
|
separatedPoints.push({ start: { x: startX, y: startY }, end: coordLX, mode: 'horizontal', id: 'checkAndAvoidBlocks', name: 'u' });
|
|
273
272
|
line = pathPre ? `${pathPre} L ${coordLX.x} ${coordLX.y}` : `L ${coordLX.x} ${coordLX.y}`;
|
|
274
273
|
return {
|
|
@@ -345,13 +344,12 @@ class MoCanvasCalculatorDirectionElementUtil {
|
|
|
345
344
|
ignoreBypassElement = true;
|
|
346
345
|
}
|
|
347
346
|
coordLX.y = MoCanvasCalculatorBranchUtil.mathOperatorsCalculation(directionY, y, lineCurve * 2);
|
|
348
|
-
|
|
347
|
+
const separatedPointsByPassElementOnRightSide = [];
|
|
349
348
|
const { pathByPassQ, endPath } = MoCanvasCalculatorDirectionElementUtil.byPassElementOnTopBottomSide(coordLX.x ?? 0, coordLX.y ?? 0, endPosition.x, lineCurve, elementBlockRoad, directionY, separatedPointsByPassElementOnRightSide, key);
|
|
350
349
|
let end = coordLX;
|
|
351
350
|
let line = pathPre ? `${pathPre} L ${coordLX.x} ${coordLX.y}` : `L ${coordLX.x} ${coordLX.y}`;
|
|
352
351
|
separatedPoints.push({ start: { x: startX, y: startY }, end: coordLX, mode: 'horizontal', id: key, name: 'b' });
|
|
353
352
|
if (ignoreBypassElement) {
|
|
354
|
-
separatedPointsByPassElementOnRightSide = [];
|
|
355
353
|
separatedPoints.push({ start: coordLX, end, mode: 'horizontal', id: key, name: 'c' });
|
|
356
354
|
return {
|
|
357
355
|
path: line,
|
|
@@ -518,7 +516,6 @@ class MoCanvasConnectNavigationBottomLeftElementUtil {
|
|
|
518
516
|
}
|
|
519
517
|
separatedPoints.push(...avoidBlocksYLine);
|
|
520
518
|
separatedPoints.push({ start: { x: straightLine.endPath.x ?? 0, y: straightLine.endPath.y ?? 0 }, end: endPosition, mode: 'vertical-single-curve', id: '4' });
|
|
521
|
-
return;
|
|
522
519
|
}
|
|
523
520
|
}
|
|
524
521
|
|
|
@@ -594,9 +591,8 @@ class MoCanvasConnectNavigationNewElementUtil {
|
|
|
594
591
|
endPath: LEnd,
|
|
595
592
|
};
|
|
596
593
|
}
|
|
597
|
-
let lineCurveSubY = lineCurve;
|
|
598
594
|
if (Math.abs((endPath.y ?? 0) - endPosition.y) < lineCurve * 2) {
|
|
599
|
-
lineCurveSubY = Math.abs((endPath.y ?? 0) - endPosition.y) / 2;
|
|
595
|
+
const lineCurveSubY = Math.abs((endPath.y ?? 0) - endPosition.y) / 2;
|
|
600
596
|
const coordQ1 = MoCanvasCalculatorDirectionElementUtil.drawLineQ({ x: endPath.x ?? 0, y: endPath.y ?? 0 }, `right-${directionY === 'above' ? 'above' : 'under'}`, lineCurveSubY * 2, lineCurveSubY); // tính đoạn cong từ đường ngang sang đường thẳng
|
|
601
597
|
const pathQ1 = `Q ${coordQ1.x1},${coordQ1.y1} ${coordQ1.x},${coordQ1.y}`; // từ ngang sang thẳng phải có đường cong
|
|
602
598
|
const coordQ2 = MoCanvasCalculatorDirectionElementUtil.drawLineQ({ x: coordQ1.x ?? 0, y: coordQ1.y ?? 0 }, `${directionY === 'above' ? 'above' : 'under'}-right`, lineCurveSubY * 2, lineCurveSubY); // tính đoạn cong từ đường thẳng sang ngang
|
|
@@ -1082,7 +1078,7 @@ class LibsUiComponentsDrawLineDirective {
|
|
|
1082
1078
|
points.separatedPoints.forEach((separatedPoints) => {
|
|
1083
1079
|
path += this.buildPathAndDrawSeparatedPoints(data, separatedPoints, separatedPoints.mode || mode);
|
|
1084
1080
|
});
|
|
1085
|
-
if (!points.pathElement
|
|
1081
|
+
if (!points.pathElement?.parentNode) {
|
|
1086
1082
|
const pathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
1087
1083
|
this.svgElement.append(pathElement);
|
|
1088
1084
|
points.pathElement = pathElement;
|
|
@@ -1120,6 +1116,12 @@ class LibsUiComponentsDrawLineDirective {
|
|
|
1120
1116
|
this.dataDraw?.forEach((item) => {
|
|
1121
1117
|
const points = item.points;
|
|
1122
1118
|
addPoints(points);
|
|
1119
|
+
// Nếu mode là s-line, thêm offset cho control points để viewBox đủ rộng cho curve vòng ra ngoài
|
|
1120
|
+
if (item.mode === 's-line') {
|
|
1121
|
+
const offsetDistance = 1000;
|
|
1122
|
+
xPoints.add(points.start.x + offsetDistance);
|
|
1123
|
+
xPoints.add(points.end.x - offsetDistance);
|
|
1124
|
+
}
|
|
1123
1125
|
points.separatedPoints?.forEach((separatedPoints) => addPoints(separatedPoints));
|
|
1124
1126
|
points.obstacleRect?.forEach((obstacleRect) => {
|
|
1125
1127
|
addPoints({
|
|
@@ -1128,8 +1130,8 @@ class LibsUiComponentsDrawLineDirective {
|
|
|
1128
1130
|
});
|
|
1129
1131
|
});
|
|
1130
1132
|
});
|
|
1131
|
-
const xMax = this.viewBoxConfig?.width ?? (
|
|
1132
|
-
const yMax = this.viewBoxConfig?.height ?? (
|
|
1133
|
+
const xMax = this.viewBoxConfig?.width ?? (xPoints.size ? Math.max(...xPoints) : 0) + 14;
|
|
1134
|
+
const yMax = this.viewBoxConfig?.height ?? (yPoints.size ? Math.max(...yPoints) : 0) + 14;
|
|
1133
1135
|
if (!this.viewBoxConfig?.ignoreViewBox) {
|
|
1134
1136
|
const rectSvgElement = this.svgElement.getBoundingClientRect();
|
|
1135
1137
|
this.svgElement?.setAttribute('viewBox', `${this.viewBoxConfig?.minX ?? rectSvgElement.x} ${this.viewBoxConfig?.minY ?? rectSvgElement.y} ${xMax} ${yMax}`);
|
|
@@ -1175,12 +1177,17 @@ class LibsUiComponentsDrawLineDirective {
|
|
|
1175
1177
|
curve = curve ?? 10;
|
|
1176
1178
|
distancePoint = distancePoint ?? 10;
|
|
1177
1179
|
}
|
|
1178
|
-
if (mode === 'quart-in' || points.start.x === points.end.x || points.start.y === points.end.y) {
|
|
1179
|
-
|
|
1180
|
+
if (mode === 'quart-in' || mode === 's-line' || points.start.x === points.end.x || points.start.y === points.end.y) {
|
|
1181
|
+
if (mode !== 's-line') {
|
|
1182
|
+
this.drawBalancedCurve(dPath, points);
|
|
1183
|
+
}
|
|
1180
1184
|
if (mode === 'quart-in') {
|
|
1181
1185
|
dPath = {};
|
|
1182
1186
|
this.drawBendBothEndsCurve(dPath, points);
|
|
1183
1187
|
}
|
|
1188
|
+
if (mode === 's-line') {
|
|
1189
|
+
this.drawBendBothEndsCurveSLine(dPath, points);
|
|
1190
|
+
}
|
|
1184
1191
|
points.pathElement?.setAttribute('d', this.builDAttributeToString(dPath));
|
|
1185
1192
|
this.drawRectAndInitEvent(data, mode);
|
|
1186
1193
|
return;
|
|
@@ -1252,6 +1259,22 @@ class LibsUiComponentsDrawLineDirective {
|
|
|
1252
1259
|
{ x: points.end.x, y: points.end.y },
|
|
1253
1260
|
];
|
|
1254
1261
|
}
|
|
1262
|
+
drawBendBothEndsCurveSLine(dPath, points) {
|
|
1263
|
+
// Khi X gần nhau → giảm offset để tránh cong quá; khi X xa nhau → offset lớn hơn để tạo S-curve rõ ràng
|
|
1264
|
+
const deltaX = points.end.x - points.start.x;
|
|
1265
|
+
const offsetDistance = Math.min(180, Math.max(80, Math.abs(deltaX)));
|
|
1266
|
+
const deltaY = points.end.y - points.start.y;
|
|
1267
|
+
// LUÔN ĐI RA PHẢI từ start, VÀO TỪ TRÁI của end (hoặc giữ tại end nếu start ở trên end)
|
|
1268
|
+
const rightX = points.start.x + offsetDistance;
|
|
1269
|
+
const leftX = deltaY > 0 ? points.end.x : points.end.x - offsetDistance;
|
|
1270
|
+
dPath.M = { x: points.start.x, y: points.start.y };
|
|
1271
|
+
// Cubic bezier curve duy nhất với control points tính toán để tạo S-curve mượt
|
|
1272
|
+
dPath.C = [
|
|
1273
|
+
{ x: rightX, y: points.start.y + deltaY * (deltaY < 0 || deltaX < 0 ? 0.5 : 0.1) },
|
|
1274
|
+
{ x: leftX, y: points.end.y - deltaY * 0.5 },
|
|
1275
|
+
{ x: points.end.x, y: points.end.y },
|
|
1276
|
+
];
|
|
1277
|
+
}
|
|
1255
1278
|
buildDAttributeByPointEndModeHorizontal(dPath, points, distancePoint, curve, mode) {
|
|
1256
1279
|
if (!mode.includes('horizontal')) {
|
|
1257
1280
|
return;
|
|
@@ -1388,6 +1411,14 @@ class LibsUiComponentsDrawLineDirective {
|
|
|
1388
1411
|
}
|
|
1389
1412
|
const modeHorizontal = pointStart.x < points.end.x ? 'right' : 'left';
|
|
1390
1413
|
const modeVertical = pointStart.y < points.end.y ? 'bottom' : 'top';
|
|
1414
|
+
// Mode s-line: nếu end ở dưới start → mũi tên chỉ xuống (bottom); ngược lại → mũi tên chỉ ngang (right)
|
|
1415
|
+
if (mode === 's-line') {
|
|
1416
|
+
const deltaY = points.end.y - points.start.y;
|
|
1417
|
+
if (deltaY > 0) {
|
|
1418
|
+
return 'bottom';
|
|
1419
|
+
}
|
|
1420
|
+
return 'right';
|
|
1421
|
+
}
|
|
1391
1422
|
if (mode?.includes('vertical') && !mode.includes('single-curve')) {
|
|
1392
1423
|
return modeVertical;
|
|
1393
1424
|
}
|