fix: improve timeframe-independent dragging and prevent undefined dragStartPos error

This commit is contained in:
DiTus
2026-03-21 21:57:28 +01:00
parent 7c92aa38be
commit cdfe8f1a39

View File

@ -312,10 +312,17 @@ export class DrawingManager {
if (pos.time === null || pos.price === null) return; if (pos.time === null || pos.price === null) return;
const d = this.selectedDrawing; const d = this.selectedDrawing;
// Safety check for dragStartPos
if (!this.dragStartPos) {
this.dragStartPos = pos;
return;
}
if (this.dragMode === 'label') { if (this.dragMode === 'label') {
// Free movement of ONLY the label field // Free movement of ONLY the label field
const dx = pos.x - this.dragStartPos.x; const dx = pos.x - this.dragStartPos.x;
const dy = pos.y - this.dragStartPos.y; const dy = pos.y - this.dragStartPos.y;
if (!d.labelOffset) d.labelOffset = { x: 0, y: 0 };
d.labelOffset.x += dx; d.labelOffset.x += dx;
d.labelOffset.y += dy; d.labelOffset.y += dy;
this.dragStartPos = pos; this.dragStartPos = pos;
@ -328,20 +335,34 @@ export class DrawingManager {
} else if (this.dragMode === 'p2') { } else if (this.dragMode === 'p2') {
d.p2 = { time: pos.time, price: pos.price }; d.p2 = { time: pos.time, price: pos.price };
} else if (this.dragMode === 'all') { } else if (this.dragMode === 'all') {
const timeDiff = pos.time - this.dragStartPos.time; let timeDiff = pos.time - this.dragStartPos.time;
const priceDiff = pos.price - this.dragStartPos.price; const priceDiff = pos.price - this.dragStartPos.price;
if (d.p1 && d.p2) {
d.p1.time = this.startP1.time + timeDiff; // If timeDiff is NaN (e.g., dragged into whitespace on high TF), estimate it
d.p1.price = this.startP1.price + priceDiff; if (isNaN(timeDiff) || pos.time === null) {
d.p2.time = this.startP2.time + timeDiff; const timeScale = this.chart.timeScale();
d.p2.price = this.startP2.price + priceDiff; const startLogical = timeScale.coordinateToLogical(this.dragStartPos.x);
} else if (d.time !== undefined && d.price !== undefined) { const currentLogical = timeScale.coordinateToLogical(pos.x);
d.time = this.startTime + timeDiff; if (startLogical !== null && currentLogical !== null) {
d.price = this.startPrice + priceDiff; const logicalDiff = currentLogical - startLogical;
} else if (d.price !== undefined) { timeDiff = logicalDiff * this.getIntervalSeconds();
d.price = this.startPrice + priceDiff; }
} else if (d.time !== undefined) { }
d.time = this.startTime + timeDiff;
if (!isNaN(timeDiff) && !isNaN(priceDiff)) {
if (d.p1 && d.p2) {
d.p1.time = this.startP1.time + timeDiff;
d.p1.price = this.startP1.price + priceDiff;
d.p2.time = this.startP2.time + timeDiff;
d.p2.price = this.startP2.price + priceDiff;
} else if (d.time !== undefined && d.price !== undefined) {
d.time = this.startTime + timeDiff;
d.price = this.startPrice + priceDiff;
} else if (d.price !== undefined) {
d.price = this.startPrice + priceDiff;
} else if (d.time !== undefined) {
d.time = this.startTime + timeDiff;
}
} }
} else if (this.dragMode === 'price') { } else if (this.dragMode === 'price') {
d.price = pos.price; d.price = pos.price;
@ -391,11 +412,13 @@ export class DrawingManager {
} }
if (d.p1 && d.p2) { if (d.p1 && d.p2) {
const x1 = this.chart.timeScale().timeToCoordinate(d.p1.time); const x1 = this.chart.timeScale().timeToCoordinate(this.snapToNearestTime(d.p1.time));
const y1 = this.series.priceToCoordinate(d.p1.price); const y1 = this.series.priceToCoordinate(d.p1.price);
const x2 = this.chart.timeScale().timeToCoordinate(d.p2.time); const x2 = this.chart.timeScale().timeToCoordinate(this.snapToNearestTime(d.p2.time));
const y2 = this.series.priceToCoordinate(d.p2.price); const y2 = this.series.priceToCoordinate(d.p2.price);
if (x1 === null || y1 === null || x2 === null || y2 === null) continue; if (x1 === null || y1 === null || x2 === null || y2 === null) continue;
if (Math.hypot(x - x1, y - y1) < threshold) return { drawing: d, part: 'p1' }; if (Math.hypot(x - x1, y - y1) < threshold) return { drawing: d, part: 'p1' };
if (Math.hypot(x - x2, y - y2) < threshold) return { drawing: d, part: 'p2' }; if (Math.hypot(x - x2, y - y2) < threshold) return { drawing: d, part: 'p2' };
@ -409,10 +432,10 @@ export class DrawingManager {
const dy = this.series.priceToCoordinate(d.price); const dy = this.series.priceToCoordinate(d.price);
if (Math.abs(y - dy) < threshold) return { drawing: d, part: 'price' }; if (Math.abs(y - dy) < threshold) return { drawing: d, part: 'price' };
} else if (d.time !== undefined && d.type === 'vertical_line') { } else if (d.time !== undefined && d.type === 'vertical_line') {
const dx = this.chart.timeScale().timeToCoordinate(d.time); const dx = this.chart.timeScale().timeToCoordinate(this.snapToNearestTime(d.time));
if (Math.abs(x - dx) < threshold) return { drawing: d, part: 'time' }; if (Math.abs(x - dx) < threshold) return { drawing: d, part: 'time' };
} else if (d.time !== undefined && d.price !== undefined) { } else if (d.time !== undefined && d.price !== undefined) {
const dx = this.chart.timeScale().timeToCoordinate(d.time); const dx = this.chart.timeScale().timeToCoordinate(this.snapToNearestTime(d.time));
const dy = this.series.priceToCoordinate(d.price); const dy = this.series.priceToCoordinate(d.price);
if (Math.hypot(x - dx, y - dy) < threshold) return { drawing: d, part: 'all' }; if (Math.hypot(x - dx, y - dy) < threshold) return { drawing: d, part: 'all' };
} }