[d565449] | 1 | "use strict";
|
---|
| 2 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
| 3 | exports.TextPath = void 0;
|
---|
| 4 | const Util_1 = require("../Util");
|
---|
| 5 | const Factory_1 = require("../Factory");
|
---|
| 6 | const Shape_1 = require("../Shape");
|
---|
| 7 | const Path_1 = require("./Path");
|
---|
| 8 | const Text_1 = require("./Text");
|
---|
| 9 | const Validators_1 = require("../Validators");
|
---|
| 10 | const Global_1 = require("../Global");
|
---|
| 11 | var EMPTY_STRING = '', NORMAL = 'normal';
|
---|
| 12 | function _fillFunc(context) {
|
---|
| 13 | context.fillText(this.partialText, 0, 0);
|
---|
| 14 | }
|
---|
| 15 | function _strokeFunc(context) {
|
---|
| 16 | context.strokeText(this.partialText, 0, 0);
|
---|
| 17 | }
|
---|
| 18 | class TextPath extends Shape_1.Shape {
|
---|
| 19 | constructor(config) {
|
---|
| 20 | super(config);
|
---|
| 21 | this.dummyCanvas = Util_1.Util.createCanvasElement();
|
---|
| 22 | this.dataArray = [];
|
---|
| 23 | this._readDataAttribute();
|
---|
| 24 | this.on('dataChange.konva', function () {
|
---|
| 25 | this._readDataAttribute();
|
---|
| 26 | this._setTextData();
|
---|
| 27 | });
|
---|
| 28 | this.on('textChange.konva alignChange.konva letterSpacingChange.konva kerningFuncChange.konva fontSizeChange.konva fontFamilyChange.konva', this._setTextData);
|
---|
| 29 | this._setTextData();
|
---|
| 30 | }
|
---|
| 31 | _getTextPathLength() {
|
---|
| 32 | return Path_1.Path.getPathLength(this.dataArray);
|
---|
| 33 | }
|
---|
| 34 | _getPointAtLength(length) {
|
---|
| 35 | if (!this.attrs.data) {
|
---|
| 36 | return null;
|
---|
| 37 | }
|
---|
| 38 | const totalLength = this.pathLength;
|
---|
| 39 | if (length - 1 > totalLength) {
|
---|
| 40 | return null;
|
---|
| 41 | }
|
---|
| 42 | return Path_1.Path.getPointAtLengthOfDataArray(length, this.dataArray);
|
---|
| 43 | }
|
---|
| 44 | _readDataAttribute() {
|
---|
| 45 | this.dataArray = Path_1.Path.parsePathData(this.attrs.data);
|
---|
| 46 | this.pathLength = this._getTextPathLength();
|
---|
| 47 | }
|
---|
| 48 | _sceneFunc(context) {
|
---|
| 49 | context.setAttr('font', this._getContextFont());
|
---|
| 50 | context.setAttr('textBaseline', this.textBaseline());
|
---|
| 51 | context.setAttr('textAlign', 'left');
|
---|
| 52 | context.save();
|
---|
| 53 | var textDecoration = this.textDecoration();
|
---|
| 54 | var fill = this.fill();
|
---|
| 55 | var fontSize = this.fontSize();
|
---|
| 56 | var glyphInfo = this.glyphInfo;
|
---|
| 57 | if (textDecoration === 'underline') {
|
---|
| 58 | context.beginPath();
|
---|
| 59 | }
|
---|
| 60 | for (var i = 0; i < glyphInfo.length; i++) {
|
---|
| 61 | context.save();
|
---|
| 62 | var p0 = glyphInfo[i].p0;
|
---|
| 63 | context.translate(p0.x, p0.y);
|
---|
| 64 | context.rotate(glyphInfo[i].rotation);
|
---|
| 65 | this.partialText = glyphInfo[i].text;
|
---|
| 66 | context.fillStrokeShape(this);
|
---|
| 67 | if (textDecoration === 'underline') {
|
---|
| 68 | if (i === 0) {
|
---|
| 69 | context.moveTo(0, fontSize / 2 + 1);
|
---|
| 70 | }
|
---|
| 71 | context.lineTo(fontSize, fontSize / 2 + 1);
|
---|
| 72 | }
|
---|
| 73 | context.restore();
|
---|
| 74 | }
|
---|
| 75 | if (textDecoration === 'underline') {
|
---|
| 76 | context.strokeStyle = fill;
|
---|
| 77 | context.lineWidth = fontSize / 20;
|
---|
| 78 | context.stroke();
|
---|
| 79 | }
|
---|
| 80 | context.restore();
|
---|
| 81 | }
|
---|
| 82 | _hitFunc(context) {
|
---|
| 83 | context.beginPath();
|
---|
| 84 | var glyphInfo = this.glyphInfo;
|
---|
| 85 | if (glyphInfo.length >= 1) {
|
---|
| 86 | var p0 = glyphInfo[0].p0;
|
---|
| 87 | context.moveTo(p0.x, p0.y);
|
---|
| 88 | }
|
---|
| 89 | for (var i = 0; i < glyphInfo.length; i++) {
|
---|
| 90 | var p1 = glyphInfo[i].p1;
|
---|
| 91 | context.lineTo(p1.x, p1.y);
|
---|
| 92 | }
|
---|
| 93 | context.setAttr('lineWidth', this.fontSize());
|
---|
| 94 | context.setAttr('strokeStyle', this.colorKey);
|
---|
| 95 | context.stroke();
|
---|
| 96 | }
|
---|
| 97 | getTextWidth() {
|
---|
| 98 | return this.textWidth;
|
---|
| 99 | }
|
---|
| 100 | getTextHeight() {
|
---|
| 101 | Util_1.Util.warn('text.getTextHeight() method is deprecated. Use text.height() - for full height and text.fontSize() - for one line height.');
|
---|
| 102 | return this.textHeight;
|
---|
| 103 | }
|
---|
| 104 | setText(text) {
|
---|
| 105 | return Text_1.Text.prototype.setText.call(this, text);
|
---|
| 106 | }
|
---|
| 107 | _getContextFont() {
|
---|
| 108 | return Text_1.Text.prototype._getContextFont.call(this);
|
---|
| 109 | }
|
---|
| 110 | _getTextSize(text) {
|
---|
| 111 | var dummyCanvas = this.dummyCanvas;
|
---|
| 112 | var _context = dummyCanvas.getContext('2d');
|
---|
| 113 | _context.save();
|
---|
| 114 | _context.font = this._getContextFont();
|
---|
| 115 | var metrics = _context.measureText(text);
|
---|
| 116 | _context.restore();
|
---|
| 117 | return {
|
---|
| 118 | width: metrics.width,
|
---|
| 119 | height: parseInt(`${this.fontSize()}`, 10),
|
---|
| 120 | };
|
---|
| 121 | }
|
---|
| 122 | _setTextData() {
|
---|
| 123 | const { width, height } = this._getTextSize(this.attrs.text);
|
---|
| 124 | this.textWidth = width;
|
---|
| 125 | this.textHeight = height;
|
---|
| 126 | this.glyphInfo = [];
|
---|
| 127 | if (!this.attrs.data) {
|
---|
| 128 | return null;
|
---|
| 129 | }
|
---|
| 130 | const letterSpacing = this.letterSpacing();
|
---|
| 131 | const align = this.align();
|
---|
| 132 | const kerningFunc = this.kerningFunc();
|
---|
| 133 | const textWidth = Math.max(this.textWidth + ((this.attrs.text || '').length - 1) * letterSpacing, 0);
|
---|
| 134 | let offset = 0;
|
---|
| 135 | if (align === 'center') {
|
---|
| 136 | offset = Math.max(0, this.pathLength / 2 - textWidth / 2);
|
---|
| 137 | }
|
---|
| 138 | if (align === 'right') {
|
---|
| 139 | offset = Math.max(0, this.pathLength - textWidth);
|
---|
| 140 | }
|
---|
| 141 | const charArr = (0, Text_1.stringToArray)(this.text());
|
---|
| 142 | let offsetToGlyph = offset;
|
---|
| 143 | for (var i = 0; i < charArr.length; i++) {
|
---|
| 144 | const charStartPoint = this._getPointAtLength(offsetToGlyph);
|
---|
| 145 | if (!charStartPoint)
|
---|
| 146 | return;
|
---|
| 147 | let glyphWidth = this._getTextSize(charArr[i]).width + letterSpacing;
|
---|
| 148 | if (charArr[i] === ' ' && align === 'justify') {
|
---|
| 149 | const numberOfSpaces = this.text().split(' ').length - 1;
|
---|
| 150 | glyphWidth += (this.pathLength - textWidth) / numberOfSpaces;
|
---|
| 151 | }
|
---|
| 152 | const charEndPoint = this._getPointAtLength(offsetToGlyph + glyphWidth);
|
---|
| 153 | if (!charEndPoint)
|
---|
| 154 | return;
|
---|
| 155 | const width = Path_1.Path.getLineLength(charStartPoint.x, charStartPoint.y, charEndPoint.x, charEndPoint.y);
|
---|
| 156 | let kern = 0;
|
---|
| 157 | if (kerningFunc) {
|
---|
| 158 | try {
|
---|
| 159 | kern = kerningFunc(charArr[i - 1], charArr[i]) * this.fontSize();
|
---|
| 160 | }
|
---|
| 161 | catch (e) {
|
---|
| 162 | kern = 0;
|
---|
| 163 | }
|
---|
| 164 | }
|
---|
| 165 | charStartPoint.x += kern;
|
---|
| 166 | charEndPoint.x += kern;
|
---|
| 167 | this.textWidth += kern;
|
---|
| 168 | const midpoint = Path_1.Path.getPointOnLine(kern + width / 2.0, charStartPoint.x, charStartPoint.y, charEndPoint.x, charEndPoint.y);
|
---|
| 169 | const rotation = Math.atan2(charEndPoint.y - charStartPoint.y, charEndPoint.x - charStartPoint.x);
|
---|
| 170 | this.glyphInfo.push({
|
---|
| 171 | transposeX: midpoint.x,
|
---|
| 172 | transposeY: midpoint.y,
|
---|
| 173 | text: charArr[i],
|
---|
| 174 | rotation: rotation,
|
---|
| 175 | p0: charStartPoint,
|
---|
| 176 | p1: charEndPoint,
|
---|
| 177 | });
|
---|
| 178 | offsetToGlyph += glyphWidth;
|
---|
| 179 | }
|
---|
| 180 | }
|
---|
| 181 | getSelfRect() {
|
---|
| 182 | if (!this.glyphInfo.length) {
|
---|
| 183 | return {
|
---|
| 184 | x: 0,
|
---|
| 185 | y: 0,
|
---|
| 186 | width: 0,
|
---|
| 187 | height: 0,
|
---|
| 188 | };
|
---|
| 189 | }
|
---|
| 190 | var points = [];
|
---|
| 191 | this.glyphInfo.forEach(function (info) {
|
---|
| 192 | points.push(info.p0.x);
|
---|
| 193 | points.push(info.p0.y);
|
---|
| 194 | points.push(info.p1.x);
|
---|
| 195 | points.push(info.p1.y);
|
---|
| 196 | });
|
---|
| 197 | var minX = points[0] || 0;
|
---|
| 198 | var maxX = points[0] || 0;
|
---|
| 199 | var minY = points[1] || 0;
|
---|
| 200 | var maxY = points[1] || 0;
|
---|
| 201 | var x, y;
|
---|
| 202 | for (var i = 0; i < points.length / 2; i++) {
|
---|
| 203 | x = points[i * 2];
|
---|
| 204 | y = points[i * 2 + 1];
|
---|
| 205 | minX = Math.min(minX, x);
|
---|
| 206 | maxX = Math.max(maxX, x);
|
---|
| 207 | minY = Math.min(minY, y);
|
---|
| 208 | maxY = Math.max(maxY, y);
|
---|
| 209 | }
|
---|
| 210 | var fontSize = this.fontSize();
|
---|
| 211 | return {
|
---|
| 212 | x: minX - fontSize / 2,
|
---|
| 213 | y: minY - fontSize / 2,
|
---|
| 214 | width: maxX - minX + fontSize,
|
---|
| 215 | height: maxY - minY + fontSize,
|
---|
| 216 | };
|
---|
| 217 | }
|
---|
| 218 | destroy() {
|
---|
| 219 | Util_1.Util.releaseCanvas(this.dummyCanvas);
|
---|
| 220 | return super.destroy();
|
---|
| 221 | }
|
---|
| 222 | }
|
---|
| 223 | exports.TextPath = TextPath;
|
---|
| 224 | TextPath.prototype._fillFunc = _fillFunc;
|
---|
| 225 | TextPath.prototype._strokeFunc = _strokeFunc;
|
---|
| 226 | TextPath.prototype._fillFuncHit = _fillFunc;
|
---|
| 227 | TextPath.prototype._strokeFuncHit = _strokeFunc;
|
---|
| 228 | TextPath.prototype.className = 'TextPath';
|
---|
| 229 | TextPath.prototype._attrsAffectingSize = ['text', 'fontSize', 'data'];
|
---|
| 230 | (0, Global_1._registerNode)(TextPath);
|
---|
| 231 | Factory_1.Factory.addGetterSetter(TextPath, 'data');
|
---|
| 232 | Factory_1.Factory.addGetterSetter(TextPath, 'fontFamily', 'Arial');
|
---|
| 233 | Factory_1.Factory.addGetterSetter(TextPath, 'fontSize', 12, (0, Validators_1.getNumberValidator)());
|
---|
| 234 | Factory_1.Factory.addGetterSetter(TextPath, 'fontStyle', NORMAL);
|
---|
| 235 | Factory_1.Factory.addGetterSetter(TextPath, 'align', 'left');
|
---|
| 236 | Factory_1.Factory.addGetterSetter(TextPath, 'letterSpacing', 0, (0, Validators_1.getNumberValidator)());
|
---|
| 237 | Factory_1.Factory.addGetterSetter(TextPath, 'textBaseline', 'middle');
|
---|
| 238 | Factory_1.Factory.addGetterSetter(TextPath, 'fontVariant', NORMAL);
|
---|
| 239 | Factory_1.Factory.addGetterSetter(TextPath, 'text', EMPTY_STRING);
|
---|
| 240 | Factory_1.Factory.addGetterSetter(TextPath, 'textDecoration', null);
|
---|
| 241 | Factory_1.Factory.addGetterSetter(TextPath, 'kerningFunc', null);
|
---|