@antv/g6
Version:
graph visualization frame work
221 lines (207 loc) • 6.02 kB
JavaScript
const min = Math.min;
const max = Math.max;
const abs = Math.abs;
const DEFAULT_TRIGGER = 'shift';
const ALLOW_EVENTS = [ 'drag', 'shift', 'ctrl', 'alt', 'control' ];
module.exports = {
getDefaultCfg() {
return {
brushStyle: {
fill: '#EEF6FF',
fillOpacity: 0.4,
stroke: '#DDEEFE',
lineWidth: 1
},
onSelect() {},
onDeselect() {},
selectedState: 'selected',
trigger: DEFAULT_TRIGGER,
includeEdges: true,
selectedEdges: [],
selectedNodes: []
};
},
getEvents() {
let trigger;
// 检测输入是否合法
if (ALLOW_EVENTS.indexOf(this.trigger.toLowerCase()) > -1) {
trigger = this.trigger;
} else {
trigger = DEFAULT_TRIGGER;
console.warn('Behavior brush-select的trigger参数不合法,请输入drag、shift、ctrl或alt');
}
if (trigger === 'drag') {
return {
mousedown: 'onMouseDown',
mousemove: 'onMouseMove',
mouseup: 'onMouseUp',
'canvas:click': 'clearStates'
};
}
return {
mousedown: 'onMouseDown',
mousemove: 'onMouseMove',
mouseup: 'onMouseUp',
'canvas:click': 'clearStates',
keyup: 'onKeyUp',
keydown: 'onKeyDown'
};
},
onMouseDown(e) {
// 按在node上面拖动时候不应该是框选
const { item } = e;
if (item) {
return;
}
if (this.trigger !== 'drag' && !this.keydown) {
return;
}
if (this.selectedNodes && this.selectedNodes.length !== 0) {
this.clearStates();
}
let brush = this.brush;
if (!brush) {
brush = this._createBrush();
}
this.originPoint = { x: e.canvasX, y: e.canvasY };
brush.attr({ width: 0, height: 0 });
brush.show();
this.dragging = true;
},
onMouseMove(e) {
if (!this.dragging) {
return;
}
if (this.trigger !== 'drag' && !this.keydown) {
return;
}
this._updateBrush(e);
this.graph.paint();
},
onMouseUp(e) {
if (!this.brush && !this.dragging) {
return;
}
if (this.trigger !== 'drag' && !this.keydown) {
return;
}
const graph = this.graph;
const autoPaint = graph.get('autoPaint');
graph.setAutoPaint(false);
this.brush.destroy();
this.brush = null;
this._getSelectedNodes(e);
this.dragging = false;
this.graph.paint();
graph.setAutoPaint(autoPaint);
},
clearStates() {
const graph = this.graph;
const autoPaint = graph.get('autoPaint');
graph.setAutoPaint(false);
const selectedState = this.selectedState;
const nodes = graph.findAllByState('node', selectedState);
const edges = graph.findAllByState('edge', selectedState);
nodes.forEach(node => graph.setItemState(node, selectedState, false));
edges.forEach(edge => graph.setItemState(edge, selectedState, false));
this.selectedNodes = [];
this.selectedEdges = [];
this.onDeselect && this.onDeselect(this.selectedNodes, this.selectedEdges);
graph.emit('nodeselectchange', { targets: {
nodes: [],
edges: []
}, select: false });
graph.paint();
graph.setAutoPaint(autoPaint);
},
_getSelectedNodes(e) {
const graph = this.graph;
const state = this.selectedState;
const originPoint = this.originPoint;
const p1 = { x: e.x, y: e.y };
const p2 = graph.getPointByCanvas(originPoint.x, originPoint.y);
const left = min(p1.x, p2.x);
const right = max(p1.x, p2.x);
const top = min(p1.y, p2.y);
const bottom = max(p1.y, p2.y);
const selectedNodes = [];
const shouldUpdate = this.shouldUpdate;
const selectedIds = [];
graph.getNodes().forEach(node => {
const bbox = node.getBBox();
if (bbox.centerX >= left
&& bbox.centerX <= right
&& bbox.centerY >= top
&& bbox.centerY <= bottom
) {
if (shouldUpdate(node, 'select')) {
selectedNodes.push(node);
const model = node.getModel();
selectedIds.push(model.id);
graph.setItemState(node, state, true);
}
}
});
const selectedEdges = [];
if (this.includeEdges) {
// 选中边,边的source和target都在选中的节点中时才选中
selectedNodes.forEach(node => {
const edges = node.getEdges();
edges.forEach(edge => {
const model = edge.getModel();
const { source, target } = model;
if (selectedIds.includes(source)
&& selectedIds.includes(target)
&& shouldUpdate(edge, 'select')) {
selectedEdges.push(edge);
graph.setItemState(edge, this.selectedState, true);
}
});
});
}
this.selectedEdges = selectedEdges;
this.selectedNodes = selectedNodes;
this.onSelect && this.onSelect(selectedNodes, selectedEdges);
graph.emit('nodeselectchange', { targets: {
nodes: selectedNodes,
edges: selectedEdges
}, select: true });
},
_createBrush() {
const self = this;
const brush = self.graph.get('canvas').addShape('rect', {
attrs: self.brushStyle,
capture: false
});
this.brush = brush;
return brush;
},
_updateBrush(e) {
const originPoint = this.originPoint;
this.brush.attr({
width: abs(e.canvasX - originPoint.x),
height: abs(e.canvasY - originPoint.y),
x: min(e.canvasX, originPoint.x),
y: min(e.canvasY, originPoint.y)
});
},
onKeyDown(e) {
const code = e.key;
// 按住control键时,允许用户设置trigger为ctrl
if (code && (code.toLowerCase() === this.trigger.toLowerCase())
|| code.toLowerCase() === 'control') {
this.keydown = true;
} else {
this.keydown = false;
}
},
onKeyUp() {
if (this.brush) {
// 清除所有选中状态后,设置拖得动状态为false,并清除框选的brush
this.brush.destroy();
this.brush = null;
this.dragging = false;
}
this.keydown = false;
}
};