Merge remote-tracking branch 'origin/dev2.1.0' into optimization2

This commit is contained in:
Yanyan-Wang 2018-08-20 17:19:36 +08:00
commit fe7d954bba
25 changed files with 27306 additions and 646 deletions

File diff suppressed because it is too large Load Diff

View File

@ -28,9 +28,10 @@
let maxSpanningForest = new MaxSpanningForestPlugin({
layoutCfg: {
prevOverlapping: true,
maxIteration: 300
}
});
let nodeSizeMapper = new Mapper('node', 'userview', 'size', [15, 50], {
let nodeSizeMapper = new Mapper('node', 'weight', 'size', [15, 50], {
legendCfg: {
containerId: 'legend',
height: 100,
@ -49,10 +50,10 @@
}
}
});
let edgeSizeMapper = new Mapper('edge', 'userview', 'size', [1, 8], {
let edgeSizeMapper = new Mapper('edge', 'weight', 'size', [1, 8], {
legendCfg: null
});
let nodeColorMapper = new Mapper('node', 'stayTime', 'color', ['#BAE7FF', '#1890FF', '#0050B3'], {
let nodeColorMapper = new Mapper('node', 'weight', 'color', ['#BAE7FF', '#1890FF', '#0050B3'], {
legendCfg: {
containerId: 'legend',
title: {
@ -101,7 +102,7 @@
// node.getGraphicGroup().toFront();
// });
// });
const minimap = document.getElementById('minimap');
// const minimap = document.getElementById('minimap');
// const legend = document.getElementById('legend');
// if (minimap !== undefined) minimap.style.display = 'none';
// if (legend !== undefined) legend.style.display = 'none';

View File

@ -1,6 +1,6 @@
{
"name": "@antv/g6",
"version": "2.1.0-beta.10",
"version": "2.1.0-beta.12",
"description": "graph visualization frame work",
"main": "build/g6.js",
"homepage": "https://github.com/antvis/g6",
@ -100,7 +100,7 @@
"screenshot": "node ./bin/screenshot.js",
"start": "npm run dev",
"test": "torch --compile --renderer --recursive ./test/unit",
"test-live": "torch --compile --interactive --watch --recursive ./test/unit/",
"test-live": "torch --compile --interactive --watch --recursive ./test/unit/util/",
"watch": "webpack --config webpack-dev.config.js",
"win-dev": "node ./bin/win-dev.js"
},

View File

@ -41,10 +41,6 @@ parameter for this plugin:
- html: the html of the li
- callBack: the onclick listener of the li, could be string or a function. If it is a string, it must be a existing function name in menu.js.
To navigate an item (a node or edge) by id or item, if this item is not in the view, the whole graph will translate a shortest distance to make the node in the view:
graph.activeItem(item); // item or id
graph.navigate(item); // item or id
To create the menu which follows the mouse click:
graph.createMenu(func, containerId);
params:

View File

@ -83,7 +83,7 @@ class Plugin {
if (this.fisheye) {
const fisheye = new G6.Plugins['tool.fisheye']({
radius: 200
radius: 100
});
graph.addPlugin(fisheye);
}
@ -184,9 +184,8 @@ class Plugin {
const graph = this.graph;
item = graph.getItem(item);
if (item.isNode) {
graph.simpleUpdate(item, {
style: this.activedNodeStyle
});
item.getKeyShape().attr(this.activedNodeStyle);
graph.draw();
} else if (item.isEdge) {
graph.simpleUpdate(item, {
style: this.activedEdgeStyle
@ -197,9 +196,8 @@ class Plugin {
const graph = this.graph;
item = graph.getItem(item);
if (item.isNode) {
graph.simpleUpdate(item, {
style: this.nodeStyle
});
item.getKeyShape().attr(this.nodeStyle);
graph.draw();
} else if (item.isEdge) {
graph.simpleUpdate(item, {
style: this.edgeStyle

View File

@ -56,79 +56,32 @@ class Menu {
return this.node;
}
showSource(node) {
const graph = this.graph;
const {
reNodes,
reEdges
} = Util.extract(graph, 'in', 1, [ node ]);
graph.highlightSubgraph({
reNodes,
reEdges
});
// show the hided edge, which is not tree edge and it is in the es
// and the source and targert of the edge are both visible
const edges = graph.getEdges();
Util.each(edges, edge => {
if (!edge.isVisible() && !edge.getModel().isTreeEdge &&
edge.getSource().isVisible() && edge.getTarget().isVisible()) {
Util.each(reEdges, e => {
if (edge.id === e.id) {
edge.show();
}
});
}
});
this.hide();
this._showEdge('in', 1, [ node ]);
}
showTargets(node) {
const graph = this.graph;
const {
reNodes,
reEdges
} = Util.extract(graph, 'out', 1, [ node ]);
graph.highlightSubgraph({
reNodes,
reEdges
});
// show the hided edge, which is not tree edge and it is in the es
// and the source and targert of the edge are both visible
const edges = graph.getEdges();
Util.each(edges, edge => {
if (!edge.isVisible() && !edge.getModel().isTreeEdge &&
edge.getSource().isVisible() && edge.getTarget().isVisible()) {
Util.each(reEdges, e => {
if (edge.id === e.id) {
edge.show();
}
});
}
});
this.hide();
this._showEdge('out', 1, [ node ]);
}
showAll(node) {
this._showEdge('bi', 1, [ node ]);
}
_showEdge(type, step, focusNodes) {
const graph = this.graph;
const {
reNodes,
reEdges
} = Util.extract(graph, 'bi', 1, [ node ]);
} = Util.extract(graph, type, step, focusNodes);
graph.highlightSubgraph({
reNodes,
reEdges
});
// show the hided edge, which is not tree edge and it is in the es
// and the source and targert of the edge are both visible
const edges = graph.getEdges();
Util.each(edges, edge => {
if (!edge.isVisible() && !edge.getModel().isTreeEdge &&
edge.getSource().isVisible() && edge.getTarget().isVisible()) {
Util.each(reEdges, e => {
if (edge.id === e.id) {
edge.show();
}
});
reEdges.forEach(edgeObj => {
const edge = graph.find(edgeObj.id);
if (!edge.isVisible() && !edge.getModel().isTreeEdge) {
edge.show();
graph.simpleUpdate(edge);
}
});
this.hide();

View File

@ -40,13 +40,12 @@ class Plugin {
// sort the group items
const ns = hlItems.reNodes;
const es = hlItems.reEdges;
const group = this.getItemGroup();
const items = this.getItems();
Util.each(items, i => {
if (i.type === 'edge') {
Util.each(es, e => {
if (i.id !== e.id) {
this.toFront(i, group);
this.toFront(i);
}
});
}
@ -55,7 +54,7 @@ class Plugin {
if (i.type === 'node') {
Util.each(ns, n => {
if (i.id !== n.id) {
this.toFront(i, group);
this.toFront(i);
}
});
}
@ -64,7 +63,7 @@ class Plugin {
Util.each(items, i => {
if (i.type === 'guide') {
mask = i;
this.toFront(i, group);
this.toFront(i);
return;
}
});
@ -72,14 +71,14 @@ class Plugin {
mask = this.add('guide', {
shape: 'mask'
});
this.toFront(mask, group);
this.toFront(mask);
}
mask.show();
Util.each(items, i => {
if (i.type === 'edge') {
Util.each(es, e => {
if (i.id === e.id) {
this.toFront(i, group);
this.toFront(i);
}
});
}
@ -88,7 +87,7 @@ class Plugin {
if (i.type === 'node') {
Util.each(ns, n => {
if (i.id === n.id) {
this.toFront(i, group);
this.toFront(i);
}
});
}

View File

@ -209,9 +209,11 @@ class Minimap {
}
if (!width) {
width = Util.getWidth(container);
this.width = width;
}
if (!height) {
height = Util.getHeight(container);
this.height = height;
}
const minimapContainerCSS = this.minimapContainerCSS;
minimapContainerCSS.width = width + 'px';
@ -240,6 +242,8 @@ class Minimap {
const width = this.width;
const height = this.height;
const toSmallNodes = [];
const minSize = 2;
Util.graph2Canvas({
graph,
width,
@ -252,10 +256,9 @@ class Minimap {
const bbox = node.getBBox();
const model = node.getModel();
const width = bbox.width;
if (width * minimapScale < 2) {
if (width * minimapScale < minSize) {
const group = node.getGraphicGroup();
const originMatrix = Util.clone(group.getMatrix());
const minSize = 4;
group.transform([
[ 't', -model.x, -model.y ],
[ 's', minSize / (width * minimapScale), minSize / (width * minimapScale) ],

View File

@ -1,7 +1,5 @@
/**
* @fileOverview G6 Mapper Plugin base on d3 tech stack
* d3-scale https://github.com/d3/d3-scale
* d3-legend https://github.com/susielu/d3-legend
* @fileOverview extractSubgraph
* @author shiwu.wyy@antfin.com
*/

View File

@ -16,6 +16,25 @@ class Edge extends Item {
Util.mix(defaultCfg, cfg);
super(defaultCfg);
}
_init() {
this._cacheEdges();
super._init();
}
// cache edge into node
_cacheEdges() {
const itemMap = this.itemMap;
const model = this.model;
const source = itemMap[model.source];
const target = itemMap[model.target];
if (source && source.isItem) {
source.edges.push(this);
source.edges = Util.uniq(source.edges);
}
if (target && target.isItem) {
target.edges.push(this);
target.edges = Util.uniq(target.edges);
}
}
_beforeDraw() {
const model = this.model;
const itemMap = this.itemMap;
@ -59,7 +78,7 @@ class Edge extends Item {
ratio = ratio();
const group = this.group;
const keyShape = this.keyShape;
const keyShapePath = Util.parsePathString(Util.cloneDeep(keyShape.attr('path')));
const keyShapePath = Util.parsePathString(keyShape.attr('path'));
const lastSegment = keyShapePath[keyShapePath.length - 1];
const startSegment = keyShapePath[0];
const point = keyShape.getPoint(ratio);
@ -100,7 +119,7 @@ class Edge extends Item {
startSegment[startSegment.length - 2] = vDindent[0] + point.x;
}
keyShape.attr('path', keyShapePath);
keyShape[type + 'Arrow'] = marker;
this[type + 'Arrow'] = marker;
}
_getControlPoints() {
const controlPoints = this.model.controlPoints;
@ -113,7 +132,7 @@ class Edge extends Item {
return super._shouldDraw() && this.linkedItemVisible();
}
_getPoint(point) {
if (point.linkable) {
if (point.isItem) {
const box = point.getBBox();
return {
x: box.centerX,
@ -160,18 +179,27 @@ class Edge extends Item {
const points = [ sourcePoint ].concat(controlPoints).concat([ targetPoint ]);
const psl = points.length;
if (source.linkable) {
if (source.isItem) {
const point = (Util.isNumber(this.model.sourceAnchor) && source.id === model.source) ? this.model.sourceAnchor : points[1];
const interPoint = source.getLinkPoints(point);
points[0] = interPoint[0];
}
if (target.linkable) {
if (target.isItem) {
const point = (Util.isNumber(this.model.targetAnchor) && target.id === model.target) ? this.model.targetAnchor : points[psl - 2];
const interPoint = target.getLinkPoints(point);
points[psl - 1] = interPoint[0];
}
return points;
}
destroy() {
const itemMap = this.itemMap;
const model = this.model;
const source = itemMap[model.source];
const target = itemMap[model.target];
source && source.isItem && Util.Array.remove(source.edges, this);
target && target.isItem && Util.Array.remove(target.edges, this);
super.destroy();
}
}
module.exports = Edge;

View File

@ -57,7 +57,13 @@ class Item {
* cache model for diff
* @type {object}
*/
modelCache: {}
modelCache: {},
/**
* is item
* @type {boolean}
*/
isItem: true
};
Util.mix(this, defaultCfg, cfg);
this._init();
@ -250,10 +256,10 @@ class Item {
return (this.bbox || this._calculateBBox());
}
layoutUpdate() {
this.draw();
this.isVisible() && this.draw();
}
update() {
this.draw();
this.isVisible() && this.draw();
}
getModel() {
return this.model;

View File

@ -10,9 +10,9 @@ class Node extends Item {
constructor(cfg) {
const defaultCfg = {
type: 'node',
linkable: true,
isNode: true,
zIndex: 3
zIndex: 3,
edges: []
};
Util.mix(defaultCfg, cfg);
super(defaultCfg);
@ -39,32 +39,16 @@ class Node extends Item {
this._beforeDraw();
this._afterDraw();
}
getEdges(callback) {
const id = this.id;
const itemMap = this.itemMap;
const edges = itemMap._edges;
const rst = [];
Util.each(edges, edge => {
if (callback) {
if (callback(edge)) {
rst.push(edge);
}
return;
}
const edgeModel = edge.getModel();
if (id === edgeModel.target || id === edgeModel.source) {
rst.push(edge);
}
});
return rst;
getEdges() {
return this.edges;
}
getInEdges() {
return this.getEdges(edge => {
return this.edges.filter(edge => {
return edge.target === this;
});
}
getOutEdges() {
return this.getEdges(edge => {
return this.edges.filter(edge => {
return edge.source === this;
});
}

View File

@ -288,36 +288,6 @@ Mixin.AUGMENT = {
}
return this;
},
navigate(item) {
if (Util.isString(item)) {
item = this.find(item);
}
let dx = 0;
let dy = 0;
const rootGroup = this.get('_rootGroup');
const matrix = rootGroup.getMatrix();
if (item) {
const point = item.getCenter();
const padding = 16;
const width = this.get('width') - padding;
const height = this.get('height') - padding;
const bbox = item.getBBox();
const node_hwidth = (bbox.maxX - bbox.minX) / 2;
const node_hheight = (bbox.maxX - bbox.minX) / 2;
if (matrix[0] * point.x + matrix[6] < 0) {
dx = -matrix[6] + matrix[0] * node_hwidth - matrix[0] * point.x;
} else if (matrix[0] * point.x + matrix[6] > width) {
dx = -matrix[6] + width - matrix[0] * node_hwidth - matrix[0] * point.x;
}
if (matrix[0] * point.y + matrix[7] < 0) {
dy = -matrix[7] + matrix[0] * node_hheight - matrix[0] * point.y;
} else if (matrix[0] * point.y + matrix[7] > height) {
dy = -matrix[7] + height - matrix[0] * node_hheight - matrix[0] * point.y;
}
}
this.translate(dx, dy);
return this;
},
/**
* @param {object} point graph point
* @return {Graph} this

View File

@ -15,20 +15,20 @@ BaseUtil.mix(DomUtil, G.DomUtil, {
* @return {object} - event object that has remove function
*/
addEventListener(target, eventType, callback) {
if (target.addEventListener) {
target.addEventListener(eventType, callback, false);
return {
remove() {
target.removeEventListener(eventType, callback, false);
}
};
} else if (target.attachEvent) {
if (target.attachEvent) {
target.attachEvent('on' + eventType, callback);
return {
remove() {
target.detachEvent('on' + eventType, callback);
}
};
} else if (target.addEventListener) {
target.addEventListener(eventType, callback, false);
return {
remove() {
target.removeEventListener(eventType, callback, false);
}
};
}
},
/**
@ -72,9 +72,6 @@ BaseUtil.mix(DomUtil, G.DomUtil, {
dom.off = function(eventType, callback) {
dom.removeEventListener(eventType, callback);
};
dom.attr = function(attrName) {
return dom.getAttribute(attrName);
};
dom.css(css);
return dom;
}

View File

@ -1 +1 @@
module.exports = '2.1.0-beta.10';
module.exports = '2.1.0-beta.12';

View File

@ -40,9 +40,9 @@ describe('graph test', () => {
});
expect(i).equal(29);
});
// it('save', () => {
// expect(JSON.stringify(graph.save())).equal('{"nodes":[{"id":"node4","x":400,"y":160,"parent":"group2","index":0},{"id":"node6","x":150,"y":150,"index":2},{"id":"node8","x":90,"y":250,"parent":"group2","index":4}],"groups":[{"id":"group2","index":3}],"guides":[{"id":"guide-node2->node5","shape":"link","source":"node2","target":"node5","index":1}]}');
// });
it('save', () => {
graph.save();
});
it('getItems', () => {
const items = graph.getItems();
expect(items.length).equal(10);
@ -324,7 +324,7 @@ describe('graph test', () => {
matrix = graph.getMatrix();
expectToDeepAlmost(matrix, [ 2.3, 0, 0, 0, 2.3, 0, -119.4, -83.4, 1 ], 1);
});
it('hide', () => {
it('hide && show', () => {
graph.add('edge', {
id: 'node1-domCenter',
source: 'node1',
@ -340,14 +340,25 @@ describe('graph test', () => {
});
graph.zoom(1);
graph.setFitView('cc');
graph.hide(graph.find('node1-domCenter'));
expect(graph.find('node1-domCenter').getGraphicGroup().get('visible')).equal(false);
graph.show(graph.find('node1-domCenter'));
expect(graph.find('node1-domCenter').getGraphicGroup().get('visible')).equal(true);
graph.hide(graph.find('node1'));
expect(graph.find('node1').getGraphicGroup().get('visible')).equal(false);
expect(graph.find('node1-{50,50}').getGraphicGroup().get('visible')).equal(false);
graph.show(graph.find('node1'));
expect(graph.find('node1').getGraphicGroup().get('visible')).equal(true);
expect(graph.find('node1-{50,50}').getGraphicGroup().get('visible')).equal(true);
graph.hide('group1');
expect(graph.find('group1').getGraphicGroup().get('visible')).equal(false);
expect(graph.find('domCenter').getGraphicGroup().get('visible')).equal(false);
graph.show('group1');
expect(graph.find('group1').getGraphicGroup().get('visible')).equal(true);
expect(graph.find('domCenter').getGraphicGroup().get('visible')).equal(true);
});
it('endArrow', () => {
graph.update('node1-domCenter', {
@ -355,6 +366,9 @@ describe('graph test', () => {
startArrow: true
});
});
it('focus', () => {
graph.focus('node1');
});
it('getLayout', () => {
graph.getLayout();
});

View File

@ -1,22 +1,35 @@
// const Graph = require('../../../src/graph');
// const Util = require('../../../src/util/');
// const div = document.createElement('div');
// const data = require('../../fixtures/sample-graph-data.json');
// div.id = 'cchart';
// document.body.appendChild(div);
// data.nodes.forEach(node => {
// node.label = node.id;
// });
// const graph = new Graph({
// container: div,
// width: 500,
// height: 500,
// });
// graph.source(Util.cloneDeep(data));
// graph.render();
const Graph = require('../../../src/graph');
const Util = require('../../../src/util/');
const expect = require('chai').expect;
const div = document.createElement('div');
let data = require('../../fixtures/sample-graph-data.json');
data = Util.cloneDeep(data);
div.id = 'cchart';
document.body.appendChild(div);
data.nodes.forEach(node => {
node.label = node.id;
});
const graph = new Graph({
container: div,
width: 500,
height: 500
});
data.edges.push({
id: 'node1->node4',
target: 'node1',
source: 'node4'
});
graph.source(data);
graph.render();
// describe('group item test', () => {
// it('destroy', () => {
// graph.destroy();
// });
// });
describe('group item test', () => {
it('getCrossEdges', () => {
expect(graph.find('group1').getCrossEdges().length).eql(1);
});
it('getInnerEdges', () => {
expect(graph.find('group1').getInnerEdges().length).eql(2);
});
it('destroy', () => {
graph.destroy();
});
});

View File

@ -0,0 +1,7 @@
const Dendrogram = require('../../../../src/layouts/tree/dendrogram');
describe('layout tree dendrogram test', () => {
it('init', () => {
new Dendrogram();
});
});

View File

@ -0,0 +1,7 @@
const Indented = require('../../../../src/layouts/tree/indented');
describe('layout tree indented test', () => {
it('init', () => {
new Indented();
});
});

View File

@ -0,0 +1,7 @@
const Mindmap = require('../../../../src/layouts/tree/mindmap');
describe('layout tree mindmap test', () => {
it('init', () => {
new Mindmap();
});
});

View File

@ -248,31 +248,32 @@ describe('graph destroyed cacheLocation test', () => {
});
describe('graph destroyed mousemove test', () => {
const fisheye = new Fisheye();
const div = document.createElement('div');
div.id = 'fisheyeMountNode2';
document.body.appendChild(div);
const graph = new G6.Graph({
container: 'fisheyeMountNode2',
width: 500,
height: 500
});
// describe('graph destroyed mousemove test', () => {
// const fisheye = new Fisheye();
// const div = document.createElement('div');
// div.id = 'fisheyeMountNode2';
// document.body.appendChild(div);
// const graph = new G6.Graph({
// container: 'fisheyeMountNode2',
// width: 500,
// height: 500,
// plugins: [ fisheye ]
// });
const mouseEventWrapper = graph.getMouseEventWrapper();
graph.destroy();
// const mouseEventWrapper = graph.getMouseEventWrapper();
// graph.destroy();
it('fisheye mouse move on node', () => {
Simulate.simulate(mouseEventWrapper, 'mousemove', {
clientX: 100 - 50,
clientY: 200
});
Simulate.simulate(mouseEventWrapper, 'mousemove', {
clientX: 100,
clientY: 200
});
});
});
// it('fisheye mouse move on node', () => {
// Simulate.simulate(mouseEventWrapper, 'mousemove', {
// clientX: 100 - 50,
// clientY: 200
// });
// Simulate.simulate(mouseEventWrapper, 'mousemove', {
// clientX: 100,
// clientY: 200
// });
// });
// });
describe('node position undefined test', () => {

View File

@ -0,0 +1,42 @@
const G6 = require('../../../src/index');
const FreezeSize = require('../../../plugins/tool.freezeSize/');
const expect = require('chai').expect;
describe('freezeSize test', () => {
const data = {
nodes: [{
id: 'node1',
x: 100,
y: 200
}, {
id: 'node2',
x: 300,
y: 200
}],
edges: [{
target: 'node2',
source: 'node1'
}]
};
const graph = new G6.Graph({
container: 'mountNode',
width: 500,
height: 500,
minZoom: 0,
plugins: [ new FreezeSize() ]
});
graph.read(data);
it('freeze size', () => {
const node1 = graph.find('node1');
node1.getKeyShape().set('freezePoint', {
x: 100,
y: 100
});
graph.update('node1', {
x: 101
});
graph.zoom(0.01);
expect(node1.getKeyShape().getMatrix()[0]).eql(100);
});
});

View File

@ -14,7 +14,9 @@ document.body.appendChild(Util.createDOM(`
describe('minimap test', () => {
const originInnerHTML = document.getElementById('minimap').innerHTML;
const minimap = new Minimap({
container: 'minimap'
container: 'minimap',
width: 100,
height: 100
});
const data = {
nodes: [{
@ -41,8 +43,6 @@ describe('minimap test', () => {
plugins: [ minimap ]
});
graph.read(data);
graph.remove('node1');
graph.remove('node2');
it('minimap render', () => {
expect(document.getElementById('minimap').innerHTML).not.eql(originInnerHTML);
});
@ -78,6 +78,11 @@ describe('minimap test', () => {
it('renderViewPort', () => {
minimap.renderViewPort();
});
it('over min node size', () => {
graph.update('node1', {
x: 10000
});
});
it('minimap destroy', () => {
graph.destroy();
expect(document.getElementById('minimap').innerHTML).eql(originInnerHTML);

View File

@ -0,0 +1,14 @@
const Shape = require('../../../src/shape/');
const expect = require('chai').expect;
describe('shape test', () => {
it('register shape manager', () => {
Shape.registerShapeManager('shape');
expect(Shape.registerShape).not.eql(undefined);
});
it('register shape', () => {
Shape.registerShape('a', {});
Shape.registerShape('b', {}, 'a');
Shape.registerShape('c', {}, [ 'a', 'b' ]);
});
});

View File

@ -0,0 +1,29 @@
const expect = require('chai').expect;
const Util = require('../../../src/util/');
describe('dom util test', () => {
it('createDOM', () => {
const dom = Util.createDOM('<div>ddd</div>');
document.body.appendChild(dom);
dom.hide();
expect(dom.style.visibility).eql('hidden');
dom.show();
expect(dom.style.visibility).eql('visible');
dom.css({
width: '701px',
height: '18px'
});
expect(dom.width()).eql(701);
expect(dom.height()).eql(18);
dom.on('click', () => {
});
if (dom.addEventListener) {
dom.attachEvent = dom.addEventListener;
}
dom.on('click', () => {
});
dom.off();
dom.destroy();
});
});