UNPKG

@devexperts/dxcharts-lite

Version:
126 lines (125 loc) 6.28 kB
/* * 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(); }