UNPKG

@antv/x6

Version:

JavaScript diagramming library that uses SVG and HTML for rendering.

197 lines (171 loc) 4.47 kB
import { Point } from '../../geometry' import { Dom, NumberExt, FunctionExt } from '../../util' import { CellView } from '../../view/cell' import { NodeView } from '../../view/node' import { EdgeView } from '../../view/edge' import { ToolsView } from '../../view/tool' import * as Util from './util' import { Cell } from '../../model' export class Button extends ToolsView.ToolItem< EdgeView | NodeView, Button.Options > { protected onRender() { Dom.addClass(this.container, this.prefixClassName('cell-tool-button')) this.update() } update() { this.updatePosition() return this } protected updatePosition() { const view = this.cellView const matrix = view.cell.isEdge() ? this.getEdgeMatrix() : this.getNodeMatrix() Dom.transform(this.container as SVGElement, matrix, { absolute: true }) } protected getNodeMatrix() { const view = this.cellView as NodeView const options = this.options let { x = 0, y = 0 } = options const { offset, useCellGeometry, rotate } = options let bbox = Util.getViewBBox(view, useCellGeometry) const angle = view.cell.getAngle() if (!rotate) { bbox = bbox.bbox(angle) } let offsetX = 0 let offsetY = 0 if (typeof offset === 'number') { offsetX = offset offsetY = offset } else if (typeof offset === 'object') { offsetX = offset.x offsetY = offset.y } x = NumberExt.normalizePercentage(x, bbox.width) y = NumberExt.normalizePercentage(y, bbox.height) let matrix = Dom.createSVGMatrix().translate( bbox.x + bbox.width / 2, bbox.y + bbox.height / 2, ) if (rotate) { matrix = matrix.rotate(angle) } matrix = matrix.translate( x + offsetX - bbox.width / 2, y + offsetY - bbox.height / 2, ) return matrix } protected getEdgeMatrix() { const view = this.cellView as EdgeView const options = this.options const { offset = 0, distance = 0, rotate } = options let tangent let position let angle if (NumberExt.isPercentage(distance)) { tangent = view.getTangentAtRatio(parseFloat(distance) / 100) } else { tangent = view.getTangentAtLength(distance) } if (tangent) { position = tangent.start angle = tangent.vector().vectorAngle(new Point(1, 0)) || 0 } else { position = view.getConnection()!.start! angle = 0 } let matrix = Dom.createSVGMatrix() .translate(position.x, position.y) .rotate(angle) if (typeof offset === 'object') { matrix = matrix.translate(offset.x || 0, offset.y || 0) } else { matrix = matrix.translate(0, offset) } if (!rotate) { matrix = matrix.rotate(-angle) } return matrix } protected onMouseDown(e: JQuery.MouseDownEvent) { if (this.guard(e)) { return } e.stopPropagation() e.preventDefault() const onClick = this.options.onClick if (typeof onClick === 'function') { FunctionExt.call(onClick, this.cellView, { e, view: this.cellView, cell: this.cellView.cell, btn: this, }) } } } export namespace Button { export interface Options extends ToolsView.ToolItem.Options { x?: number y?: number distance?: number offset?: number | Point.PointLike rotate?: boolean useCellGeometry?: boolean onClick?: ( this: CellView, args: { e: JQuery.MouseDownEvent cell: Cell view: CellView btn: Button }, ) => any } } export namespace Button { Button.config<Button.Options>({ name: 'button', events: { mousedown: 'onMouseDown', touchstart: 'onMouseDown', }, }) } export namespace Button { export const Remove = Button.define<Button.Options>({ name: 'button-remove', markup: [ { tagName: 'circle', selector: 'button', attrs: { r: 7, fill: '#FF1D00', cursor: 'pointer', }, }, { tagName: 'path', selector: 'icon', attrs: { d: 'M -3 -3 3 3 M -3 3 3 -3', fill: 'none', stroke: '#FFFFFF', 'stroke-width': 2, 'pointer-events': 'none', }, }, ], distance: 60, offset: 0, onClick({ view, btn }) { btn.parent.remove() view.cell.remove({ ui: true, toolId: btn.cid }) }, }) }