feat: enable free movement of measurement tool label box
This commit is contained in:
@ -221,7 +221,8 @@ export class DrawingManager {
|
||||
type: 'measure',
|
||||
p1: { time: pos.time, price: pos.price },
|
||||
p2: { time: pos.time, price: pos.price },
|
||||
color: '#26a69a'
|
||||
color: '#26a69a',
|
||||
labelOffset: { x: 0, y: 0 }
|
||||
};
|
||||
this.update();
|
||||
return;
|
||||
@ -285,11 +286,18 @@ export class DrawingManager {
|
||||
|
||||
handleMouseMove(e) {
|
||||
const pos = this.getMousePos(e);
|
||||
|
||||
// Hover cursor logic
|
||||
if (!this.isMouseDown && !this.activeTool) {
|
||||
const hit = this.findHit(pos.x, pos.y);
|
||||
this.container.style.cursor = hit ? 'pointer' : 'default';
|
||||
if (hit) {
|
||||
this.container.style.cursor = hit.part === 'label' ? 'move' : 'pointer';
|
||||
} else {
|
||||
this.container.style.cursor = 'default';
|
||||
}
|
||||
}
|
||||
|
||||
// Track measurement even if mouse is up (Click-Move-Click)
|
||||
if (this.currentDrawing && this.currentDrawing.type === 'measure') {
|
||||
if (pos.time !== null) {
|
||||
this.currentDrawing.p2 = { time: pos.time, price: pos.price };
|
||||
@ -303,6 +311,18 @@ export class DrawingManager {
|
||||
if (this.selectedDrawing && this.dragMode) {
|
||||
if (pos.time === null || pos.price === null) return;
|
||||
const d = this.selectedDrawing;
|
||||
|
||||
if (this.dragMode === 'label') {
|
||||
// Free movement of ONLY the label field
|
||||
const dx = pos.x - this.dragStartPos.x;
|
||||
const dy = pos.y - this.dragStartPos.y;
|
||||
d.labelOffset.x += dx;
|
||||
d.labelOffset.y += dy;
|
||||
this.dragStartPos = pos;
|
||||
this.update();
|
||||
return; // Critical: exit here so we don't move measurement points
|
||||
}
|
||||
|
||||
if (this.dragMode === 'p1') {
|
||||
d.p1 = { time: pos.time, price: pos.price };
|
||||
} else if (this.dragMode === 'p2') {
|
||||
@ -361,6 +381,15 @@ export class DrawingManager {
|
||||
const threshold = 10;
|
||||
for (let i = this.drawings.length - 1; i >= 0; i--) {
|
||||
const d = this.drawings[i];
|
||||
|
||||
// Check for label hit first (highest z-order)
|
||||
if (d.type === 'measure' && d.labelPos) {
|
||||
if (x >= d.labelPos.x && x <= d.labelPos.x + d.labelPos.width &&
|
||||
y >= d.labelPos.y && y <= d.labelPos.y + d.labelPos.height) {
|
||||
return { drawing: d, part: 'label' };
|
||||
}
|
||||
}
|
||||
|
||||
if (d.p1 && d.p2) {
|
||||
const x1 = this.chart.timeScale().timeToCoordinate(d.p1.time);
|
||||
const y1 = this.series.priceToCoordinate(d.p1.price);
|
||||
@ -645,8 +674,14 @@ export class DrawingManager {
|
||||
ctx.font = '500 12px Inter';
|
||||
const labelWidth = Math.max(...labelLines.map(l => ctx.measureText(l).width)) + 24;
|
||||
const labelHeight = 65;
|
||||
const labelX = x2 - labelWidth / 2;
|
||||
const labelY = isUp ? y2 - labelHeight - 10 : y2 + 10;
|
||||
const defaultLabelX = x2 - labelWidth / 2;
|
||||
const defaultLabelY = isUp ? y2 - labelHeight - 10 : y2 + 10;
|
||||
|
||||
const labelX = defaultLabelX + (d.labelOffset?.x || 0);
|
||||
const labelY = defaultLabelY + (d.labelOffset?.y || 0);
|
||||
|
||||
// Store label position for hit detection
|
||||
d.labelPos = { x: labelX, y: labelY, width: labelWidth, height: labelHeight };
|
||||
|
||||
// Solid Box
|
||||
ctx.fillStyle = color;
|
||||
|
||||
Reference in New Issue
Block a user