Загрузка данных
import {
getAnchorFromPoint,
getContainerSize,
getPriceDelta,
getXCoordinateFromTime,
getYCoordinateFromPrice,
shiftTimeByPixels,
} from '@core/Drawings/helpers';
import { DrawingBase } from '@core/Drawings/DrawingBase';
import type { Anchor, Bounds, ContainerSize, Point } from '@core/Drawings/types';
import type { SettingsValues } from '@src/types';
export type TwoPointAnchorKind = 'start' | 'end';
export interface TwoPointGeometry extends Bounds {
startPoint: Point;
endPoint: Point;
}
export abstract class TwoPointDrawingBase<
TSettings extends SettingsValues = SettingsValues,
THandleId extends string = string,
> extends DrawingBase<TSettings, THandleId> {
protected startAnchor: Anchor | null = null;
protected endAnchor: Anchor | null = null;
protected getAnchor(kind: TwoPointAnchorKind): Anchor | null {
return kind === 'start'
? this.startAnchor
: this.endAnchor;
}
protected setAnchor(
kind: TwoPointAnchorKind,
anchor: Anchor | null,
): void {
if (kind === 'start') {
this.startAnchor = anchor;
return;
}
this.endAnchor = anchor;
}
protected setAnchors(
startAnchor: Anchor | null,
endAnchor: Anchor | null,
): void {
this.startAnchor = startAnchor;
this.endAnchor = endAnchor;
}
protected createAnchor(point: Point): Anchor | null {
return getAnchorFromPoint(
this.chart,
this.series,
point,
);
}
protected getPointFromAnchor(anchor: Anchor | null): Point | null {
if (!anchor) {
return null;
}
const x = getXCoordinateFromTime(
this.chart,
anchor.time,
this.series,
);
const y = getYCoordinateFromPrice(
this.series,
anchor.price,
);
if (x === null || y === null) {
return null;
}
return {
x: Number(x),
y: Number(y),
};
}
protected setAnchorFromPoint(
kind: TwoPointAnchorKind,
point: Point,
): boolean {
const anchor = this.createAnchor(point);
if (!anchor) {
return false;
}
this.setAnchor(
kind,
anchor,
);
return true;
}
protected setAnchorsFromPoints(
startPoint: Point,
endPoint: Point,
): boolean {
const startAnchor = this.createAnchor(startPoint);
const endAnchor = this.createAnchor(endPoint);
if (!startAnchor || !endAnchor) {
return false;
}
this.setAnchors(
startAnchor,
endAnchor,
);
return true;
}
protected getAnchorTimeCoordinate(
kind: TwoPointAnchorKind,
): number | null {
const anchor = this.getAnchor(kind);
if (!anchor) {
return null;
}
const coordinate = getXCoordinateFromTime(
this.chart,
anchor.time,
this.series,
);
return coordinate === null
? null
: Number(coordinate);
}
protected getAnchorPriceCoordinate(
kind: TwoPointAnchorKind,
): number | null {
const anchor = this.getAnchor(kind);
if (!anchor) {
return null;
}
const coordinate = getYCoordinateFromPrice(
this.series,
anchor.price,
);
return coordinate === null
? null
: Number(coordinate);
}
protected moveAnchorsByPixels(
startAnchor: Anchor | null,
endAnchor: Anchor | null,
dragStartPoint: Point | null,
point: Point,
): boolean {
if (!startAnchor || !endAnchor || !dragStartPoint) {
return false;
}
const offsetX = point.x - dragStartPoint.x;
const priceOffset = getPriceDelta(
this.series,
dragStartPoint.y,
point.y,
);
const nextStartTime = shiftTimeByPixels(
this.chart,
startAnchor.time,
offsetX,
this.series,
);
const nextEndTime = shiftTimeByPixels(
this.chart,
endAnchor.time,
offsetX,
this.series,
);
if (nextStartTime === null || nextEndTime === null) {
return false;
}
this.startAnchor = {
time: nextStartTime,
price: startAnchor.price + priceOffset,
};
this.endAnchor = {
time: nextEndTime,
price: endAnchor.price + priceOffset,
};
return true;
}
protected getContainerSize(): ContainerSize {
return getContainerSize(this.container);
}
protected getTwoPointGeometry(): TwoPointGeometry | null {
const startPoint = this.getPointFromAnchor(this.startAnchor);
const endPoint = this.getPointFromAnchor(this.endAnchor);
if (!startPoint || !endPoint) {
return null;
}
return {
startPoint,
endPoint,
left: Math.min(startPoint.x, endPoint.x),
right: Math.max(startPoint.x, endPoint.x),
top: Math.min(startPoint.y, endPoint.y),
bottom: Math.max(startPoint.y, endPoint.y),
};
}
}