优化
This commit is contained in:
@@ -10,6 +10,8 @@ import {
|
||||
import {
|
||||
resolveCornerRadiiPx,
|
||||
resolveBorderSides,
|
||||
resolvePaddingMm,
|
||||
getPaddedRectPx,
|
||||
traceRoundedRect,
|
||||
drawElementFill,
|
||||
drawElementBorders,
|
||||
@@ -213,23 +215,6 @@ function layoutVerticalTextColumns(
|
||||
return columns;
|
||||
}
|
||||
|
||||
function getPaddedRect(
|
||||
x: number,
|
||||
y: number,
|
||||
w: number,
|
||||
h: number,
|
||||
paddingMm: number,
|
||||
scale: number
|
||||
) {
|
||||
const paddingPx = Math.round(paddingMm * scale);
|
||||
return {
|
||||
x: x + paddingPx,
|
||||
y: y + paddingPx,
|
||||
w: Math.max(1, w - 2 * paddingPx),
|
||||
h: Math.max(1, h - 2 * paddingPx),
|
||||
};
|
||||
}
|
||||
|
||||
function drawImagePlaceholder(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
x: number,
|
||||
@@ -343,10 +328,17 @@ export async function renderLabelToDataUrl(options: RenderLabelOptions): Promise
|
||||
|
||||
drawElementFill(ctx, ex, ey, ew, eh, elem, radii);
|
||||
|
||||
const paddingMm = elem.padding || 0;
|
||||
const paddingPx = Math.round(paddingMm * scale);
|
||||
const writableW = Math.max(1, ew - 2 * paddingPx);
|
||||
const writableH = Math.max(1, eh - 2 * paddingPx);
|
||||
const padPx = (() => {
|
||||
const pad = resolvePaddingMm(elem);
|
||||
return {
|
||||
top: Math.round(pad.top * scale),
|
||||
right: Math.round(pad.right * scale),
|
||||
bottom: Math.round(pad.bottom * scale),
|
||||
left: Math.round(pad.left * scale),
|
||||
};
|
||||
})();
|
||||
const writableW = Math.max(1, ew - padPx.left - padPx.right);
|
||||
const writableH = Math.max(1, eh - padPx.top - padPx.bottom);
|
||||
|
||||
const fontStyle = elem.fontStyle === 'italic' ? 'italic ' : '';
|
||||
const fontWeight = elem.fontWeight === 'bold' ? 'bold ' : '';
|
||||
@@ -375,8 +367,8 @@ export async function renderLabelToDataUrl(options: RenderLabelOptions): Promise
|
||||
|
||||
const textScaleX = Math.max(0.1, Math.min(5, elem.textScaleX ?? 1));
|
||||
const textScaleY = Math.max(0.1, Math.min(5, elem.textScaleY ?? 1));
|
||||
const transformOriginX = ex + paddingPx + writableW / 2;
|
||||
const transformOriginY = ey + paddingPx + writableH / 2;
|
||||
const transformOriginX = ex + padPx.left + writableW / 2;
|
||||
const transformOriginY = ey + padPx.top + writableH / 2;
|
||||
|
||||
ctx.save();
|
||||
if (textScaleX !== 1 || textScaleY !== 1) {
|
||||
@@ -393,11 +385,11 @@ export async function renderLabelToDataUrl(options: RenderLabelOptions): Promise
|
||||
|
||||
let startX: number;
|
||||
if (elem.textAlign === 'center') {
|
||||
startX = ex + paddingPx + Math.max(0, (writableW - totalColumnsWidth) / 2) + columnWidth / 2;
|
||||
startX = ex + padPx.left + Math.max(0, (writableW - totalColumnsWidth) / 2) + columnWidth / 2;
|
||||
} else if (elem.textAlign === 'right') {
|
||||
startX = ex + paddingPx + Math.max(0, writableW - totalColumnsWidth) + columnWidth / 2;
|
||||
startX = ex + padPx.left + Math.max(0, writableW - totalColumnsWidth) + columnWidth / 2;
|
||||
} else {
|
||||
startX = ex + paddingPx + columnWidth / 2;
|
||||
startX = ex + padPx.left + columnWidth / 2;
|
||||
}
|
||||
ctx.textAlign = 'center';
|
||||
|
||||
@@ -406,18 +398,18 @@ export async function renderLabelToDataUrl(options: RenderLabelOptions): Promise
|
||||
const colTextHeight = column.length * lineHeight;
|
||||
let colStartY: number;
|
||||
if (vAlign === 'top') {
|
||||
colStartY = ey + paddingPx + lineHeight / 2;
|
||||
colStartY = ey + padPx.top + lineHeight / 2;
|
||||
} else if (vAlign === 'bottom') {
|
||||
colStartY = ey + eh - paddingPx - colTextHeight + lineHeight / 2;
|
||||
colStartY = ey + eh - padPx.bottom - colTextHeight + lineHeight / 2;
|
||||
} else {
|
||||
colStartY =
|
||||
ey + paddingPx + Math.max(0, (writableH - colTextHeight) / 2) + lineHeight / 2;
|
||||
ey + padPx.top + Math.max(0, (writableH - colTextHeight) / 2) + lineHeight / 2;
|
||||
}
|
||||
|
||||
const colX = startX + col * columnWidth;
|
||||
for (let i = 0; i < column.length; i++) {
|
||||
const charY = colStartY + i * lineHeight;
|
||||
if (charY - lineHeight / 2 <= ey + eh - paddingPx) {
|
||||
if (charY - lineHeight / 2 <= ey + eh - padPx.bottom) {
|
||||
ctx.fillText(column[i], colX, charY);
|
||||
}
|
||||
}
|
||||
@@ -426,32 +418,32 @@ export async function renderLabelToDataUrl(options: RenderLabelOptions): Promise
|
||||
const lines = layoutHorizontalTextLines(ctx, String(value), writableW, wordWrap);
|
||||
const totalTextHeight = lines.length * lineHeight;
|
||||
|
||||
let textX = ex + paddingPx;
|
||||
let textX = ex + padPx.left;
|
||||
let textAlign: CanvasTextAlign = 'left';
|
||||
if (elem.textAlign === 'center') {
|
||||
textX = ex + paddingPx + writableW / 2;
|
||||
textX = ex + padPx.left + writableW / 2;
|
||||
textAlign = 'center';
|
||||
} else if (elem.textAlign === 'right') {
|
||||
textX = ex + paddingPx + (writableW - 2);
|
||||
textX = ex + padPx.left + (writableW - 2);
|
||||
textAlign = 'right';
|
||||
} else {
|
||||
textX = ex + paddingPx + 2;
|
||||
textX = ex + padPx.left + 2;
|
||||
}
|
||||
ctx.textAlign = textAlign;
|
||||
|
||||
let startY: number;
|
||||
if (vAlign === 'top') {
|
||||
startY = ey + paddingPx + lineHeight / 2;
|
||||
startY = ey + padPx.top + lineHeight / 2;
|
||||
} else if (vAlign === 'bottom') {
|
||||
startY = ey + eh - paddingPx - totalTextHeight + lineHeight / 2;
|
||||
startY = ey + eh - padPx.bottom - totalTextHeight + lineHeight / 2;
|
||||
} else {
|
||||
startY =
|
||||
ey + paddingPx + Math.max(0, (writableH - totalTextHeight) / 2) + lineHeight / 2;
|
||||
ey + padPx.top + Math.max(0, (writableH - totalTextHeight) / 2) + lineHeight / 2;
|
||||
}
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const lineY = startY + i * lineHeight;
|
||||
if (lineY - lineHeight / 2 <= ey + eh - paddingPx) {
|
||||
if (lineY - lineHeight / 2 <= ey + eh - padPx.bottom) {
|
||||
const line = lines[i];
|
||||
ctx.fillText(line, textX, lineY);
|
||||
drawTextLineDecorations(ctx, elem, textX, lineY, line, fontSizePx, textAlign);
|
||||
@@ -468,7 +460,7 @@ export async function renderLabelToDataUrl(options: RenderLabelOptions): Promise
|
||||
} else if (elem.type === 'barcode') {
|
||||
try {
|
||||
drawElementChrome(ctx, ex, ey, ew, eh, elem, scale);
|
||||
const inner = getPaddedRect(ex, ey, ew, eh, elem.padding || 0, scale);
|
||||
const inner = getPaddedRectPx(ex, ey, ew, eh, elem, scale);
|
||||
const tempCanvas = document.createElement('canvas');
|
||||
const barcodeValue = value ? String(value).trim() : mode === 'design' ? 'SAMPLE' : '';
|
||||
|
||||
@@ -488,7 +480,7 @@ export async function renderLabelToDataUrl(options: RenderLabelOptions): Promise
|
||||
} catch (error) {
|
||||
console.warn('Barcode drawing failed', error);
|
||||
if (mode === 'design') {
|
||||
const inner = getPaddedRect(ex, ey, ew, eh, elem.padding || 0, scale);
|
||||
const inner = getPaddedRectPx(ex, ey, ew, eh, elem, scale);
|
||||
ctx.fillStyle = '#f3f4f6';
|
||||
ctx.fillRect(inner.x, inner.y, inner.w, inner.h);
|
||||
ctx.strokeStyle = '#ef4444';
|
||||
@@ -503,7 +495,7 @@ export async function renderLabelToDataUrl(options: RenderLabelOptions): Promise
|
||||
} else if (elem.type === 'qrcode') {
|
||||
try {
|
||||
drawElementChrome(ctx, ex, ey, ew, eh, elem, scale);
|
||||
const inner = getPaddedRect(ex, ey, ew, eh, elem.padding || 0, scale);
|
||||
const inner = getPaddedRectPx(ex, ey, ew, eh, elem, scale);
|
||||
const qrValue = value ? String(value).trim() : mode === 'design' ? 'SAMPLE QR' : '';
|
||||
|
||||
if (qrValue) {
|
||||
@@ -522,7 +514,7 @@ export async function renderLabelToDataUrl(options: RenderLabelOptions): Promise
|
||||
} catch (error) {
|
||||
console.warn('QR code drawing failed', error);
|
||||
if (mode === 'design') {
|
||||
const inner = getPaddedRect(ex, ey, ew, eh, elem.padding || 0, scale);
|
||||
const inner = getPaddedRectPx(ex, ey, ew, eh, elem, scale);
|
||||
ctx.fillStyle = '#f3f4f6';
|
||||
ctx.fillRect(inner.x, inner.y, inner.w, inner.h);
|
||||
ctx.strokeStyle = '#ef4444';
|
||||
@@ -532,7 +524,7 @@ export async function renderLabelToDataUrl(options: RenderLabelOptions): Promise
|
||||
}
|
||||
} else if (elem.type === 'image') {
|
||||
drawElementChrome(ctx, ex, ey, ew, eh, elem, scale);
|
||||
const inner = getPaddedRect(ex, ey, ew, eh, elem.padding || 0, scale);
|
||||
const inner = getPaddedRectPx(ex, ey, ew, eh, elem, scale);
|
||||
const src = value ? String(value).trim() : '';
|
||||
if (!src) {
|
||||
if (mode === 'design') {
|
||||
|
||||
Reference in New Issue
Block a user