Загрузка данных
import { CanvasRenderingTarget2D } from 'fancy-canvas';
import { IPrimitivePaneRenderer } from 'lightweight-charts';
import { getThemeStore } from '@src/theme';
import { Text } from './text';
const UI = {
borderWidth: 1,
borderRadius: 4,
padding: 6,
selectionBorderWidth: 1,
selectionDashLength: 4,
selectionDashGap: 3,
};
export class TextPaneRenderer implements IPrimitivePaneRenderer {
private readonly text: Text;
constructor(text: Text) {
this.text = text;
}
public draw(target: CanvasRenderingTarget2D): void {
const data = this.text.getRenderData();
if (!data) {
return;
}
target.useBitmapCoordinateSpace(({ context, horizontalPixelRatio, verticalPixelRatio }) => {
const pixelRatio = Math.max(horizontalPixelRatio, verticalPixelRatio);
const left = data.left * horizontalPixelRatio;
const top = data.top * verticalPixelRatio;
const width = data.width * horizontalPixelRatio;
const height = data.height * verticalPixelRatio;
const paddingX = UI.padding * horizontalPixelRatio;
const paddingY = UI.padding * verticalPixelRatio;
const borderRadius = UI.borderRadius * pixelRatio;
context.save();
context.fillStyle = data.backgroundColor;
fillRoundedRect(context, left, top, width, height, borderRadius);
context.strokeStyle = data.borderColor;
context.lineWidth = UI.borderWidth * pixelRatio;
strokeRoundedRect(context, left, top, width, height, borderRadius);
context.save();
context.beginPath();
context.rect(left, top, width, height);
context.clip();
context.font = data.font;
context.fillStyle = data.textColor;
context.textAlign = 'left';
context.textBaseline = 'top';
data.lines.forEach((line, index) => {
context.fillText(
line,
left + paddingX,
top + paddingY + index * data.lineHeight * verticalPixelRatio,
);
});
context.restore();
if (data.showSelectionBorder) {
drawSelectionBorder(context, left, top, width, height, borderRadius, pixelRatio);
}
context.restore();
});
}
}
function drawSelectionBorder(
context: CanvasRenderingContext2D,
x: number,
y: number,
width: number,
height: number,
radius: number,
pixelRatio: number,
): void {
const { colors } = getThemeStore();
context.save();
context.strokeStyle = colors.chartLineColor;
context.lineWidth = UI.selectionBorderWidth * pixelRatio;
context.setLineDash([
UI.selectionDashLength * pixelRatio,
UI.selectionDashGap * pixelRatio,
]);
strokeRoundedRect(context, x, y, width, height, radius);
context.restore();
}
function fillRoundedRect(
context: CanvasRenderingContext2D,
x: number,
y: number,
width: number,
height: number,
radius: number,
): void {
context.beginPath();
buildRoundedRectPath(context, x, y, width, height, radius);
context.fill();
}
function strokeRoundedRect(
context: CanvasRenderingContext2D,
x: number,
y: number,
width: number,
height: number,
radius: number,
): void {
context.beginPath();
buildRoundedRectPath(context, x, y, width, height, radius);
context.stroke();
}
function buildRoundedRectPath(
context: CanvasRenderingContext2D,
x: number,
y: number,
width: number,
height: number,
radius: number,
): void {
const safeRadius = Math.min(radius, width / 2, height / 2);
context.moveTo(x + safeRadius, y);
context.arcTo(x + width, y, x + width, y + height, safeRadius);
context.arcTo(x + width, y + height, x, y + height, safeRadius);
context.arcTo(x, y + height, x, y, safeRadius);
context.arcTo(x, y, x + width, y, safeRadius);
context.closePath();
}