Загрузка данных
import { CanvasRenderingTarget2D } from 'fancy-canvas';
import { IPrimitivePaneRenderer } from 'lightweight-charts';
import { getThemeStore } from '@src/theme';
import type { Point } from '@core/Drawings/types';
import type { RegressionTrend } from './regressionTrend';
const UI = {
lineWidth: 2,
middleLineWidth: 1,
middleLineDash: 5,
middleLineGap: 4,
handleRadius: 5,
handleBorderWidth: 2,
correlationFontSize: 11,
correlationOffsetX: 4,
correlationOffsetY: 6,
};
export class RegressionTrendPaneRenderer implements IPrimitivePaneRenderer {
private readonly regressionTrend: RegressionTrend;
constructor(regressionTrend: RegressionTrend) {
this.regressionTrend = regressionTrend;
}
public draw(target: CanvasRenderingTarget2D): void {
const data = this.regressionTrend.getRenderData();
if (!data) {
return;
}
const { colors } = getThemeStore();
target.useBitmapCoordinateSpace(
({
context,
horizontalPixelRatio,
verticalPixelRatio,
}) => {
const pixelRatio = Math.max(
horizontalPixelRatio,
verticalPixelRatio,
);
const baseStart = scalePoint(
data.baseStartPoint,
horizontalPixelRatio,
verticalPixelRatio,
);
const baseEnd = scalePoint(
data.baseEndPoint,
horizontalPixelRatio,
verticalPixelRatio,
);
const upperStart = scalePoint(
data.upperStartPoint,
horizontalPixelRatio,
verticalPixelRatio,
);
const upperEnd = scalePoint(
data.upperEndPoint,
horizontalPixelRatio,
verticalPixelRatio,
);
const lowerStart = scalePoint(
data.lowerStartPoint,
horizontalPixelRatio,
verticalPixelRatio,
);
const lowerEnd = scalePoint(
data.lowerEndPoint,
horizontalPixelRatio,
verticalPixelRatio,
);
context.save();
if (data.showChannel) {
drawArea(
context,
upperStart,
upperEnd,
baseEnd,
baseStart,
data.upperFillColor,
);
drawArea(
context,
baseStart,
baseEnd,
lowerEnd,
lowerStart,
data.lowerFillColor,
);
context.strokeStyle = data.lineColor;
context.lineWidth = UI.lineWidth * pixelRatio;
drawLine(
context,
upperStart,
upperEnd,
);
drawLine(
context,
lowerStart,
lowerEnd,
);
}
if (
data.showMiddleLine ||
!data.showChannel
) {
context.save();
context.strokeStyle = data.middleLineColor;
context.lineWidth = UI.middleLineWidth * pixelRatio;
context.setLineDash([
UI.middleLineDash * pixelRatio,
UI.middleLineGap * pixelRatio,
]);
drawLine(
context,
baseStart,
baseEnd,
);
context.restore();
}
if (
data.showChannel &&
data.showCorrelation
) {
drawCorrelation(
context,
data.correlation,
upperStart,
data.lineColor,
pixelRatio,
);
}
if (data.showHandles) {
context.fillStyle = colors.chartBackground;
context.strokeStyle = colors.chartLineColor;
context.lineWidth = UI.handleBorderWidth * pixelRatio;
const radius = UI.handleRadius * pixelRatio;
drawHandle(
context,
baseStart,
radius,
);
drawHandle(
context,
baseEnd,
radius,
);
}
context.restore();
},
);
}
}
function scalePoint(
point: Point,
horizontalPixelRatio: number,
verticalPixelRatio: number,
): Point {
return {
x: point.x * horizontalPixelRatio,
y: point.y * verticalPixelRatio,
};
}
function drawLine(
context: CanvasRenderingContext2D,
start: Point,
end: Point,
): void {
context.beginPath();
context.moveTo(start.x, start.y);
context.lineTo(end.x, end.y);
context.stroke();
}
function drawArea(
context: CanvasRenderingContext2D,
first: Point,
second: Point,
third: Point,
fourth: Point,
color: string,
): void {
context.fillStyle = color;
context.beginPath();
context.moveTo(first.x, first.y);
context.lineTo(second.x, second.y);
context.lineTo(third.x, third.y);
context.lineTo(fourth.x, fourth.y);
context.closePath();
context.fill();
}
function drawHandle(
context: CanvasRenderingContext2D,
point: Point,
radius: number,
): void {
context.beginPath();
context.arc(
point.x,
point.y,
radius,
0,
Math.PI * 2,
);
context.fill();
context.stroke();
}
function drawCorrelation(
context: CanvasRenderingContext2D,
correlation: number,
point: Point,
color: string,
pixelRatio: number,
): void {
const fontSize =
UI.correlationFontSize *
pixelRatio;
context.save();
context.font =
`${fontSize}px Inter, sans-serif`;
context.fillStyle = color;
context.textAlign = 'left';
context.textBaseline = 'top';
context.fillText(
correlation.toFixed(6),
point.x +
UI.correlationOffsetX *
pixelRatio,
point.y +
UI.correlationOffsetY *
pixelRatio,
);
context.restore();
}