@devexperts/dxcharts-lite
Version:
126 lines (125 loc) • 6.28 kB
JavaScript
/*
* Copyright (C) 2019 - 2025 Devexperts Solutions IE Limited
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { CanvasElement, CHART_UUID } from '../../../canvas/canvas-bounds-container';
import { getFontFromConfig, } from '../../../chart.config';
import { redrawBackgroundArea } from '../../../drawers/chart-background.drawer';
import { avoidAntialiasing, drawLine } from '../../../utils/canvas/canvas-drawing-functions.utils';
import { calculateSymbolHeight, calculateTextWidth } from '../../../utils/canvas/canvas-font-measure-tool.utils';
import { floor } from '../../../utils/math.utils';
import { drawBadgeLabel, drawPlainLabel, drawRectLabel, checkLabelInBoundaries } from '../y-axis-labels.drawer';
export const DEFAULT_LABEL_APPEARANCE_TYPE = 'badge';
const DEFAULT_PADDING = 4;
export const priceLabelDrawersMap = {
badge: drawBadgeLabel,
rectangle: drawRectLabel,
plain: drawPlainLabel,
};
/**
* Draws label on Y axis with provided parameters.
* @param ctx - canvas 2D context to draw on
* @param bounds - bounds of Y axis
* @param visualLabel
* @param canvasBoundsContainer
* @param config
*/
export function drawLabel(ctx, yAxisDescriptionsCtx, backgroundCtx, bounds, paneBounds, visualLabel, canvasBoundsContainer, config, colors) {
var _a, _b, _c, _d, _e;
const centralY = visualLabel.y;
const text = visualLabel.labelText;
const mode = (_a = visualLabel.mode) !== null && _a !== void 0 ? _a : 'label';
const appearanceType = (_b = visualLabel.labelType) !== null && _b !== void 0 ? _b : DEFAULT_LABEL_APPEARANCE_TYPE;
const description = visualLabel.description;
const textFont = (_c = visualLabel.textFont) !== null && _c !== void 0 ? _c : getFontFromConfig(config);
const bgColor = visualLabel.bgColor;
const lineColor = (_d = visualLabel.lineColor) !== null && _d !== void 0 ? _d : bgColor;
const descriptionWidth = calculateTextWidth(description !== null && description !== void 0 ? description : '', ctx, textFont) + 8;
const labelY = floor(visualLabel.y);
const fontHeight = calculateSymbolHeight(textFont, ctx);
const labelBoxTopY = centralY - fontHeight / 2;
const labelBoxBottomY = centralY + fontHeight / 2;
const labelBoxHeight = labelBoxBottomY - labelBoxTopY;
ctx.save();
ctx.fillStyle = bgColor;
ctx.strokeStyle = lineColor;
const chartBounds = canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(CHART_UUID));
const drawLabel = priceLabelDrawersMap[appearanceType];
const showDescription = config.labels.descriptions;
const showLine = isLineVisible(bounds, labelY, labelBoxHeight);
const _drawDescription = () => showDescription &&
drawDescription(backgroundCtx, yAxisDescriptionsCtx, bounds, paneBounds, visualLabel, config);
let lineXStart;
let lineXEnd;
// line should touch the label
const lineStartAdjust = 2;
if (config.align === 'right') {
lineXStart = chartBounds.x;
lineXEnd = showDescription
? chartBounds.x + chartBounds.width - descriptionWidth
: chartBounds.x + chartBounds.width + lineStartAdjust;
}
else {
lineXStart = showDescription ? chartBounds.x + descriptionWidth : chartBounds.x - lineStartAdjust;
lineXEnd = chartBounds.x + chartBounds.width;
}
const lineY = (_e = visualLabel.lineY) !== null && _e !== void 0 ? _e : visualLabel.y;
const _drawLine = () => showLine && avoidAntialiasing(ctx, () => drawLine(ctx, lineXStart, lineY, lineXEnd, lineY, 1));
const _drawLabel = () => drawLabel(ctx, bounds, text, centralY, visualLabel, config, colors.yAxis, false);
const drawLineLabel = () => {
_drawLine();
_drawDescription();
};
const drawLineLabelLabel = () => {
_drawLine();
_drawLabel();
_drawDescription();
};
const drawLabelLabel = () => {
_drawDescription();
_drawLabel();
};
const labelDrawerByMode = {
line: drawLineLabel,
'line-label': drawLineLabelLabel,
label: drawLabelLabel,
};
if (mode !== 'none' && checkLabelInBoundaries(centralY, bounds, labelBoxHeight)) {
labelDrawerByMode[mode]();
}
ctx.restore();
}
const isLineVisible = (bounds, labelY, labelBoxHeight) => labelY > bounds.y + labelBoxHeight / 2 && labelY < bounds.y + bounds.height - labelBoxHeight / 2;
function drawDescription(backgroundCtx, ctx, labelBounds, paneBounds, visualLabel, yAxisState) {
var _a, _b, _c;
const align = yAxisState.align || 'right';
const description = visualLabel.description;
if (!description || description.length === 0) {
return;
}
const centralY = visualLabel.y;
const textFont = getFontFromConfig(yAxisState);
const descriptionWidth = calculateTextWidth(description, ctx, textFont);
const fontHeight = calculateSymbolHeight(textFont, ctx);
const paddingTop = (_a = visualLabel.paddingTop) !== null && _a !== void 0 ? _a : DEFAULT_PADDING;
const paddingBottom = (_b = visualLabel.paddingBottom) !== null && _b !== void 0 ? _b : DEFAULT_PADDING;
const labelBoxY = centralY - fontHeight / 2 - paddingTop;
const labelBoxBottom = centralY + fontHeight / 2 + paddingBottom;
const labelBoxHeight = labelBoxBottom - labelBoxY;
ctx.save();
// overlay rect
const width = descriptionWidth + 5;
const descriptionPadding = 4;
const rectWidth = descriptionWidth + descriptionPadding * 2;
const boundsEnd = paneBounds.x + paneBounds.width;
const x = align === 'right' ? boundsEnd - rectWidth : paneBounds.x + descriptionPadding;
redrawBackgroundArea(backgroundCtx, ctx, x, labelBoxY, width, labelBoxHeight, 0.8);
ctx.fillStyle = (_c = visualLabel.descColor) !== null && _c !== void 0 ? _c : visualLabel.bgColor;
ctx.font = textFont;
const xTextBounds = align === 'right'
? boundsEnd - descriptionWidth - descriptionPadding * 2
: paneBounds.x + descriptionPadding * 2;
ctx.fillText(description, xTextBounds, centralY + fontHeight / 2 - 1); // -1 for font height adjustment
ctx.restore();
}