|
|
|
|
| class SvgArrow { |
| static yArrows: number = 0; |
| |
| container: HTMLElement; |
| markFrom: HTMLElement; |
| markTo: HTMLElement; |
| score: number; |
| classNames: string[] = []; |
| constructor(container: HTMLElement, markFrom: HTMLElement, markTo: HTMLElement, score: number) { |
| this.container = container; |
| this.markFrom = markFrom; |
| this.markTo = markTo; |
| this.score = score; |
| } |
| |
| |
| _el(tag, options): SVGElement { |
| const { classnames = [], attributes = [], style = [], children = [], text, id, xlink } = options; |
| const ns = 'http://www.w3.org/2000/svg'; |
| const nsx = 'http://www.w3.org/1999/xlink'; |
| const el = document.createElementNS(ns, tag); |
|
|
| classnames.forEach(name => el.classList.add(name)); |
| attributes.forEach(([attr, value]) => el.setAttribute(attr, value)); |
| style.forEach(([ prop, value ]) => el.style[prop] = value); |
| if(xlink) el.setAttributeNS(nsx, 'xlink:href', xlink); |
| if(text) el.appendChild(document.createTextNode(text)); |
| if(id) el.id = id; |
| children.forEach(child => el.appendChild(child)); |
| return el; |
| } |
| |
| |
| generate(): SVGElement { |
| const rand = Math.random().toString(36).substr(2, 8); |
| |
| const startX = this.markTo.getBoundingClientRect().left |
| - this.container.getBoundingClientRect().left |
| + this.markTo.getBoundingClientRect().width / 2; |
| |
| const endX = this.markFrom.getBoundingClientRect().left |
| - this.container.getBoundingClientRect().left |
| + this.markFrom.getBoundingClientRect().width / 2; |
| |
| const curveY = Math.max(-50, SvgArrow.yArrows - (endX - startX) / 3.2); |
| |
| return this._el('g', { |
| classnames: [ 'displacy-arrow' ].concat(this.classNames), |
| children: [ |
| this._el('path', { |
| id: `arrow-${rand}`, |
| classnames: [ 'displacy-arc' ], |
| attributes: [ |
| [ 'd', `M${startX},${SvgArrow.yArrows} C${startX},${curveY} ${endX},${curveY} ${endX},${SvgArrow.yArrows}`], |
| [ 'stroke-width', '2px' ], |
| [ 'fill', 'none' ], |
| [ 'stroke', 'currentColor' ], |
| ] |
| }), |
| this._el('text', { |
| attributes: [ |
| [ 'dy', '1em' ] |
| ], |
| children: [ |
| this._el('textPath', { |
| xlink: `#arrow-${rand}`, |
| classnames: [ 'displacy-label' ], |
| attributes: [ |
| [ 'startOffset', '50%' ], |
| [ 'fill', 'currentColor' ], |
| [ 'text-anchor', 'middle' ], |
| ], |
| text: this.score.toFixed(2) |
| }) |
| ] |
| }), |
| ] |
| }); |
| } |
| } |
|
|