/** * @fileoverview text * @author dengfuping_develop@163.com */ import { each } from '@antv/util'; import { detect } from 'detect-browser'; import { setTransform } from '../util/svg'; import { SVG_ATTR_MAP } from '../constant'; import ShapeBase from './base'; const LETTER_SPACING = 0.3; const BASELINE_MAP = { top: 'before-edge', middle: 'central', bottom: 'after-edge', alphabetic: 'baseline', hanging: 'hanging', }; // for FireFox const BASELINE_MAP_FOR_FIREFOX = { top: 'text-before-edge', middle: 'central', bottom: 'text-after-edge', alphabetic: 'alphabetic', hanging: 'hanging', }; const ANCHOR_MAP = { left: 'left', start: 'left', center: 'middle', right: 'end', end: 'end', }; class Text extends ShapeBase { type: string = 'text'; canFill: boolean = true; canStroke: boolean = true; getDefaultAttrs() { const attrs = super.getDefaultAttrs(); return { ...attrs, x: 0, y: 0, text: null, fontSize: 12, fontFamily: 'sans-serif', fontStyle: 'normal', fontWeight: 'normal', fontVariant: 'normal', textAlign: 'start', textBaseline: 'bottom', }; } createPath(context, targetAttrs) { const attrs = this.attr(); const el = this.get('el'); this._setFont(); each(targetAttrs || attrs, (value, attr) => { if (attr === 'text') { this._setText(`${value}`); } else if (attr === 'matrix' && value) { setTransform(this); } else if (SVG_ATTR_MAP[attr]) { el.setAttribute(SVG_ATTR_MAP[attr], value); } }); el.setAttribute('paint-order', 'stroke'); el.setAttribute('style', 'stroke-linecap:butt; stroke-linejoin:miter;'); } _setFont() { const el = this.get('el'); const { textBaseline, textAlign } = this.attr(); const browser = detect(); if (browser && browser.name === 'firefox') { // compatible with FireFox browser, ref: https://github.com/antvis/g/issues/119 el.setAttribute('dominant-baseline', BASELINE_MAP_FOR_FIREFOX[textBaseline] || 'alphabetic'); } else { el.setAttribute('alignment-baseline', BASELINE_MAP[textBaseline] || 'baseline'); } el.setAttribute('text-anchor', ANCHOR_MAP[textAlign] || 'left'); } _setText(text) { const el = this.get('el'); const { x, textBaseline: baseline = 'bottom' } = this.attr(); if (!text) { el.innerHTML = ''; } else if (~text.indexOf('\n')) { const textArr = text.split('\n'); const textLen = textArr.length - 1; let arr = ''; each(textArr, (segment, i: number) => { if (i === 0) { if (baseline === 'alphabetic') { arr += `${segment}`; } else if (baseline === 'top') { arr += `${segment}`; } else if (baseline === 'middle') { arr += `${segment}`; } else if (baseline === 'bottom') { arr += `${segment}`; } else if (baseline === 'hanging') { arr += `${segment}`; } } else { arr += `${segment}`; } }); el.innerHTML = arr; } else { el.innerHTML = text; } } } export default Text;