mirror of
https://gitee.com/antv/g6.git
synced 2024-12-05 05:09:07 +08:00
feat(behavior): add behavior activate-relations
This commit is contained in:
parent
a5e0a9b66f
commit
5099c57d85
78
src/behavior/activate-relations.js
Normal file
78
src/behavior/activate-relations.js
Normal file
@ -0,0 +1,78 @@
|
||||
module.exports = {
|
||||
getDefaultCfg() {
|
||||
return {
|
||||
trigger: 'mouseenter', // 可选 mouseenter || click
|
||||
activeState: 'active',
|
||||
inactiveState: 'inactive',
|
||||
shouldUpdate() { return true; }
|
||||
};
|
||||
},
|
||||
getEvents() {
|
||||
if (this.get('trigger') === 'mouseenter') {
|
||||
return {
|
||||
'node:mouseenter': 'setAllItemStates',
|
||||
'node:mouseleave': 'clearAllItemStates'
|
||||
};
|
||||
}
|
||||
return {
|
||||
'node:click': 'setAllItemStates',
|
||||
'canvas:click': 'clearAllItemStates'
|
||||
};
|
||||
},
|
||||
setAllItemStates(e) {
|
||||
const graph = this.get('graph');
|
||||
const item = e.item;
|
||||
this.item = item;
|
||||
if (!this.shouldUpdate(e.item, { event: e, action: 'activate' })) {
|
||||
return;
|
||||
}
|
||||
const activeState = this.get('activeState');
|
||||
const inactiveState = this.get('inactiveState');
|
||||
graph.setAutoPaint(false);
|
||||
graph.getNodes().forEach(function(node) {
|
||||
graph.setItemState(node, activeState, false);
|
||||
inactiveState && graph.setItemState(node, inactiveState, true);
|
||||
});
|
||||
graph.getEdges().forEach(function(edge) {
|
||||
graph.setItemState(edge, activeState, false);
|
||||
inactiveState && graph.setItemState(edge, inactiveState, true);
|
||||
});
|
||||
inactiveState && graph.setItemState(item, inactiveState, false);
|
||||
graph.setItemState(item, activeState, true);
|
||||
graph.getEdges().forEach(function(edge) {
|
||||
if (edge.getSource() === item) {
|
||||
inactiveState && graph.setItemState(edge.getTarget(), inactiveState, false);
|
||||
graph.setItemState(edge.getTarget(), activeState, true);
|
||||
graph.setItemState(edge, activeState, true);
|
||||
graph.setItemState(edge, inactiveState, false);
|
||||
edge.toFront();
|
||||
} else if (edge.getTarget() === item) {
|
||||
inactiveState && graph.setItemState(edge.getSource(), inactiveState, false);
|
||||
graph.setItemState(edge.getSource(), activeState, true);
|
||||
graph.setItemState(edge, activeState, true);
|
||||
graph.setItemState(edge, inactiveState, false);
|
||||
edge.toFront();
|
||||
}
|
||||
});
|
||||
graph.paint();
|
||||
graph.setAutoPaint(true);
|
||||
graph.emit('afteractivaterelations', { item: e.item, action: 'activate' });
|
||||
},
|
||||
clearAllItemStates(e) {
|
||||
const graph = this.get('graph');
|
||||
if (!this.shouldUpdate(e.item, { event: e, action: 'deactivate' })) {
|
||||
return;
|
||||
}
|
||||
const autoPaint = graph.get('autoPaint');
|
||||
graph.setAutoPaint(false);
|
||||
graph.getNodes().forEach(function(node) {
|
||||
graph.clearItemStates(node);
|
||||
});
|
||||
graph.getEdges().forEach(function(edge) {
|
||||
graph.clearItemStates(edge);
|
||||
});
|
||||
graph.paint();
|
||||
graph.setAutoPaint(autoPaint);
|
||||
graph.emit('afteractivaterelations', { item: e.item || this.item, action: 'deactivate' });
|
||||
}
|
||||
};
|
@ -7,7 +7,8 @@ const behaviors = {
|
||||
'click-select': require('./click-select'),
|
||||
tooltip: require('./tooltip'),
|
||||
'edge-tooltip': require('./edge-tooltip'),
|
||||
'collapse-expand': require('./collapse-expand')
|
||||
'collapse-expand': require('./collapse-expand'),
|
||||
'activate-relations': require('./activate-relations')
|
||||
};
|
||||
Util.each(behaviors, (behavior, type) => {
|
||||
Behavior.registerBehavior(type, behavior);
|
||||
|
@ -224,8 +224,8 @@ class Graph extends EventEmitter {
|
||||
_initPlugins() {
|
||||
const self = this;
|
||||
Util.each(self.get('plugins'), plugin => {
|
||||
if (!plugin.destroyed && plugin.init) {
|
||||
plugin.init(self);
|
||||
if (!plugin.destroyed && plugin._init) {
|
||||
plugin._init(self);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -516,31 +516,15 @@ class Graph extends EventEmitter {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变画布大小
|
||||
* @private 仅供内部更新视口使用
|
||||
* @param {array} matrix group矩阵
|
||||
*/
|
||||
_updateMatrix(matrix) {
|
||||
const rootGroup = this.get('group');
|
||||
const minZoom = this.get('minZoom');
|
||||
const maxZoom = this.get('maxZoom');
|
||||
if (minZoom && matrix[0] < minZoom) {
|
||||
return;
|
||||
}
|
||||
if (maxZoom && matrix[0] > maxZoom) {
|
||||
return;
|
||||
}
|
||||
rootGroup.setMatrix(matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平移画布
|
||||
* @param {number} dx 水平方向位移
|
||||
* @param {number} dy 垂直方向位移
|
||||
*/
|
||||
translate(dx, dy) {
|
||||
this.get('group').translate(dx, dy);
|
||||
const group = this.get('group');
|
||||
group.translate(dx, dy);
|
||||
this.emit('viewportchange', { action: 'translate', matrix: group.getMatrix() });
|
||||
this.autoPaint();
|
||||
}
|
||||
|
||||
@ -550,7 +534,10 @@ class Graph extends EventEmitter {
|
||||
* @param {number} y 垂直坐标
|
||||
*/
|
||||
moveTo(x, y) {
|
||||
this.get('group').move(x, y);
|
||||
const group = this.get('group');
|
||||
group.move(x, y);
|
||||
this.emit('viewportchange', { action: 'move', matrix: group.getMatrix() });
|
||||
this.autoPaint();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -637,6 +624,8 @@ class Graph extends EventEmitter {
|
||||
*/
|
||||
zoom(ratio, center) {
|
||||
const matrix = Util.clone(this.get('group').getMatrix());
|
||||
const minZoom = this.get('minZoom');
|
||||
const maxZoom = this.get('maxZoom');
|
||||
if (center) {
|
||||
Util.mat3.translate(matrix, matrix, [ -center.x, -center.y ]);
|
||||
Util.mat3.scale(matrix, matrix, [ ratio, ratio ]);
|
||||
@ -644,7 +633,14 @@ class Graph extends EventEmitter {
|
||||
} else {
|
||||
Util.mat3.scale(matrix, matrix, [ ratio, ratio ]);
|
||||
}
|
||||
this._updateMatrix(matrix);
|
||||
if (minZoom && matrix[0] < minZoom) {
|
||||
return;
|
||||
}
|
||||
if (maxZoom && matrix[0] > maxZoom) {
|
||||
return;
|
||||
}
|
||||
this.get('group').setMatrix(matrix);
|
||||
this.emit('viewportchange', { action: 'zoom', matrix });
|
||||
this.autoPaint();
|
||||
}
|
||||
|
||||
|
168
test/unit/behavior/activate-relations-spec.js
Normal file
168
test/unit/behavior/activate-relations-spec.js
Normal file
@ -0,0 +1,168 @@
|
||||
const expect = require('chai').expect;
|
||||
const G6 = require('../../../src');
|
||||
|
||||
describe('activate-relations', () => {
|
||||
const div = document.createElement('div');
|
||||
div.id = 'activate-relations-spec';
|
||||
document.body.appendChild(div);
|
||||
const graph = new G6.Graph({
|
||||
container: div,
|
||||
width: 500,
|
||||
height: 500,
|
||||
pixelRatio: 2,
|
||||
modes: { default: [] }
|
||||
});
|
||||
const node1 = graph.addItem('node', { id: 'node1', x: 100, y: 100, label: 'node1' });
|
||||
const node2 = graph.addItem('node', { id: 'node2', x: 200, y: 200, label: 'node2' });
|
||||
graph.addItem('node', { id: 'node3', x: 80, y: 150, label: 'node3' });
|
||||
graph.addItem('edge', { source: 'node1', target: 'node2' });
|
||||
graph.addItem('edge', { source: 'node1', target: 'node3' });
|
||||
it('default activate', done => {
|
||||
graph.on('afteractivaterelations', e => {
|
||||
const action = e.action;
|
||||
if (e.item === node1) {
|
||||
if (action === 'activate') {
|
||||
const nodes = graph.findAllByState('node', 'active');
|
||||
const edges = graph.findAllByState('edge', 'active');
|
||||
expect(nodes.length).to.equal(3);
|
||||
expect(edges.length).to.equal(2);
|
||||
expect(graph.findAllByState('node', 'inactive').length).to.equal(0);
|
||||
expect(graph.findAllByState('edge', 'inactive').length).to.equal(0);
|
||||
const keyShape = node2.getKeyShape();
|
||||
expect(keyShape.attr('fillOpacity')).to.equal(0.8);
|
||||
} else {
|
||||
const nodes = graph.findAllByState('node', 'active');
|
||||
const edges = graph.findAllByState('edge', 'active');
|
||||
expect(nodes.length).to.equal(0);
|
||||
expect(edges.length).to.equal(0);
|
||||
expect(graph.findAllByState('node', 'inactive').length).to.equal(0);
|
||||
expect(graph.findAllByState('edge', 'inactive').length).to.equal(0);
|
||||
}
|
||||
} else {
|
||||
if (action === 'activate') {
|
||||
const nodes = graph.findAllByState('node', 'active');
|
||||
const edges = graph.findAllByState('edge', 'active');
|
||||
expect(nodes.length).to.equal(2);
|
||||
expect(edges.length).to.equal(1);
|
||||
expect(graph.findAllByState('node', 'inactive').length).to.equal(1);
|
||||
expect(graph.findAllByState('edge', 'inactive').length).to.equal(1);
|
||||
const keyShape = node1.getKeyShape();
|
||||
expect(keyShape.attr('fillOpacity')).to.equal(0.8);
|
||||
} else {
|
||||
const nodes = graph.findAllByState('node', 'active');
|
||||
const edges = graph.findAllByState('edge', 'active');
|
||||
expect(nodes.length).to.equal(0);
|
||||
expect(edges.length).to.equal(0);
|
||||
expect(graph.findAllByState('node', 'inactive').length).to.equal(0);
|
||||
expect(graph.findAllByState('edge', 'inactive').length).to.equal(0);
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
graph.addBehaviors([ 'activate-relations' ], 'default');
|
||||
graph.emit('node:mouseenter', { item: node1 });
|
||||
graph.emit('node:mouseleave', { item: node1 });
|
||||
graph.emit('node:mouseenter', { item: node2 });
|
||||
graph.emit('node:mouseleave', { item: node2 });
|
||||
graph.removeBehaviors([ 'activate-relations' ], 'default');
|
||||
graph.removeEvent();
|
||||
});
|
||||
it('click to activate', done => {
|
||||
graph.on('afteractivaterelations', e => {
|
||||
const action = e.action;
|
||||
if (e.item === node1) {
|
||||
if (action === 'activate') {
|
||||
const nodes = graph.findAllByState('node', 'active');
|
||||
const edges = graph.findAllByState('edge', 'active');
|
||||
expect(nodes.length).to.equal(3);
|
||||
expect(edges.length).to.equal(2);
|
||||
expect(graph.findAllByState('node', 'inactive').length).to.equal(0);
|
||||
expect(graph.findAllByState('edge', 'inactive').length).to.equal(0);
|
||||
const keyShape = node2.getKeyShape();
|
||||
expect(keyShape.attr('fillOpacity')).to.equal(0.8);
|
||||
} else {
|
||||
const nodes = graph.findAllByState('node', 'active');
|
||||
const edges = graph.findAllByState('edge', 'active');
|
||||
expect(nodes.length).to.equal(0);
|
||||
expect(edges.length).to.equal(0);
|
||||
expect(graph.findAllByState('node', 'inactive').length).to.equal(0);
|
||||
expect(graph.findAllByState('edge', 'inactive').length).to.equal(0);
|
||||
}
|
||||
} else {
|
||||
if (action === 'activate') {
|
||||
const nodes = graph.findAllByState('node', 'active');
|
||||
const edges = graph.findAllByState('edge', 'active');
|
||||
expect(nodes.length).to.equal(2);
|
||||
expect(edges.length).to.equal(1);
|
||||
expect(graph.findAllByState('node', 'inactive').length).to.equal(1);
|
||||
expect(graph.findAllByState('edge', 'inactive').length).to.equal(1);
|
||||
const keyShape = node1.getKeyShape();
|
||||
expect(keyShape.attr('fillOpacity')).to.equal(0.8);
|
||||
} else {
|
||||
const nodes = graph.findAllByState('node', 'active');
|
||||
const edges = graph.findAllByState('edge', 'active');
|
||||
expect(nodes.length).to.equal(0);
|
||||
expect(edges.length).to.equal(0);
|
||||
expect(graph.findAllByState('node', 'inactive').length).to.equal(0);
|
||||
expect(graph.findAllByState('edge', 'inactive').length).to.equal(0);
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
graph.addBehaviors([{
|
||||
type: 'activate-relations',
|
||||
trigger: 'click'
|
||||
}], 'default');
|
||||
graph.emit('node:click', { item: node1 });
|
||||
graph.emit('canvas:click', {});
|
||||
graph.emit('node:click', { item: node2 });
|
||||
graph.emit('canvas:click', {});
|
||||
graph.removeBehaviors([ 'activate-relations' ], 'default');
|
||||
graph.removeEvent();
|
||||
});
|
||||
it('custom state', done => {
|
||||
graph.on('afteractivaterelations', e => {
|
||||
const action = e.action;
|
||||
if (e.item === node1) {
|
||||
if (action === 'activate') {
|
||||
const nodes = graph.findAllByState('node', 'highlight');
|
||||
const edges = graph.findAllByState('edge', 'highlight');
|
||||
expect(nodes.length).to.equal(3);
|
||||
expect(edges.length).to.equal(2);
|
||||
expect(graph.findAllByState('node', 'inactive').length).to.equal(0);
|
||||
expect(graph.findAllByState('edge', 'inactive').length).to.equal(0);
|
||||
} else {
|
||||
const nodes = graph.findAllByState('node', 'highlight');
|
||||
const edges = graph.findAllByState('edge', 'highlight');
|
||||
expect(nodes.length).to.equal(0);
|
||||
expect(edges.length).to.equal(0);
|
||||
}
|
||||
} else {
|
||||
if (action === 'activate') {
|
||||
const nodes = graph.findAllByState('node', 'highlight');
|
||||
const edges = graph.findAllByState('edge', 'highlight');
|
||||
expect(nodes.length).to.equal(2);
|
||||
expect(edges.length).to.equal(1);
|
||||
expect(graph.findAllByState('node', 'inactive').length).to.equal(0);
|
||||
expect(graph.findAllByState('edge', 'inactive').length).to.equal(0);
|
||||
} else {
|
||||
const nodes = graph.findAllByState('node', 'highlight');
|
||||
const edges = graph.findAllByState('edge', 'highlight');
|
||||
expect(nodes.length).to.equal(0);
|
||||
expect(edges.length).to.equal(0);
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
graph.addBehaviors([{
|
||||
type: 'activate-relations',
|
||||
activeState: 'highlight',
|
||||
inactiveState: null
|
||||
}], 'default');
|
||||
graph.emit('node:mouseenter', { item: node1 });
|
||||
graph.emit('node:mouseleave', { item: node1 });
|
||||
graph.emit('node:mouseenter', { item: node2 });
|
||||
graph.emit('node:mouseleave', { item: node2 });
|
||||
graph.destroy();
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user