UNPKG

ag-charts-community

Version:

Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue

267 lines 8.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const shape_1 = require("./shape"); const object_1 = require("../../util/object"); const bbox_1 = require("../bbox"); const hdpiCanvas_1 = require("../../canvas/hdpiCanvas"); class Text extends shape_1.Shape { constructor() { super(...arguments); this._x = 0; this._y = 0; this.lineBreakRegex = /\r?\n/g; this.lines = []; this._text = ''; this._dirtyFont = true; this._fontSize = 10; this._fontFamily = 'sans-serif'; this._textAlign = Text.defaultStyles.textAlign; this._textBaseline = Text.defaultStyles.textBaseline; this._lineHeight = 14; } set x(value) { if (this._x !== value) { this._x = value; this.dirty = true; } } get x() { return this._x; } set y(value) { if (this._y !== value) { this._y = value; this.dirty = true; } } get y() { return this._y; } splitText() { this.lines = this._text.split(this.lineBreakRegex); } set text(value) { const str = String(value); // `value` can be an object here if (this._text !== str) { this._text = str; this.splitText(); this.dirty = true; } } get text() { return this._text; } get font() { if (this.dirtyFont) { this.dirtyFont = false; this._font = getFont(this.fontSize, this.fontFamily, this.fontStyle, this.fontWeight); } return this._font; } set dirtyFont(value) { if (this._dirtyFont !== value) { this._dirtyFont = value; if (value) { this.dirty = true; } } } get dirtyFont() { return this._dirtyFont; } set fontStyle(value) { if (this._fontStyle !== value) { this._fontStyle = value; this.dirtyFont = true; } } get fontStyle() { return this._fontStyle; } set fontWeight(value) { if (this._fontWeight !== value) { this._fontWeight = value; this.dirtyFont = true; } } get fontWeight() { return this._fontWeight; } set fontSize(value) { if (!isFinite(value)) { value = 10; } if (this._fontSize !== value) { this._fontSize = value; this.dirtyFont = true; } } get fontSize() { return this._fontSize; } set fontFamily(value) { if (this._fontFamily !== value) { this._fontFamily = value; this.dirtyFont = true; } } get fontFamily() { return this._fontFamily; } set textAlign(value) { if (this._textAlign !== value) { this._textAlign = value; this.dirty = true; } } get textAlign() { return this._textAlign; } set textBaseline(value) { if (this._textBaseline !== value) { this._textBaseline = value; this.dirty = true; } } get textBaseline() { return this._textBaseline; } set lineHeight(value) { // Multi-line text is complicated because: // - Canvas does not support it natively, so we have to implement it manually // - need to know the height of each line -> need to parse the font shorthand -> // generally impossible to do because font size may not be in pixels // - so, need to measure the text instead, each line individually -> expensive // - or make the user provide the line height manually for multi-line text // - computeBBox should use the lineHeight for multi-line text but ignore it otherwise // - textBaseline kind of loses its meaning for multi-line text if (this._lineHeight !== value) { this._lineHeight = value; this.dirty = true; } } get lineHeight() { return this._lineHeight; } computeBBox() { return hdpiCanvas_1.HdpiCanvas.has.textMetrics ? this.getPreciseBBox() : this.getApproximateBBox(); } getPreciseBBox() { const metrics = hdpiCanvas_1.HdpiCanvas.measureText(this.text, this.font, this.textBaseline, this.textAlign); return new bbox_1.BBox(this.x - metrics.actualBoundingBoxLeft, this.y - metrics.actualBoundingBoxAscent, metrics.width, metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent); } getApproximateBBox() { const size = hdpiCanvas_1.HdpiCanvas.getTextSize(this.text, this.font); let { x, y } = this; switch (this.textAlign) { case 'end': case 'right': x -= size.width; break; case 'center': x -= size.width / 2; } switch (this.textBaseline) { case 'alphabetic': y -= size.height * 0.7; break; case 'middle': y -= size.height * 0.45; break; case 'ideographic': y -= size.height; break; case 'hanging': y -= size.height * 0.2; break; case 'bottom': y -= size.height; break; } return new bbox_1.BBox(x, y, size.width, size.height); } isPointInPath(x, y) { const point = this.transformPoint(x, y); const bbox = this.computeBBox(); return bbox ? bbox.containsPoint(point.x, point.y) : false; } isPointInStroke(x, y) { return false; } render(ctx) { if (!this.lines.length || !this.scene) { return; } if (this.dirtyTransform) { this.computeTransformMatrix(); } // this.matrix.transformBBox(this.computeBBox!()).render(ctx); // debug this.matrix.toContext(ctx); const { fill, stroke, strokeWidth } = this; ctx.font = this.font; ctx.textAlign = this.textAlign; ctx.textBaseline = this.textBaseline; const pixelRatio = this.scene.canvas.pixelRatio || 1; const { globalAlpha } = ctx; if (fill) { ctx.fillStyle = fill; ctx.globalAlpha = globalAlpha * this.opacity * this.fillOpacity; const { fillShadow, text, x, y } = this; if (fillShadow && fillShadow.enabled) { ctx.shadowColor = fillShadow.color; ctx.shadowOffsetX = fillShadow.xOffset * pixelRatio; ctx.shadowOffsetY = fillShadow.yOffset * pixelRatio; ctx.shadowBlur = fillShadow.blur * pixelRatio; } ctx.fillText(text, x, y); } if (stroke && strokeWidth) { ctx.strokeStyle = stroke; ctx.lineWidth = strokeWidth; ctx.globalAlpha = globalAlpha * this.opacity * this.strokeOpacity; const { lineDash, lineDashOffset, lineCap, lineJoin, strokeShadow, text, x, y } = this; if (lineDash) { ctx.setLineDash(lineDash); } if (lineDashOffset) { ctx.lineDashOffset = lineDashOffset; } if (lineCap) { ctx.lineCap = lineCap; } if (lineJoin) { ctx.lineJoin = lineJoin; } if (strokeShadow && strokeShadow.enabled) { ctx.shadowColor = strokeShadow.color; ctx.shadowOffsetX = strokeShadow.xOffset * pixelRatio; ctx.shadowOffsetY = strokeShadow.yOffset * pixelRatio; ctx.shadowBlur = strokeShadow.blur * pixelRatio; } ctx.strokeText(text, x, y); } this.dirty = false; } } exports.Text = Text; Text.className = 'Text'; Text.defaultStyles = object_1.chainObjects(shape_1.Shape.defaultStyles, { textAlign: 'start', fontStyle: undefined, fontWeight: undefined, fontSize: 10, fontFamily: 'sans-serif', textBaseline: 'alphabetic' }); function getFont(fontSize, fontFamily, fontStyle, fontWeight) { return [ fontStyle || '', fontWeight || '', fontSize + 'px', fontFamily ].join(' ').trim(); } exports.getFont = getFont; //# sourceMappingURL=text.js.map