@devexperts/dxcharts-lite
Version:
234 lines (231 loc) • 8.37 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/.
*/
/**
* The minimum supported canvas size in chart-core (in pixels).
* Any size of <canvas> element below these dimensions will not be rendered (is NOT INTENDED to be rendered).
* @doc-tags chart-core,canvas
*/
export const MIN_SUPPORTED_CANVAS_SIZE = {
width: 20,
height: 20,
};
export class CanvasModel {
constructor(eventBus, canvas, drawingManager, canvasModels, resizer, options = {}) {
var _a;
this.eventBus = eventBus;
this.canvas = canvas;
this.drawingManager = drawingManager;
this.resizer = resizer;
this.width = 0;
this.height = 0;
this.prevHeight = 0;
this.prevWidth = 0;
this.type = CANDLE_TYPE;
canvasModels.push(this);
this.parent = findHeightParent(canvas);
const ctx = canvas.getContext('2d', options);
if (ctx === null) {
throw new Error("Couldn't get 2d context????");
}
this.context = ctx;
this._canvasId = (_a = canvas.getAttribute('data-element')) !== null && _a !== void 0 ? _a : '';
this.updateCanvasWidthHeight(canvas, this.getChartResizerElement().getBoundingClientRect());
}
/**
* About rendering for non-integer dpi
* https://stackoverflow.com/questions/17553557/draw-crisp-lines-on-html5-canvas-with-browser-zoom
* @param bcr
*/
updateDPR(bcr) {
const { width, height } = bcr;
const dpi = window.devicePixelRatio;
this.canvas.style.height = height + 'px';
this.canvas.style.width = width + 'px';
this.canvas.width = width * dpi;
this.canvas.height = height * dpi;
this.width = width;
this.height = height;
this.ctx.scale(dpi, dpi);
}
get canvasId() {
return this._canvasId;
}
get ctx() {
return this.context;
}
/**
* Clears the canvas by using the clearRect method of the canvas context.
* @function
* @name clear
* @memberof Canvas
* @returns {void}
*/
clear() {
this.context.clearRect(0, 0, this.width, this.height);
}
/**
* Checks if the type is linked.
*
* @returns {boolean} Returns true if the type is linked, false otherwise.
*/
isLinked() {
var _a, _b;
return (_b = (_a = this.type) === null || _a === void 0 ? void 0 : _a.linked) !== null && _b !== void 0 ? _b : false;
}
/**
* Triggers the 'fireDraw' event on the event bus with the canvas ID as the parameter.
*/
fireDraw() {
this.eventBus.fireDraw([this.canvasId]);
}
/**
* Updates the width and height of the canvas element based on the client width and height of the canvas element and the height of the chart resizer element.
* @param {HTMLCanvasElement} canvas - The canvas element to update.
* @param {ClientRect | DOMRect} [bcr=this.getChartResizerElement().getBoundingClientRect()] - The bounding client rectangle of the chart resizer element.
* @returns {void}
*/
updateCanvasWidthHeight(canvas, bcr = this.getChartResizerElement().getBoundingClientRect()) {
if (canvas.clientWidth !== this.width) {
canvas.width = canvas.clientWidth;
this.width = canvas.clientWidth;
}
const height = bcr.height;
if (height !== this.height) {
canvas.style.height = height + 'px';
this.height = height;
canvas.height = height;
this.prevHeight = height;
}
}
/**
* Returns the chart resizer element. If the resizer is not defined, it returns the parent element.
*
* @returns {HTMLElement} The chart resizer element.
*/
getChartResizerElement() {
var _a;
return (_a = this.resizer) !== null && _a !== void 0 ? _a : this.parent;
}
/**
* Checks if the canvas is ready to be used by verifying if its width and height are greater than the minimum supported canvas size.
*
* @returns {boolean} - Returns true if the canvas is ready to be used, false otherwise.
*/
isReady() {
return this.width > MIN_SUPPORTED_CANVAS_SIZE.width && this.height > MIN_SUPPORTED_CANVAS_SIZE.height;
}
}
const CANDLE_TYPE = {
name: 'candle',
};
const BAR_TYPE = {
name: 'candle',
};
const LINE_TYPE = {
name: 'line',
linked: true,
};
const AREA_TYPE = {
name: 'area',
linked: true,
};
const TYPES = {
candle: CANDLE_TYPE,
bar: BAR_TYPE,
line: LINE_TYPE,
area: AREA_TYPE,
};
/**
* Creates a new canvas model for the main chart canvas.
*
* @param {EventBus} eventBus - The event bus used to communicate between components.
* @param {HTMLCanvasElement} canvas - The canvas element to create the model for.
* @param {HTMLElement} resizer - The element used to resize the canvas.
* @param {BarType} barType - The type of bar to use for the chart.
* @param {FullChartConfig} config - The configuration object for the chart.
* @param {DrawingManager} drawingManager - The drawing manager used to draw on the canvas.
* @param {CanvasModel[]} canvasModels - An array of canvas models to add the new model to.
*
* @returns {CanvasModel} The newly created canvas model.
export function createMainCanvasModel(
eventBus,
canvas,
resizer,
barType,
config,
drawingManager,
canvasModels,
) {
const canvasModel = createCanvasModel(eventBus, canvas, config, drawingManager, canvasModels, resizer);
// @ts-ignore
canvasModel.type = TYPES[barType] ?? CANDLE_TYPE;
return canvasModel;
}*/
export function createMainCanvasModel(eventBus, canvas, resizer, barType, config, drawingManager, canvasModels) {
var _a;
const canvasModel = createCanvasModel(eventBus, canvas, config, drawingManager, canvasModels, resizer);
// @ts-ignore
canvasModel.type = (_a = TYPES[barType]) !== null && _a !== void 0 ? _a : CANDLE_TYPE;
return canvasModel;
}
/**
* Creates a new CanvasModel instance.
*
* @param {EventBus} eventBus - The event bus to use.
* @param {HTMLCanvasElement} canvas - The canvas element to use.
* @param {FullChartConfig} config - The configuration object for the chart.
* @param {DrawingManager} drawingManager - The drawing manager to use.
* @param {CanvasModel[]} canvasModels - An array of existing canvas models.
* @param {HTMLElement} [resizer] - The element to use for resizing the canvas.
*
* @returns {CanvasModel} A new instance of the CanvasModel class.
*/
export function createCanvasModel(eventBus, canvas, config, drawingManager, canvasModels, resizer, options) {
const canvasModel = new CanvasModel(eventBus, canvas, drawingManager, canvasModels, resizer, options);
initCanvasWithConfig(canvasModel, config);
return canvasModel;
}
/**
* Initializes a canvas with a given configuration.
* @param {CanvasModel} canvasModel - The canvas model to be initialized.
* @param {FullChartConfig} config - The configuration object for the canvas.
* @returns {void}
*/
export function initCanvasWithConfig(canvasModel, config) {
const canvas = canvasModel.canvas;
if (config.fixedSize) {
canvas.width = config.fixedSize.width;
canvas.height = config.fixedSize.height;
canvas.style.width = config.fixedSize.width + 'px';
canvas.style.height = config.fixedSize.height + 'px';
canvasModel.width = config.fixedSize.width;
canvasModel.height = config.fixedSize.height;
}
canvas.style.position = 'absolute';
canvas.style.top = '0';
canvas.style.left = '0';
canvas.style.direction = 'ltr';
}
/**
* Gets the first parent with "data-chart-container" attribute to compute height
*/
function findHeightParent(initial) {
let el = initial;
while (el) {
if (el.nodeType === 1 && el.hasAttribute('data-chart-container')) {
return el;
}
else {
if (el.parentElement !== null) {
el = el.parentElement;
}
else {
break;
}
}
}
return el;
}