embroidery-qc-image 1.0.26 → 1.0.27
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/dist/components/EmbroideryQCImage.d.ts.map +1 -1
- package/dist/index.esm.js +98 -19
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +98 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1071,16 +1071,22 @@ displayIndex, showLabels, scaleFactor, imageRefs) => {
|
|
|
1071
1071
|
effectiveTextFontSize = textFontSize * shrinkRatio;
|
|
1072
1072
|
}
|
|
1073
1073
|
}
|
|
1074
|
-
//
|
|
1074
|
+
// Line height luôn theo Text label (textFontSize), không theo effectiveTextFontSize
|
|
1075
|
+
const valueLineHeight = textFontSize;
|
|
1076
|
+
const textBlockHeight = lines.length * valueLineHeight;
|
|
1077
|
+
// Text align center: căn giữa theo chiều dọc trong block
|
|
1078
|
+
const textCenterY = currentY + textBlockHeight / 2;
|
|
1079
|
+
// Vẽ phần value với font hiệu dụng, màu đỏ, align center
|
|
1080
|
+
ctx.textBaseline = "middle";
|
|
1075
1081
|
ctx.font = `${effectiveTextFontSize}px ${LAYOUT.FONT_FAMILY}`;
|
|
1076
1082
|
ctx.fillStyle = DEFAULT_ERROR_COLOR;
|
|
1077
|
-
|
|
1078
|
-
let localY = currentY;
|
|
1083
|
+
// Vẽ từ trên xuống: căn giữa mỗi dòng
|
|
1079
1084
|
lines.forEach((line, idx) => {
|
|
1080
|
-
|
|
1081
|
-
|
|
1085
|
+
const lineY = textCenterY - (lines.length - 1) / 2 * valueLineHeight + idx * valueLineHeight;
|
|
1086
|
+
ctx.fillText(line, valueStartX, lineY);
|
|
1082
1087
|
});
|
|
1083
|
-
|
|
1088
|
+
// Reset textBaseline về top cho các phần tiếp theo
|
|
1089
|
+
ctx.textBaseline = LAYOUT.TEXT_BASELINE;
|
|
1084
1090
|
currentY += textBlockHeight;
|
|
1085
1091
|
drawnHeight += textBlockHeight;
|
|
1086
1092
|
// Draw additional labels (skip when text is empty)
|
|
@@ -1241,29 +1247,102 @@ const renderIconPosition = (ctx, position, x, y, maxWidth, scaleFactor, imageRef
|
|
|
1241
1247
|
// Kiểm tra xem có icon_image không để tính height phù hợp
|
|
1242
1248
|
const hasIconImage = position.icon_image && position.icon_image.trim().length > 0;
|
|
1243
1249
|
const iconImageHeight = hasIconImage ? iconFontSize * 2 : iconFontSize;
|
|
1244
|
-
//
|
|
1245
|
-
const textBottomY = cursorY + iconImageHeight;
|
|
1246
|
-
// Đo width trước khi vẽ
|
|
1250
|
+
// Đo width của label
|
|
1247
1251
|
ctx.font = `bold ${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;
|
|
1248
1252
|
const labelWidth = ctx.measureText(iconLabel).width;
|
|
1249
|
-
|
|
1250
|
-
const
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1253
|
+
// Chuẩn hóa xuống dòng cho icon_value (giống text value)
|
|
1254
|
+
const normalizeNewlines = (text) => text
|
|
1255
|
+
.replace(/\r\n/g, "\n")
|
|
1256
|
+
.replace(/\r/g, "\n")
|
|
1257
|
+
.replace(/\\n/g, "\n");
|
|
1258
|
+
const normalizedIconValue = normalizeNewlines(iconValue);
|
|
1259
|
+
const iconValueLines = normalizedIconValue.split("\n");
|
|
1260
|
+
// Tính kích thước icon_image nếu có để chừa khoảng trống
|
|
1261
|
+
let iconImageReservedWidth = 0;
|
|
1262
|
+
if (hasIconImage) {
|
|
1263
|
+
const iconUrl = getIconImageUrl(position);
|
|
1264
|
+
if (iconUrl) {
|
|
1265
|
+
const img = imageRefs.current.get(iconUrl);
|
|
1266
|
+
if (img?.complete && img.naturalHeight > 0) {
|
|
1267
|
+
const ratio = img.naturalWidth / img.naturalHeight;
|
|
1268
|
+
const iconHeight = iconFontSize * 2;
|
|
1269
|
+
const iconWidth = Math.max(1, Math.floor(iconHeight * ratio));
|
|
1270
|
+
iconImageReservedWidth = iconWidth + LAYOUT.ELEMENT_SPACING * scaleFactor;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
// Tính available width cho icon value (trừ đi khoảng trống cho icon_image)
|
|
1275
|
+
const availableWidth = Math.max(1, maxWidth - labelWidth - iconImageReservedWidth);
|
|
1276
|
+
// Tính font-size hiệu dụng cho icon value
|
|
1277
|
+
// Giới hạn thu nhỏ tối đa 50% (tối thiểu = iconFontSize * 0.5)
|
|
1278
|
+
const MIN_ICON_VALUE_FONT_SIZE = iconFontSize * 0.5;
|
|
1279
|
+
const measureMaxLineWidth = (fontSize) => {
|
|
1280
|
+
ctx.font = `${fontSize}px ${LAYOUT.FONT_FAMILY}`;
|
|
1281
|
+
let maxLineWidth = 0;
|
|
1282
|
+
iconValueLines.forEach((line) => {
|
|
1283
|
+
const w = ctx.measureText(` ${line}`).width;
|
|
1284
|
+
if (w > maxLineWidth)
|
|
1285
|
+
maxLineWidth = w;
|
|
1286
|
+
});
|
|
1287
|
+
return maxLineWidth;
|
|
1288
|
+
};
|
|
1289
|
+
let effectiveIconValueFontSize = iconFontSize;
|
|
1290
|
+
const baseMaxWidth = measureMaxLineWidth(iconFontSize);
|
|
1291
|
+
let needsWrap = false;
|
|
1292
|
+
if (baseMaxWidth > availableWidth) {
|
|
1293
|
+
const shrinkRatio = availableWidth / baseMaxWidth;
|
|
1294
|
+
effectiveIconValueFontSize = Math.max(MIN_ICON_VALUE_FONT_SIZE, iconFontSize * shrinkRatio);
|
|
1295
|
+
// Kiểm tra xem sau khi thu nhỏ đến 50% có vẫn overflow không
|
|
1296
|
+
const minMaxWidth = measureMaxLineWidth(MIN_ICON_VALUE_FONT_SIZE);
|
|
1297
|
+
if (minMaxWidth > availableWidth) {
|
|
1298
|
+
// Vẫn overflow, cần dùng wrap text
|
|
1299
|
+
needsWrap = true;
|
|
1300
|
+
effectiveIconValueFontSize = MIN_ICON_VALUE_FONT_SIZE;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
// Tính line height và block height cho icon value
|
|
1304
|
+
const valueLineHeight = effectiveIconValueFontSize;
|
|
1305
|
+
let allWrappedLines = [];
|
|
1306
|
+
if (needsWrap) {
|
|
1307
|
+
// Dùng wrap text logic: wrap tất cả các dòng trước
|
|
1308
|
+
iconValueLines.forEach((line) => {
|
|
1309
|
+
const wrappedLines = buildWrappedLines(ctx, line, availableWidth);
|
|
1310
|
+
allWrappedLines.push(...wrappedLines);
|
|
1311
|
+
});
|
|
1312
|
+
allWrappedLines.length * valueLineHeight;
|
|
1313
|
+
}
|
|
1314
|
+
else {
|
|
1315
|
+
allWrappedLines = iconValueLines;
|
|
1316
|
+
iconValueLines.length * valueLineHeight;
|
|
1317
|
+
}
|
|
1318
|
+
// Text align center: căn giữa theo chiều dọc trong block
|
|
1319
|
+
const textCenterY = cursorY + iconImageHeight / 2;
|
|
1320
|
+
// Vẽ label với textBaseline = middle để align center với value
|
|
1321
|
+
ctx.textBaseline = "middle";
|
|
1254
1322
|
ctx.font = `bold ${iconFontSize}px ${LAYOUT.FONT_FAMILY}`;
|
|
1255
1323
|
ctx.fillStyle = LAYOUT.LABEL_COLOR;
|
|
1256
|
-
ctx.fillText(iconLabel, x,
|
|
1257
|
-
|
|
1324
|
+
ctx.fillText(iconLabel, x, textCenterY);
|
|
1325
|
+
const valueStartX = x + labelWidth;
|
|
1326
|
+
// Vẽ icon value với align center
|
|
1327
|
+
ctx.font = `${effectiveIconValueFontSize}px ${LAYOUT.FONT_FAMILY}`;
|
|
1258
1328
|
ctx.fillStyle = DEFAULT_ERROR_COLOR;
|
|
1259
|
-
|
|
1329
|
+
let maxValueLineWidth = 0;
|
|
1330
|
+
// Vẽ từng dòng, căn giữa theo chiều dọc
|
|
1331
|
+
allWrappedLines.forEach((line, index) => {
|
|
1332
|
+
const lineY = textCenterY - (allWrappedLines.length - 1) / 2 * valueLineHeight + index * valueLineHeight;
|
|
1333
|
+
const lineText = needsWrap ? line : ` ${line}`;
|
|
1334
|
+
ctx.fillText(lineText, valueStartX, lineY);
|
|
1335
|
+
const w = ctx.measureText(lineText).width;
|
|
1336
|
+
if (w > maxValueLineWidth)
|
|
1337
|
+
maxValueLineWidth = w;
|
|
1338
|
+
});
|
|
1260
1339
|
ctx.fillStyle = LAYOUT.LABEL_COLOR;
|
|
1261
1340
|
// Reset textBaseline về top cho các phần tiếp theo
|
|
1262
1341
|
ctx.textBaseline = LAYOUT.TEXT_BASELINE;
|
|
1263
1342
|
const iconResult = {
|
|
1264
1343
|
height: iconImageHeight + lineGap,
|
|
1265
1344
|
// tổng width của cả label + value, dùng để canh icon image lệch sang phải
|
|
1266
|
-
lastLineWidth: labelWidth +
|
|
1345
|
+
lastLineWidth: labelWidth + maxValueLineWidth};
|
|
1267
1346
|
// Draw icon image
|
|
1268
1347
|
const iconUrl = getIconImageUrl(position);
|
|
1269
1348
|
if (iconUrl) {
|
|
@@ -1276,7 +1355,7 @@ const renderIconPosition = (ctx, position, x, y, maxWidth, scaleFactor, imageRef
|
|
|
1276
1355
|
const iconX = x +
|
|
1277
1356
|
Math.ceil(iconResult.lastLineWidth) +
|
|
1278
1357
|
LAYOUT.ELEMENT_SPACING * scaleFactor;
|
|
1279
|
-
const iconY =
|
|
1358
|
+
const iconY = textCenterY - iconHeight / 2; // Align center với text
|
|
1280
1359
|
ctx.drawImage(img, iconX, iconY, swatchW, iconHeight);
|
|
1281
1360
|
}
|
|
1282
1361
|
}
|