fix: Text rendering and settings for horizontal and vertical lines, parallel trendline text

This commit is contained in:
DiTus
2026-03-22 17:10:24 +01:00
parent f9eda9f18b
commit beda3858e9

View File

@ -391,7 +391,14 @@ export class DrawingManager {
color: defs.color,
width: defs.width,
style: defs.style,
opacity: defs.opacity
opacity: defs.opacity,
text: defs.text,
textColor: defs.textColor,
fontSize: defs.fontSize,
bold: defs.bold,
italic: defs.italic,
alignVert: defs.alignVert,
alignHorz: defs.alignHorz
});
this.setTool(null);
} else if (this.activeTool === 'vertical_line') {
@ -402,7 +409,14 @@ export class DrawingManager {
color: defs.color,
width: defs.width,
style: defs.style,
opacity: defs.opacity
opacity: defs.opacity,
text: defs.text,
textColor: defs.textColor,
fontSize: defs.fontSize,
bold: defs.bold,
italic: defs.italic,
alignVert: defs.alignVert,
alignHorz: defs.alignHorz
});
this.setTool(null);
} else if (this.activeTool === 'fib_retracement') {
@ -783,13 +797,27 @@ export class DrawingManager {
const fontStyle = (d.bold ? 'bold ' : '') + (d.italic ? 'italic ' : '');
ctx.font = `${fontStyle}${fontSize}px Inter`;
ctx.fillStyle = d.textColor || color;
let startX = x1, startY = y1, endX = x2, endY = y2;
if (x1 > x2 || (x1 === x2 && y1 > y2)) {
startX = x2; startY = y2; endX = x1; endY = y1;
}
const angle = Math.atan2(endY - startY, endX - startX);
const length = Math.hypot(endX - startX, endY - startY);
ctx.translate(startX, startY);
ctx.rotate(angle);
ctx.textAlign = d.alignHorz || 'left';
ctx.textBaseline = d.alignVert === 'middle' ? 'middle' : (d.alignVert === 'bottom' ? 'top' : 'bottom');
const tx = (x1 + x2) / 2;
const ty = (y1 + y2) / 2;
let tx = 0;
if (d.alignHorz === 'center') tx = length / 2;
else if (d.alignHorz === 'right') tx = length;
const offset = 10;
const finalTy = d.alignVert === 'top' ? ty - offset : (d.alignVert === 'bottom' ? ty + offset : ty);
const finalTy = d.alignVert === 'top' ? -offset : (d.alignVert === 'bottom' ? offset : 0);
ctx.fillText(d.text, tx, finalTy);
ctx.restore();
@ -837,41 +865,46 @@ export class DrawingManager {
ctx.beginPath(); ctx.arc(0, y, 5, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
}
// Store label position for hit detection (before rendering)
let textX = scope.mediaSize.width / 2;
let textY = y;
// Render Text and store label position
let labelPos = null;
if (d.text) {
ctx.save();
ctx.setLineDash([]);
const fontSize = d.fontSize || 14;
const fontStyle = (d.bold ? 'bold ' : '') + (d.italic ? 'italic ' : '');
const font = `${fontStyle}${fontSize}px Inter`;
ctx.font = font;
ctx.fillStyle = d.textColor || d.color;
const alignHorz = d.alignHorz || 'center';
ctx.textAlign = alignHorz;
ctx.textBaseline = d.alignVert === 'middle' ? 'middle' : (d.alignVert === 'bottom' ? 'top' : 'bottom');
let textX = scope.mediaSize.width / 2;
if (alignHorz === 'left') textX = 10;
else if (alignHorz === 'right') textX = scope.mediaSize.width - 10;
const offset = 10;
let textY = d.alignVert === 'top' ? y - offset : (d.alignVert === 'bottom' ? y + offset : y);
ctx.fillText(d.text, textX, textY);
const metrics = ctx.measureText(d.text);
const labelWidth = metrics.width + 16;
const labelHeight = 24;
const defaultLabelX = scope.mediaSize.width / 2 - labelWidth / 2;
const offset = 10;
let defaultLabelX = scope.mediaSize.width / 2 - labelWidth / 2;
if (alignHorz === 'left') defaultLabelX = 10;
else if (alignHorz === 'right') defaultLabelX = scope.mediaSize.width - labelWidth - 10;
const defaultLabelY = d.alignVert === 'top' ? y - 40 : (d.alignVert === 'bottom' ? y + 20 : y - 12);
labelPos = {
x: defaultLabelX + (d.labelOffset?.x || 0),
y: defaultLabelY + (d.labelOffset?.y || 0),
width: labelWidth,
height: labelHeight
};
textX = scope.mediaSize.width / 2;
textY = d.alignVert === 'top' ? y - offset : (d.alignVert === 'bottom' ? y + offset : y);
}
// Render Text if present
if (d.text) {
ctx.save();
ctx.setLineDash([]);
ctx.font = font;
ctx.fillStyle = d.textColor || d.color;
ctx.textAlign = d.alignHorz || 'center';
ctx.textBaseline = d.alignVert === 'middle' ? 'middle' : (d.alignVert === 'bottom' ? 'top' : 'bottom');
ctx.fillText(d.text, textX, textY);
ctx.restore();
}
@ -902,39 +935,48 @@ export class DrawingManager {
ctx.beginPath(); ctx.arc(x, 0, 5, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
}
// Store label position for hit detection (before rendering)
let textX = x;
let textY = 0;
// Render Text and store label position
let labelPos = null;
if (d.text) {
ctx.save();
ctx.setLineDash([]);
const fontSize = d.fontSize || 14;
const fontStyle = (d.bold ? 'bold ' : '') + (d.italic ? 'italic ' : '');
const font = `${fontStyle}${fontSize}px Inter`;
ctx.font = font;
ctx.fillStyle = d.textColor || d.color;
const alignHorz = d.alignHorz || 'center';
ctx.textAlign = alignHorz;
ctx.textBaseline = d.alignVert === 'middle' ? 'middle' : (d.alignVert === 'bottom' ? 'bottom' : 'top');
let textX = x;
const offset = 10;
let textY = scope.mediaSize.height / 2; // Middle
if (d.alignVert === 'top') textY = offset;
else if (d.alignVert === 'bottom') textY = scope.mediaSize.height - offset;
ctx.fillText(d.text, textX, textY);
const metrics = ctx.measureText(d.text);
const labelWidth = metrics.width + 16;
const labelHeight = 24;
const offset = 10;
const defaultLabelY = d.alignVert === 'top' ? -50 : (d.alignVert === 'bottom' ? 20 : -12);
let defaultLabelY = scope.mediaSize.height / 2 - labelHeight / 2; // Middle
if (d.alignVert === 'top') defaultLabelY = offset;
else if (d.alignVert === 'bottom') defaultLabelY = scope.mediaSize.height - offset - labelHeight;
let defaultLabelX = x - labelWidth / 2;
if (alignHorz === 'left') defaultLabelX = x - labelWidth;
else if (alignHorz === 'right') defaultLabelX = x;
labelPos = {
x: x - labelWidth / 2 + (d.labelOffset?.x || 0),
x: defaultLabelX + (d.labelOffset?.x || 0),
y: defaultLabelY + (d.labelOffset?.y || 0),
width: labelWidth,
height: labelHeight
};
textY = d.alignVert === 'top' ? -offset : (d.alignVert === 'bottom' ? offset : 0);
}
// Render Text if present
if (d.text) {
ctx.save();
ctx.setLineDash([]);
ctx.font = font;
ctx.fillStyle = d.textColor || d.color;
ctx.textAlign = d.alignHorz || 'center';
ctx.textBaseline = d.alignVert === 'middle' ? 'middle' : (d.alignVert === 'bottom' ? 'top' : 'bottom');
ctx.fillText(d.text, textX, textY);
ctx.restore();
}
@ -1374,7 +1416,7 @@ export class DrawingManager {
applySettings(key, value) {
if (this.selectedDrawing) {
if (key === 'bold' || key === 'italic' || key === 'fontSize' || key === 'text' || key === 'textColor' || key === 'alignVert' || key === 'alignHorz') {
const isLineWithText = ['trend_line', 'ray', 'rectangle'].includes(this.selectedDrawing.type);
const isLineWithText = ['trend_line', 'ray', 'rectangle', 'horizontal_line', 'vertical_line'].includes(this.selectedDrawing.type);
if (!isLineWithText) return;
this.selectedDrawing[key] = value;
} else {