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