Загрузка данных
import { CanvasRenderingTarget2D } from 'fancy-canvas';
import { IPrimitivePaneRenderer } from 'lightweight-charts';
import { getThemeStore } from '@src/theme';
import { Traectory } from './traectory';
const UI = {
lineWidth: 2,
previewLineWidth: 1,
handleRadius: 5,
handleBorderWidth: 2,
previewDash: [6, 4],
arrowLength: 14,
arrowHalfWidth: 6,
};
export class TraectoryPaneRenderer implements IPrimitivePaneRenderer {
private readonly traectory: Traectory;
constructor(traectory: Traectory) {
this.traectory = traectory;
}
public draw(target: CanvasRenderingTarget2D): void {
const data = this.traectory.getRenderData();
if (!data) {
return;
}
target.useBitmapCoordinateSpace(({ context, horizontalPixelRatio, verticalPixelRatio }) => {
const pixelRatio = Math.max(horizontalPixelRatio, verticalPixelRatio);
const lineWidth = UI.lineWidth * pixelRatio;
const previewLineWidth = UI.previewLineWidth * pixelRatio;
const handleRadius = UI.handleRadius * pixelRatio;
const handleBorderWidth = UI.handleBorderWidth * pixelRatio;
const arrowLength = UI.arrowLength * pixelRatio;
const arrowHalfWidth = UI.arrowHalfWidth * pixelRatio;
context.save();
context.lineJoin = 'round';
context.lineCap = 'round';
context.strokeStyle = data.lineColor;
context.fillStyle = data.lineColor;
if (data.points.length > 1) {
context.lineWidth = lineWidth;
context.beginPath();
data.points.forEach((point, index) => {
const x = point.x * horizontalPixelRatio;
const y = point.y * verticalPixelRatio;
if (index === 0) {
context.moveTo(x, y);
return;
}
context.lineTo(x, y);
});
context.stroke();
}
if (data.showArrow && data.points.length > 1) {
const previousPoint = data.points[data.points.length - 2];
const lastPoint = data.points[data.points.length - 1];
context.lineWidth = lineWidth;
drawArrowHead(
context,
previousPoint.x * horizontalPixelRatio,
previousPoint.y * verticalPixelRatio,
lastPoint.x * horizontalPixelRatio,
lastPoint.y * verticalPixelRatio,
arrowLength,
arrowHalfWidth,
);
}
if (data.previewPoint && data.points.length > 0) {
const lastPoint = data.points[data.points.length - 1];
context.save();
context.lineWidth = previewLineWidth;
context.setLineDash(UI.previewDash.map((value) => value * pixelRatio));
context.beginPath();
context.moveTo(lastPoint.x * horizontalPixelRatio, lastPoint.y * verticalPixelRatio);
context.lineTo(data.previewPoint.x * horizontalPixelRatio, data.previewPoint.y * verticalPixelRatio);
context.stroke();
context.restore();
}
if (data.showHandles) {
const { colors } = getThemeStore();
context.fillStyle = colors.chartBackground;
context.strokeStyle = colors.chartLineColor;
context.lineWidth = handleBorderWidth;
data.points.forEach((point) => {
drawHandle(context, point.x * horizontalPixelRatio, point.y * verticalPixelRatio, handleRadius);
});
}
context.restore();
});
}
}
function drawHandle(context: CanvasRenderingContext2D, x: number, y: number, radius: number): void {
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2);
context.fill();
context.stroke();
}
function drawArrowHead(
context: CanvasRenderingContext2D,
fromX: number,
fromY: number,
toX: number,
toY: number,
arrowLength: number,
arrowHalfWidth: number,
): void {
const dx = toX - fromX;
const dy = toY - fromY;
const distance = Math.hypot(dx, dy);
if (distance === 0) {
return;
}
const directionX = dx / distance;
const directionY = dy / distance;
const normalX = -directionY;
const normalY = directionX;
const leftX = toX - directionX * arrowLength + normalX * arrowHalfWidth;
const leftY = toY - directionY * arrowLength + normalY * arrowHalfWidth;
const rightX = toX - directionX * arrowLength - normalX * arrowHalfWidth;
const rightY = toY - directionY * arrowLength - normalY * arrowHalfWidth;
context.beginPath();
context.moveTo(toX, toY);
context.lineTo(leftX, leftY);
context.moveTo(toX, toY);
context.lineTo(rightX, rightY);
context.stroke();
}
import { getThemeStore } from '@src/theme';
import { SettingField, SettingsTab, SettingsValues } from '@src/types';
export interface TraectoryStyle {
lineColor: string;
}
export type TraectorySettings = SettingsValues & TraectoryStyle;
export function createDefaultSettings(): TraectorySettings {
const { colors } = getThemeStore();
return {
lineColor: colors.chartLineColor,
};
}
export function getTraectorySettingsTabs(settings: TraectorySettings): SettingsTab[] {
const fields: SettingField[] = [
{
key: 'lineColor',
label: 'Цвет линии',
type: 'color',
defaultValue: settings.lineColor,
},
];
return [{ key: 'style', label: 'Стиль', fields }];
}