@devexperts/dxcharts-lite
Version:
90 lines (89 loc) • 4.61 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 } from '../../canvas/canvas-bounds-container';
import { CandleSeriesModel } from '../../model/candle-series.model';
import { flat } from '../../utils/array.utils';
export class BaselineDrawer {
constructor(baseLineModel, canvasBoundContainer) {
this.baseLineModel = baseLineModel;
this.canvasBoundContainer = canvasBoundContainer;
}
draw(ctx, points, model, hitTestDrawerConfig) {
if (hitTestDrawerConfig !== undefined && model instanceof CandleSeriesModel) {
const visualCandles = flat(points);
// calculate baseline
const baselineYPercents = this.baseLineModel.baselineYPercents;
const chartBounds = this.canvasBoundContainer.getBounds(CanvasElement.CHART);
const baseLine = chartBounds.y + chartBounds.height * (baselineYPercents / 100);
const first = visualCandles[0];
for (let i = 0; i < visualCandles.length; i++) {
const current = visualCandles[i];
const prev = visualCandles[i - 1];
const next = visualCandles[i + 1];
const firstLineXPx = model.view.toX(first.centerUnit);
const currentLineXPx = model.view.toX(current.centerUnit);
const currentCloseYPx = model.view.toY(current.close);
const prevHigherThanBL = prev ? model.view.toY(prev.close) < baseLine : false;
const curHigherThanBL = currentCloseYPx < baseLine;
if (prev !== void 0 && prevHigherThanBL !== curHigherThanBL) {
setBaselineFillStyle(ctx, model, hitTestDrawerConfig, prevHigherThanBL);
const prevLineXPx = model.view.toX(prev.centerUnit);
const prevCloseYPx = model.view.toY(prev.close);
// our goal here is to find the crossing point X between chart line and baseline
const distanceWidth = currentLineXPx - prevLineXPx;
const distanceHeight = currentCloseYPx - prevCloseYPx;
const tg = distanceWidth / distanceHeight;
const distanceHeightToBL = currentCloseYPx - baseLine;
// distance from crossing point BL and area line to current candle X
const distanceWidthBL = tg * distanceHeightToBL;
const xPx = prevLineXPx + (distanceWidth - distanceWidthBL);
ctx.lineTo(xPx, baseLine);
ctx.stroke();
ctx.lineTo(firstLineXPx, baseLine);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.moveTo(xPx, baseLine);
}
if (prev === void 0) {
ctx.beginPath();
ctx.moveTo(currentLineXPx, currentCloseYPx);
}
else if (next === void 0) {
setBaselineFillStyle(ctx, model, hitTestDrawerConfig, curHigherThanBL);
ctx.lineTo(currentLineXPx, currentCloseYPx);
ctx.stroke();
ctx.lineTo(currentLineXPx, baseLine);
ctx.lineTo(firstLineXPx, baseLine);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.moveTo(firstLineXPx, baseLine);
ctx.lineTo(currentLineXPx, baseLine);
ctx.strokeStyle = model.colors.baseLineTheme.baselineColor;
ctx.stroke();
}
else {
ctx.lineTo(currentLineXPx, currentCloseYPx);
}
}
}
}
}
const setBaselineFillStyle = (ctx, candleSeries, hitTestDrawerConfig, upper) => {
if (hitTestDrawerConfig.color) {
ctx.fillStyle = hitTestDrawerConfig.color;
ctx.strokeStyle = hitTestDrawerConfig.color;
}
else {
ctx.fillStyle = upper
? candleSeries.colors.baseLineTheme.upperSectionFillColor
: candleSeries.colors.baseLineTheme.lowerSectionFillColor;
ctx.strokeStyle = upper
? candleSeries.colors.baseLineTheme.upperSectionStrokeColor
: candleSeries.colors.baseLineTheme.lowerSectionStrokeColor;
}
};