@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering
406 lines • 15.5 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Segments = void 0;
const x6_common_1 = require("@antv/x6-common");
const x6_geometry_1 = require("@antv/x6-geometry");
const view_1 = require("../../view/view");
const tool_1 = require("../../view/tool");
const Util = __importStar(require("./util"));
class Segments extends tool_1.ToolsView.ToolItem {
constructor() {
super(...arguments);
this.handles = [];
}
get vertices() {
return this.cellView.cell.getVertices();
}
update() {
this.render();
return this;
}
onRender() {
x6_common_1.Dom.addClass(this.container, this.prefixClassName('edge-tool-segments'));
this.resetHandles();
const edgeView = this.cellView;
const vertices = [...this.vertices];
vertices.unshift(edgeView.sourcePoint);
vertices.push(edgeView.targetPoint);
for (let i = 0, l = vertices.length; i < l - 1; i += 1) {
const vertex = vertices[i];
const nextVertex = vertices[i + 1];
const handle = this.renderHandle(vertex, nextVertex, i);
this.stamp(handle.container);
this.handles.push(handle);
}
return this;
}
renderHandle(vertex, nextVertex, index) {
const handle = this.options.createHandle({
index,
graph: this.graph,
guard: (evt) => this.guard(evt),
attrs: this.options.attrs || {},
});
if (this.options.processHandle) {
this.options.processHandle(handle);
}
this.updateHandle(handle, vertex, nextVertex);
this.container.appendChild(handle.container);
this.startHandleListening(handle);
return handle;
}
startHandleListening(handle) {
handle.on('change', this.onHandleChange, this);
handle.on('changing', this.onHandleChanging, this);
handle.on('changed', this.onHandleChanged, this);
}
stopHandleListening(handle) {
handle.off('change', this.onHandleChange, this);
handle.off('changing', this.onHandleChanging, this);
handle.off('changed', this.onHandleChanged, this);
}
resetHandles() {
const handles = this.handles;
this.handles = [];
if (handles) {
handles.forEach((handle) => {
this.stopHandleListening(handle);
handle.remove();
});
}
}
shiftHandleIndexes(delta) {
const handles = this.handles;
for (let i = 0, n = handles.length; i < n; i += 1) {
handles[i].options.index += delta;
}
}
resetAnchor(type, anchor) {
const edge = this.cellView.cell;
const options = {
ui: true,
toolId: this.cid,
};
if (anchor) {
edge.prop([type, 'anchor'], anchor, options);
}
else {
edge.removeProp([type, 'anchor'], options);
}
}
snapHandle(handle, position, data) {
const axis = handle.options.axis;
const index = handle.options.index;
const edgeView = this.cellView;
const edge = edgeView.cell;
const vertices = edge.getVertices();
const prev = vertices[index - 2] || data.sourceAnchor;
const next = vertices[index + 1] || data.targetAnchor;
const snapRadius = this.options.snapRadius;
if (Math.abs(position[axis] - prev[axis]) < snapRadius) {
position[axis] = prev[axis];
}
else if (Math.abs(position[axis] - next[axis]) < snapRadius) {
position[axis] = next[axis];
}
return position;
}
onHandleChanging({ handle, e, }) {
const graph = this.graph;
const options = this.options;
const edgeView = this.cellView;
const anchorFn = options.anchor;
const axis = handle.options.axis;
const index = handle.options.index - 1;
const data = this.getEventData(e);
const evt = this.normalizeEvent(e);
const coords = graph.snapToGrid(evt.clientX, evt.clientY);
const position = this.snapHandle(handle, coords.clone(), data);
const vertices = x6_common_1.ObjectExt.cloneDeep(this.vertices);
let vertex = vertices[index];
let nextVertex = vertices[index + 1];
// First Segment
const sourceView = edgeView.sourceView;
const sourceBBox = edgeView.sourceBBox;
let changeSourceAnchor = false;
let deleteSourceAnchor = false;
if (!vertex) {
vertex = edgeView.sourceAnchor.toJSON();
vertex[axis] = position[axis];
if (sourceBBox.containsPoint(vertex)) {
changeSourceAnchor = true;
}
else {
vertices.unshift(vertex);
this.shiftHandleIndexes(1);
deleteSourceAnchor = true;
}
}
else if (index === 0) {
if (sourceBBox.containsPoint(vertex)) {
vertices.shift();
this.shiftHandleIndexes(-1);
changeSourceAnchor = true;
}
else {
vertex[axis] = position[axis];
deleteSourceAnchor = true;
}
}
else {
vertex[axis] = position[axis];
}
if (typeof anchorFn === 'function' && sourceView) {
if (changeSourceAnchor) {
const sourceAnchorPosition = data.sourceAnchor.clone();
sourceAnchorPosition[axis] = position[axis];
const sourceAnchor = x6_common_1.FunctionExt.call(anchorFn, edgeView, sourceAnchorPosition, sourceView, edgeView.sourceMagnet || sourceView.container, 'source', edgeView, this);
this.resetAnchor('source', sourceAnchor);
}
if (deleteSourceAnchor) {
this.resetAnchor('source', data.sourceAnchorDef);
}
}
// Last segment
const targetView = edgeView.targetView;
const targetBBox = edgeView.targetBBox;
let changeTargetAnchor = false;
let deleteTargetAnchor = false;
if (!nextVertex) {
nextVertex = edgeView.targetAnchor.toJSON();
nextVertex[axis] = position[axis];
if (targetBBox.containsPoint(nextVertex)) {
changeTargetAnchor = true;
}
else {
vertices.push(nextVertex);
deleteTargetAnchor = true;
}
}
else if (index === vertices.length - 2) {
if (targetBBox.containsPoint(nextVertex)) {
vertices.pop();
changeTargetAnchor = true;
}
else {
nextVertex[axis] = position[axis];
deleteTargetAnchor = true;
}
}
else {
nextVertex[axis] = position[axis];
}
if (typeof anchorFn === 'function' && targetView) {
if (changeTargetAnchor) {
const targetAnchorPosition = data.targetAnchor.clone();
targetAnchorPosition[axis] = position[axis];
const targetAnchor = x6_common_1.FunctionExt.call(anchorFn, edgeView, targetAnchorPosition, targetView, edgeView.targetMagnet || targetView.container, 'target', edgeView, this);
this.resetAnchor('target', targetAnchor);
}
if (deleteTargetAnchor) {
this.resetAnchor('target', data.targetAnchorDef);
}
}
if (!x6_geometry_1.Point.equalPoints(vertices, this.vertices)) {
this.cellView.cell.setVertices(vertices, { ui: true, toolId: this.cid });
}
this.updateHandle(handle, vertex, nextVertex, 0);
if (!options.stopPropagation) {
edgeView.notifyMouseMove(evt, coords.x, coords.y);
}
}
onHandleChange({ handle, e }) {
const options = this.options;
const handles = this.handles;
const edgeView = this.cellView;
const index = handle.options.index;
if (!Array.isArray(handles)) {
return;
}
for (let i = 0, n = handles.length; i < n; i += 1) {
if (i !== index) {
handles[i].hide();
}
}
this.focus();
this.setEventData(e, {
sourceAnchor: edgeView.sourceAnchor.clone(),
targetAnchor: edgeView.targetAnchor.clone(),
sourceAnchorDef: x6_common_1.ObjectExt.cloneDeep(this.cell.prop(['source', 'anchor'])),
targetAnchorDef: x6_common_1.ObjectExt.cloneDeep(this.cell.prop(['target', 'anchor'])),
});
this.cell.startBatch('move-segment', { ui: true, toolId: this.cid });
if (!options.stopPropagation) {
const normalizedEvent = this.normalizeEvent(e);
const coords = this.graph.snapToGrid(normalizedEvent.clientX, normalizedEvent.clientY);
edgeView.notifyMouseDown(normalizedEvent, coords.x, coords.y);
}
}
onHandleChanged({ e }) {
const options = this.options;
const edgeView = this.cellView;
if (options.removeRedundancies) {
edgeView.removeRedundantLinearVertices({ ui: true, toolId: this.cid });
}
const normalizedEvent = this.normalizeEvent(e);
const coords = this.graph.snapToGrid(normalizedEvent.clientX, normalizedEvent.clientY);
this.render();
this.blur();
this.cell.stopBatch('move-segment', { ui: true, toolId: this.cid });
if (!options.stopPropagation) {
edgeView.notifyMouseUp(normalizedEvent, coords.x, coords.y);
}
edgeView.checkMouseleave(normalizedEvent);
options.onChanged && options.onChanged({ edge: edgeView.cell, edgeView });
}
updateHandle(handle, vertex, nextVertex, offset = 0) {
const precision = this.options.precision || 0;
const vertical = Math.abs(vertex.x - nextVertex.x) < precision;
const horizontal = Math.abs(vertex.y - nextVertex.y) < precision;
if (vertical || horizontal) {
const segmentLine = new x6_geometry_1.Line(vertex, nextVertex);
const length = segmentLine.length();
if (length < this.options.threshold) {
handle.hide();
}
else {
const position = segmentLine.getCenter();
const axis = vertical ? 'x' : 'y';
position[axis] += offset || 0;
const angle = segmentLine.vector().vectorAngle(new x6_geometry_1.Point(1, 0));
handle.updatePosition(position.x, position.y, angle, this.cellView);
handle.show();
handle.options.axis = axis;
}
}
else {
handle.hide();
}
}
onRemove() {
this.resetHandles();
}
}
exports.Segments = Segments;
(function (Segments) {
class Handle extends view_1.View {
constructor(options) {
super();
this.options = options;
this.render();
this.delegateEvents({
mousedown: 'onMouseDown',
touchstart: 'onMouseDown',
});
}
render() {
this.container = view_1.View.createElement('rect', true);
const attrs = this.options.attrs;
if (typeof attrs === 'function') {
const defaults = Segments.getDefaults();
this.setAttrs(Object.assign(Object.assign({}, defaults.attrs), attrs(this)));
}
else {
this.setAttrs(attrs);
}
this.addClass(this.prefixClassName('edge-tool-segment'));
}
updatePosition(x, y, angle, view) {
const p = view.getClosestPoint(new x6_geometry_1.Point(x, y)) || new x6_geometry_1.Point(x, y);
let matrix = x6_common_1.Dom.createSVGMatrix().translate(p.x, p.y);
if (!p.equals({ x, y })) {
const line = new x6_geometry_1.Line(x, y, p.x, p.y);
let deg = line.vector().vectorAngle(new x6_geometry_1.Point(1, 0));
if (deg !== 0) {
deg += 90;
}
matrix = matrix.rotate(deg);
}
else {
matrix = matrix.rotate(angle);
}
this.setAttrs({
transform: x6_common_1.Dom.matrixToTransformString(matrix),
cursor: angle % 180 === 0 ? 'row-resize' : 'col-resize',
});
}
onMouseDown(evt) {
if (this.options.guard(evt)) {
return;
}
this.trigger('change', { e: evt, handle: this });
evt.stopPropagation();
evt.preventDefault();
this.options.graph.view.undelegateEvents();
this.delegateDocumentEvents({
mousemove: 'onMouseMove',
touchmove: 'onMouseMove',
mouseup: 'onMouseUp',
touchend: 'onMouseUp',
touchcancel: 'onMouseUp',
}, evt.data);
}
onMouseMove(evt) {
this.emit('changing', { e: evt, handle: this });
}
onMouseUp(evt) {
this.emit('changed', { e: evt, handle: this });
this.undelegateDocumentEvents();
this.options.graph.view.delegateEvents();
}
show() {
this.container.style.display = '';
}
hide() {
this.container.style.display = 'none';
}
}
Segments.Handle = Handle;
})(Segments = exports.Segments || (exports.Segments = {}));
(function (Segments) {
Segments.config({
name: 'segments',
precision: 0.5,
threshold: 40,
snapRadius: 10,
stopPropagation: true,
removeRedundancies: true,
attrs: {
width: 20,
height: 8,
x: -10,
y: -4,
rx: 4,
ry: 4,
fill: '#333',
stroke: '#fff',
'stroke-width': 2,
},
createHandle: (options) => new Segments.Handle(options),
anchor: Util.getAnchor,
});
})(Segments = exports.Segments || (exports.Segments = {}));
//# sourceMappingURL=segments.js.map