From 72b0b6313cb3cc7a8345b81dfc043fdc47d8dc66 Mon Sep 17 00:00:00 2001 From: Yanyan-Wang Date: Wed, 8 Aug 2018 10:08:34 +0800 Subject: [PATCH 1/4] test: several plugin tests --- .babelrc | 2 +- package.json | 2 +- plugins/template.maxSpanningForest/index.js | 2 +- plugins/tool.fisheye/index.js | 7 +- plugins/tool.fisheye/tool.js | 4 +- plugins/tool.highlightSubgraph/README.md | 2 +- plugins/tool.highlightSubgraph/index.js | 6 +- plugins/tool.textDisplay/index.js | 6 +- plugins/util.extractSubgraph/index.js | 16 - test/unit/plugins/tool.fisheye-spec.js | 328 ++++++++++++++++++ .../plugins/tool.highlightSubgraph-spec.js | 65 ++++ test/unit/plugins/tool.mapper-spec.js | 44 ++- test/unit/plugins/tool.textDisplay-spec.js | 61 ++++ .../unit/plugins/util.extractSubgraph-spec.js | 69 ++++ 14 files changed, 575 insertions(+), 39 deletions(-) create mode 100644 test/unit/plugins/tool.fisheye-spec.js create mode 100644 test/unit/plugins/tool.highlightSubgraph-spec.js create mode 100644 test/unit/plugins/tool.textDisplay-spec.js create mode 100644 test/unit/plugins/util.extractSubgraph-spec.js diff --git a/.babelrc b/.babelrc index 745599e9a..d3a883036 100644 --- a/.babelrc +++ b/.babelrc @@ -2,7 +2,7 @@ { "plugins": [ "transform-object-rest-spread", - "transform-remove-strict-mode", + "transform-remove-strict-mode" ], "presets": [ [ diff --git a/package.json b/package.json index 06dfe1c3d..3e94f73a5 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,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/plugins/tool.highlightSubgraph-spec.js", "watch": "webpack --config webpack-dev.config.js", "win-dev": "node ./bin/win-dev.js" }, diff --git a/plugins/template.maxSpanningForest/index.js b/plugins/template.maxSpanningForest/index.js index 4d9a728fd..902144cac 100644 --- a/plugins/template.maxSpanningForest/index.js +++ b/plugins/template.maxSpanningForest/index.js @@ -237,7 +237,7 @@ class Plugin { } else { this.menu.hide(); // restore the highlighted graph and hide the edges which are not tree edges. - graph.restoreGraph(); + graph.unhighlightGraph(); const edges = graph.getEdges(); Util.each(edges, edge => { if (edge.isVisible() && !edge.getModel().isTreeEdge) { diff --git a/plugins/tool.fisheye/index.js b/plugins/tool.fisheye/index.js index c1025cfc1..3bc2e728f 100644 --- a/plugins/tool.fisheye/index.js +++ b/plugins/tool.fisheye/index.js @@ -21,6 +21,7 @@ class Plugin { ...this.options }); graph.on('mousemove', Util.throttle(ev => { + if (graph.destroyed) return; const nodes = graph.getNodes(); const size = nodes.length; if (this.oriXs.length !== size) return; @@ -34,6 +35,7 @@ class Plugin { ); }); const cacheLocation = Util.debounce(ev => { + if (graph.destroyed) return; const nodes = graph.getNodes(); const size = nodes.length; if (ev === undefined || ev.item === undefined) { @@ -42,8 +44,9 @@ class Plugin { this.oriXs[i] = nodes[i].getModel().x; this.oriYs[i] = nodes[i].getModel().y; } - } else if (ev.item.type !== 'node' || (!ev.updateModel.x && !ev.updateModel.y)) return; - else { + } else if (ev.item.type !== 'node' || (ev.updateModel.x === undefined && ev.updateModel.y === undefined)) { + return; + } else { const item = graph.find(ev.originModel.id); for (let i = 0; i < size; i++) { if (nodes[i].getModel().id === item.id) { diff --git a/plugins/tool.fisheye/tool.js b/plugins/tool.fisheye/tool.js index c5889cf19..796f441e1 100644 --- a/plugins/tool.fisheye/tool.js +++ b/plugins/tool.fisheye/tool.js @@ -16,13 +16,13 @@ class Tool { /** * defualt zoom center - * @type {object} + * @type {array} */ center: [ 0, 0 ], /** * defualt magnification factor - * @type {object} + * @type {number} */ d: 1.0 }, options); diff --git a/plugins/tool.highlightSubgraph/README.md b/plugins/tool.highlightSubgraph/README.md index 29e774187..d5e0b7dd5 100644 --- a/plugins/tool.highlightSubgraph/README.md +++ b/plugins/tool.highlightSubgraph/README.md @@ -8,7 +8,7 @@ interface: params: - hlItems: the items which will be highlighted -- restoreGraph() +- unhighlightGraph() restore the graph to the un-lighlighted style. ## use diff --git a/plugins/tool.highlightSubgraph/index.js b/plugins/tool.highlightSubgraph/index.js index 1457eed39..ac008424e 100644 --- a/plugins/tool.highlightSubgraph/index.js +++ b/plugins/tool.highlightSubgraph/index.js @@ -32,11 +32,11 @@ class Plugin { init() { this.graph.on('afterinit', () => { this.graph.highlightSubgraph = this.highlightSubgraph; - this.graph.restoreGraph = this.restoreGraph; + this.graph.unhighlightGraph = this.unhighlightGraph; }); } highlightSubgraph(hlItems) { - this.restoreGraph(); + this.unhighlightGraph(); // sort the group items const ns = hlItems.reNodes; const es = hlItems.reEdges; @@ -95,7 +95,7 @@ class Plugin { }); this.draw(); } - restoreGraph() { + unhighlightGraph() { // hide the mask const items = this.getItems(); let mask; diff --git a/plugins/tool.textDisplay/index.js b/plugins/tool.textDisplay/index.js index 84a69cec5..9eaa9cd0f 100644 --- a/plugins/tool.textDisplay/index.js +++ b/plugins/tool.textDisplay/index.js @@ -30,7 +30,11 @@ class Plugin { const model = node.getModel(); const labelBox = label.getBBox(); const labelWidth = labelBox.maxX - labelBox.minX; - const nodeWidth = model.size * scale; + let nodeWidth = model.size * scale; + if (model.size === undefined) { + const nodeBox = node.getBBox(); + nodeWidth = nodeBox.maxX - nodeBox.minX; + } if (labelWidth === 0) return; const ratio = labelWidth / nodeWidth; if (ratio > 2) { diff --git a/plugins/util.extractSubgraph/index.js b/plugins/util.extractSubgraph/index.js index b1a8acf52..063b882b2 100644 --- a/plugins/util.extractSubgraph/index.js +++ b/plugins/util.extractSubgraph/index.js @@ -49,22 +49,6 @@ const extractSubgraph = { reNodes, reEdges }; - }, - setZIndex(ns, es, minZ) { - const graph = this.graph; - const nodes = graph.getNodes(); - const edges = graph.getEdges(); - Util.each(nodes, node => { - Util.each(ns, n => { - if (node.id === n.id) node.getGraphicGroup().setSilent('zIndex', minZ + 2); - }); - }); - Util.each(edges, edge => { - Util.each(es, e => { - if (edge.id === e.id) edge.getGraphicGroup().setSilent('zIndex', minZ + 1); - }); - }); - graph.getItemGroup().sort(); } }; Util.mix(Util, extractSubgraph); diff --git a/test/unit/plugins/tool.fisheye-spec.js b/test/unit/plugins/tool.fisheye-spec.js new file mode 100644 index 000000000..f201fc6a0 --- /dev/null +++ b/test/unit/plugins/tool.fisheye-spec.js @@ -0,0 +1,328 @@ +const G6 = require('../../../src/index'); +const expect = require('chai').expect; +const Simulate = require('event-simulate'); +const Fisheye = require('../../../plugins/tool.fisheye/'); + +describe('fisheye test', () => { + const fisheye = new Fisheye(); + const data = { + nodes: [{ + id: 'node1', + x: 100, + y: 200, + weight: 10 + }, { + id: 'node2', + x: 300, + y: 200, + weight: 100 + }, { + id: 'node3', + x: 0, + y: -200, + weight: 100 + }], + edges: [{ + target: 'node2', + source: 'node1' + }, { + target: 'node2', + source: 'node3' + }] + }; + const div = document.createElement('div'); + div.id = 'fisheyeMountNode'; + document.body.appendChild(div); + const graph = new G6.Graph({ + container: div, + width: 500, + height: 500, + plugins: [ fisheye ] + }); + const mouseEventWrapper = graph.getMouseEventWrapper(); + graph.read(data); + + + it('fisheye mouse move on node test', () => { + const node1Model = graph.find('node1').getModel(); + const clientPoint = graph.getClientPoint(node1Model); + Simulate.simulate(mouseEventWrapper, 'mousedown', { + clientX: clientPoint.x - 50, + clientY: clientPoint.y + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: clientPoint.x - 50, + clientY: clientPoint.y + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: clientPoint.x, + clientY: clientPoint.y + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: clientPoint.x - 100, + clientY: clientPoint.y + }); + expect([ node1Model.x, node1Model.y ]).eql([ 130, 200 ]); + + graph.update('node3', { + x: -50, + y: -100 + }); + const node3Model = graph.find('node3').getModel(); + const clientPoint3 = graph.getClientPoint(node3Model); + Simulate.simulate(mouseEventWrapper, 'mousedown', { + clientX: clientPoint3.x, + clientY: clientPoint3.y - 50 + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: clientPoint3.x, + clientY: clientPoint3.y - 50 + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: clientPoint3.x, + clientY: clientPoint3.y + }); + expect([ node1Model.x, node1Model.y ]).eql([ 130, 200 ]); + expect(div.childNodes.length).not.eql(0); + }); + + it('fisheye after updating node to (0, 0) test1', done => { + graph.update('node2', { + x: 0, + y: 0 + }); + setTimeout(() => { + const node2Model = graph.find('node2').getModel(); + const clientPoint = graph.getClientPoint(node2Model); + Simulate.simulate(mouseEventWrapper, 'mousedown', { + clientX: clientPoint.x - 50, + clientY: clientPoint.y + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: clientPoint.x - 50, + clientY: clientPoint.y + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: clientPoint.x, + clientY: clientPoint.y + }); + expect(div.childNodes.length).not.eql(0); + done(); + }, 100); + }); + + it('fisheye after updating node to (0, 0) test2', done => { + graph.update('node2', { + x: 0, + y: 0 + }); + setTimeout(() => { + Simulate.simulate(mouseEventWrapper, 'mousedown', { + clientX: 0 + 50, + clientY: 0 + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: 0 + 50, + clientY: 0 + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: 0, + clientY: 0 + }); + expect(div.childNodes.length).not.eql(0); + done(); + }, 100); + }); + + it('fisheye after updating node to (0, -100)', done => { + graph.update('node2', { + x: 0, + y: -100 + }); + setTimeout(() => { + Simulate.simulate(mouseEventWrapper, 'mousedown', { + clientX: 0 + 50, + clientY: 100 + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: 0 + 50, + clientY: 100 + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: 0, + clientY: 100 + }); + expect(div.childNodes.length).not.eql(0); + done(); + }, 100); + }); + + + it('fisheye after updating node to red', done => { + graph.update('node1', { + color: 'red' + }); + setTimeout(() => { + const node1Model = graph.find('node1').getModel(); + const clientPoint = graph.getClientPoint(node1Model); + Simulate.simulate(mouseEventWrapper, 'mousedown', { + clientX: clientPoint.x - 50, + clientY: clientPoint.y + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: clientPoint.x - 50, + clientY: clientPoint.y + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: clientPoint.x, + clientY: clientPoint.y + }); + expect([ node1Model.x, node1Model.y ]).eql([ 130, 200 ]); + expect(div.childNodes.length).not.eql(0); + done(); + }, 100); + }); + + it('graph destroy', () => { + graph.destroy(); + expect(div.childNodes.length).equal(0); + }); +}); + + +describe('graph destroyed cacheLocation test', () => { + const fisheye = new Fisheye(); + const data = { + nodes: [{ + id: 'node1', + x: 100, + y: 200, + weight: 10 + }, { + id: 'node2', + x: 300, + y: 200, + weight: 100 + }, { + id: 'node3', + x: 0, + y: -200, + weight: 100 + }], + edges: [{ + target: 'node2', + source: 'node1' + }, { + target: 'node2', + source: 'node3' + }] + }; + const div = document.createElement('div'); + div.id = 'fisheyeMountNode1'; + document.body.appendChild(div); + const graph = new G6.Graph({ + container: 'fisheyeMountNode1', + width: 500, + height: 500, + plugins: [ fisheye ] + }); + + const mouseEventWrapper = graph.getMouseEventWrapper(); + graph.read(data); + graph.destroy(); + + it('fisheye mouse move on node', () => { + Simulate.simulate(mouseEventWrapper, 'mousedown', { + clientX: 100 - 50, + clientY: 200 + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: 100 - 50, + clientY: 200 + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: 100, + clientY: 200 + }); + }); +}); + + +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 + }); + + 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 + }); + }); +}); + + +describe('node position undefined test', () => { + const fisheye = new Fisheye(); + const data = { + nodes: [{ + id: 'node1' + }, { + id: 'node2' + }, { + id: 'node3' + }], + edges: [{ + target: 'node2', + source: 'node1' + }, { + target: 'node2', + source: 'node3' + }] + }; + const div = document.createElement('div'); + div.id = 'fisheyeMountNode3'; + document.body.appendChild(div); + const graph = new G6.Graph({ + container: 'fisheyeMountNode3', + width: 500, + height: 500, + plugins: [ fisheye ] + }); + + const mouseEventWrapper = graph.getMouseEventWrapper(); + graph.read(data); + + it('fisheye mouse move on node', () => { + Simulate.simulate(mouseEventWrapper, 'mousedown', { + clientX: 100 - 50, + clientY: 200 + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: 100 - 50, + clientY: 200 + }); + Simulate.simulate(mouseEventWrapper, 'mousemove', { + clientX: 100, + clientY: 200 + }); + }); + + it('graph destroy', () => { + graph.destroy(); + expect(div.childNodes.length).equal(0); + }); +}); diff --git a/test/unit/plugins/tool.highlightSubgraph-spec.js b/test/unit/plugins/tool.highlightSubgraph-spec.js new file mode 100644 index 000000000..9538f73e3 --- /dev/null +++ b/test/unit/plugins/tool.highlightSubgraph-spec.js @@ -0,0 +1,65 @@ +const G6 = require('../../../src/index'); +const Highlighter = require('../../../plugins/tool.highlightSubgraph/'); +const expect = require('chai').expect; + +describe('highlight subgraph test', () => { + const highlighter = new Highlighter(); + const data = { + nodes: [{ + id: 'node1', + x: 100, + y: 200 + }, { + id: 'node2', + x: 300, + y: 200 + }, { + id: 'node3', + x: 400, + y: 200 + }], + edges: [{ + target: 'node2', + source: 'node1' + }, { + target: 'node3', + source: 'node2' + }] + }; + const div = document.createElement('div'); + document.body.appendChild(div); + const graph = new G6.Graph({ + container: div, + width: 500, + height: 500, + plugins: [ highlighter ] + }); + graph.read(data); + + it('highlight', () => { + const nodes = graph.getNodes(); + const edges = graph.getEdges(); + const reNodes = [ nodes[0], nodes[1] ]; + const reEdges = [ edges[0] ]; + graph.highlightSubgraph({ + reNodes, + reEdges + }); + }); + it('unhighlight', () => { + graph.unhighlightGraph(); + }); + it('highlight again', () => { + const nodes = graph.getNodes(); + const reNodes = [ nodes[0] ]; + const reEdges = [ ]; + graph.highlightSubgraph({ + reNodes, + reEdges + }); + }); + it('graph destroy', () => { + graph.destroy(); + expect(div.childNodes.length).equal(0); + }); +}); diff --git a/test/unit/plugins/tool.mapper-spec.js b/test/unit/plugins/tool.mapper-spec.js index 1589faa65..167bf65a7 100644 --- a/test/unit/plugins/tool.mapper-spec.js +++ b/test/unit/plugins/tool.mapper-spec.js @@ -45,8 +45,10 @@ describe('node size mapper test', () => { source: 'node1' }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ nodeSizeMapper ] @@ -98,8 +100,10 @@ describe('node color mapper domain length test', () => { source: 'node1' }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ nodeSizeMapper ] @@ -140,8 +144,10 @@ describe('node color mapper domian equals 1 test', () => { source: 'node1' }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ nodeSizeMapper ] @@ -193,8 +199,10 @@ describe('node color mapper domian equals 0 test', () => { source: 'node1' }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ nodeSizeMapper ] @@ -242,8 +250,10 @@ describe('node color mapper domian equals -1 test', () => { source: 'node1' }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ nodeSizeMapper ] @@ -293,8 +303,10 @@ describe('edge size mapper test', () => { weight: 2 }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ edgeSizeMapper ] @@ -341,8 +353,10 @@ describe('edge size mapper vertical test', () => { weight: 2 }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ edgeSizeMapper ] @@ -383,8 +397,10 @@ describe('node color category mapper test', () => { source: 'node1' }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ nodeColoreMapper ] @@ -430,8 +446,10 @@ describe('node size mapper with formatter test', () => { source: 'node1' }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ nodeSizeMapper ] @@ -472,8 +490,10 @@ describe('container undefined test', () => { source: 'node1' }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ nodeSizeMapper ] @@ -511,8 +531,10 @@ describe('slider test', () => { source: 'node1' }] }; + const div = document.createElement('div'); + document.body.appendChild(div); const graph = new G6.Graph({ - container: 'mountNode', + container: div, width: 500, height: 500, plugins: [ nodeSizeMapper ] diff --git a/test/unit/plugins/tool.textDisplay-spec.js b/test/unit/plugins/tool.textDisplay-spec.js new file mode 100644 index 000000000..fe815ab04 --- /dev/null +++ b/test/unit/plugins/tool.textDisplay-spec.js @@ -0,0 +1,61 @@ +const G6 = require('../../../src/index'); +const TextDisplay = require('../../../plugins/tool.textDisplay/'); +const expect = require('chai').expect; + +describe('node size mapper test', () => { + const textDisplay = new TextDisplay(); + const data = { + nodes: [{ + id: 'node1', + x: 100, + y: 200, + name: 'node1' + }, { + id: 'node2', + x: 300, + y: 200, + name: '' + }, { + id: 'node3', + x: 400, + y: 200, + name: 'node3node3node3node3node3node3node3node3node3node3node3node3node3node3' + }], + edges: [{ + target: 'node2', + source: 'node1' + }, { + target: 'node3', + source: 'node2' + }] + }; + const div = document.createElement('div'); + document.body.appendChild(div); + const graph = new G6.Graph({ + container: div, + width: 500, + height: 500, + plugins: [ textDisplay ] + }); + graph.node({ + label(model) { + return { + text: model.name, + stroke: '#fff', + lineWidth: 4 + }; + } + }); + graph.read(data); + + it('graph change view port', () => { + graph.emit('afterviewportchange', {}); + }); + it('graph zoom', () => { + graph.emit('afterzoom', {}); + }); + it('graph destroy', () => { + graph.destroy(); + expect(div.childNodes.length).equal(0); + }); +}); diff --git a/test/unit/plugins/util.extractSubgraph-spec.js b/test/unit/plugins/util.extractSubgraph-spec.js new file mode 100644 index 000000000..d2219153d --- /dev/null +++ b/test/unit/plugins/util.extractSubgraph-spec.js @@ -0,0 +1,69 @@ +const G6 = require('../../../src/index'); +const Extractor = require('../../../plugins/util.extractSubgraph/'); +const expect = require('chai').expect; +const Util = G6.Util; + +describe('extract subgraph test', () => { + const data = { + nodes: [{ + id: 'node1', + x: 100, + y: 200 + }, { + id: 'node2', + x: 300, + y: 200 + }, { + id: 'node3', + x: 400, + y: 200 + }], + edges: [{ + target: 'node2', + source: 'node1' + }, { + target: 'node3', + source: 'node2' + }] + }; + const div = document.createElement('div'); + document.body.appendChild(div); + const graph = new G6.Graph({ + container: div, + width: 500, + height: 500 + }); + graph.read(data); + + it('double direction subgraph about node2', () => { + const node = graph.find('node2'); + const { + reNodes, + reEdges + } = Util.extract(graph, 'bi', 1, [ node ]); + expect(reNodes.length).eql(3); + expect(reEdges.length).eql(2); + }); + it('in direction subgraph about node2', () => { + const node = graph.find('node2'); + const { + reNodes, + reEdges + } = Util.extract(graph, 'in', 1, [ node ]); + expect(reNodes.length).eql(2); + expect(reEdges.length).eql(1); + }); + it('out direction subgraph about node2', () => { + const node = graph.find('node2'); + const { + reNodes, + reEdges + } = Util.extract(graph, 'out', 1, [ node ]); + expect(reNodes.length).eql(2); + expect(reEdges.length).eql(1); + }); + it('graph destroy', () => { + graph.destroy(); + expect(div.childNodes.length).equal(0); + }); +}); From a17e6157e8259dfba1b7bd6291276eb9ccc69fc1 Mon Sep 17 00:00:00 2001 From: Yanyan-Wang Date: Wed, 8 Aug 2018 11:00:41 +0800 Subject: [PATCH 2/4] fix:loading image --- plugins/layout.forceAtlas2/layout.js | 15 +++++++++------ plugins/tool.mapper/index.js | 4 ++-- test/unit/plugins/tool.mapper-spec.js | 13 ++++++++----- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/plugins/layout.forceAtlas2/layout.js b/plugins/layout.forceAtlas2/layout.js index b997886f8..f57618c9c 100644 --- a/plugins/layout.forceAtlas2/layout.js +++ b/plugins/layout.forceAtlas2/layout.js @@ -159,21 +159,24 @@ class Layout { loading.style.setProperty('background-color', '#fff'); loading.style.setProperty('position', 'absolute'); const parent = graph.getGraphContainer().parentNode; - loading.style.setProperty('width', parent.offsetWidth + 'px'); - loading.style.setProperty('height', parent.offsetHeight + 'px'); + const divHeight = parent.offsetHeight ? parent.offsetHeight : 500; + const divWidth = parent.offsetWidth ? parent.offsetWidth : 500; + loading.style.setProperty('width', divWidth + 'px'); + loading.style.setProperty('height', divHeight + 'px'); loading.style.setProperty('margin-top', (-parent.offsetHeight) + 'px'); loading.style.zIndex = 999; parent.appendChild(loading); // the loading image + const imgSize = 200; const loadingImg = document.createElement('img'); loadingImg.src = 'https://gw.alipayobjects.com/zos/rmsportal/mnEmjOmrHbghTsZNeTmI.gif'; - loadingImg.style.setProperty('width', 200 + 'px'); - loadingImg.style.setProperty('height', 200 + 'px'); - const Cw = loadingImg.offsetWidth; + loadingImg.style.setProperty('width', imgSize + 'px'); + loadingImg.style.setProperty('height', imgSize + 'px'); + const Cw = imgSize; const Pw = loading.offsetWidth; const left = (Pw - Cw) / 2; loadingImg.style.setProperty('margin-left', left + 'px'); - const Ch = loadingImg.offsetHeight; + const Ch = imgSize; const Ph = loading.offsetHeight; const top = (Ph - Ch) / 2; loadingImg.style.setProperty('margin-top', top + 'px'); diff --git a/plugins/tool.mapper/index.js b/plugins/tool.mapper/index.js index f99eb6489..5790ec673 100644 --- a/plugins/tool.mapper/index.js +++ b/plugins/tool.mapper/index.js @@ -179,14 +179,14 @@ class Plugin { if (legendContainer === undefined) { if (containerId === undefined) { legendContainer = Util.createDOM('
'); + const container = graph.getGraphContainer(); + container.appendChild(legendContainer); } else { legendContainer = document.getElementById(containerId); if (legendContainer === undefined || legendContainer === null) { throw new Error('please set the container for the graph !'); } } - const container = graph.getGraphContainer(); - container.appendChild(legendContainer); } const canvas = new G.Canvas({ diff --git a/test/unit/plugins/tool.mapper-spec.js b/test/unit/plugins/tool.mapper-spec.js index 167bf65a7..e5e97ac8e 100644 --- a/test/unit/plugins/tool.mapper-spec.js +++ b/test/unit/plugins/tool.mapper-spec.js @@ -67,7 +67,7 @@ describe('node size mapper test', () => { }); it('legend destroy', () => { graph.destroy(); - expect(document.getElementById('nodeSizeLegend')).eql(null); + expect(document.getElementById('nodeSizeLegend').innerHTML).eql(originInnerHTML); }); }); @@ -164,7 +164,7 @@ describe('node color mapper domian equals 1 test', () => { }); it('legend destroy', () => { graph.destroy(); - expect(document.getElementById('nodeColorLegend1')).eql(null); + expect(document.getElementById('nodeColorLegend1').innerHTML).eql(originInnerHTML); }); }); @@ -219,7 +219,7 @@ describe('node color mapper domian equals 0 test', () => { }); it('legend destroy', () => { graph.destroy(); - expect(document.getElementById('nodeColorLegend2')).eql(null); + expect(document.getElementById('nodeColorLegend2').innerHTML).eql(originInnerHTML); }); }); @@ -270,7 +270,7 @@ describe('node color mapper domian equals -1 test', () => { }); it('legend destroy', () => { graph.destroy(); - expect(document.getElementById('nodeColorLegend3')).eql(null); + expect(document.getElementById('nodeColorLegend3').innerHTML).eql(originInnerHTML); }); }); @@ -321,6 +321,9 @@ describe('edge size mapper test', () => { expect(size1).eql(10); expect(size2).eql(50); }); + it('legend destroy', () => { + graph.destroy(); + }); }); describe('edge size mapper vertical test', () => { @@ -417,7 +420,7 @@ describe('node color category mapper test', () => { }); it('legend destroy', () => { graph.destroy(); - expect(document.getElementById('nodeColorCatLegend')).eql(null); + expect(document.getElementById('nodeColorCatLegend').innerHTML).eql(originInnerHTML); }); }); From 34fc2abc4f32c3512c4b7fc4d77ca9f3093a3ef7 Mon Sep 17 00:00:00 2001 From: Yanyan-Wang Date: Wed, 8 Aug 2018 20:06:28 +0800 Subject: [PATCH 3/4] text: more expect. fix: legend label undefined. --- package.json | 2 +- plugins/layout.forceAtlas2/layout.js | 2 +- plugins/tool.mapper/README.md | 2 +- plugins/tool.mapper/index.js | 5 ++-- plugins/tool.textDisplay/index.js | 4 +-- .../plugins/tool.highlightSubgraph-spec.js | 27 +++++++++++++++++++ test/unit/plugins/tool.textDisplay-spec.js | 16 ++++++++++- 7 files changed, 50 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 8ed1b0e3d..e83824ff7 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,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/plugins/tool.highlightSubgraph-spec.js", + "test-live": "torch --compile --interactive --watch --recursive ./test/unit/plugins/tool.textDisplay-spec.js", "watch": "webpack --config webpack-dev.config.js", "win-dev": "node ./bin/win-dev.js" }, diff --git a/plugins/layout.forceAtlas2/layout.js b/plugins/layout.forceAtlas2/layout.js index f57618c9c..9f2365243 100644 --- a/plugins/layout.forceAtlas2/layout.js +++ b/plugins/layout.forceAtlas2/layout.js @@ -182,7 +182,7 @@ class Layout { loadingImg.style.setProperty('margin-top', top + 'px'); loading.appendChild(loadingImg); - const worker = new Worker();// { type: 'module' } + const worker = new Worker(); worker.postMessage(obj); worker.onmessage = function(event) { this.nodes = event.data; diff --git a/plugins/tool.mapper/README.md b/plugins/tool.mapper/README.md index d276b5b9f..482d937bb 100644 --- a/plugins/tool.mapper/README.md +++ b/plugins/tool.mapper/README.md @@ -21,7 +21,7 @@ Constructor parameters: simple use. ```js -const Mapper = G6.Plugins['tool.mapper'] +const Mapper = G6.Plugins['tool.mapper']; const nodeColorMapper = new Mapper('node', 'class', 'color', ['#BAE7FF', '#0050B3'], { legendCfg: { scale: 0.5 diff --git a/plugins/tool.mapper/index.js b/plugins/tool.mapper/index.js index 5790ec673..39945880d 100644 --- a/plugins/tool.mapper/index.js +++ b/plugins/tool.mapper/index.js @@ -311,10 +311,11 @@ class Plugin { } } + const domainStep = (domain[domain.length - 1] - domain[0]) / (range.length - 1); const items = []; Util.each(range, (val, i) => { - const percent = (domain[i] - scale.min) / (scale.max - scale.min); - let itemText = domain[i]; + let itemText = domain[0] + domainStep * i; + const percent = (itemText - domain[0]) / (domain[domain.length - 1] - domain[0]); if (legendCfg.formatter !== undefined && legendCfg.formatter !== null) { itemText = legendCfg.formatter(domain[i]); } diff --git a/plugins/tool.textDisplay/index.js b/plugins/tool.textDisplay/index.js index 9eaa9cd0f..d9b913eb9 100644 --- a/plugins/tool.textDisplay/index.js +++ b/plugins/tool.textDisplay/index.js @@ -24,13 +24,13 @@ class Plugin { textDisplay() { const graph = this.graph; const nodes = graph.getNodes(); - const scale = graph.getMatrix()[0]; Util.each(nodes, node => { const label = node.getLabel(); const model = node.getModel(); const labelBox = label.getBBox(); const labelWidth = labelBox.maxX - labelBox.minX; - let nodeWidth = model.size * scale; + const nodeBox = node.getBBox(); + let nodeWidth = nodeBox.maxX - nodeBox.minX; if (model.size === undefined) { const nodeBox = node.getBBox(); nodeWidth = nodeBox.maxX - nodeBox.minX; diff --git a/test/unit/plugins/tool.highlightSubgraph-spec.js b/test/unit/plugins/tool.highlightSubgraph-spec.js index 9538f73e3..8b2b39861 100644 --- a/test/unit/plugins/tool.highlightSubgraph-spec.js +++ b/test/unit/plugins/tool.highlightSubgraph-spec.js @@ -45,9 +45,27 @@ describe('highlight subgraph test', () => { reNodes, reEdges }); + const items = graph.getItems(); + let mask; + G6.Util.each(items, i => { + if (i.type === 'guide') { + mask = i; + return; + } + }); + expect(mask.isVisible()).eql(true); }); it('unhighlight', () => { graph.unhighlightGraph(); + const items = graph.getItems(); + let mask; + G6.Util.each(items, i => { + if (i.type === 'guide') { + mask = i; + return; + } + }); + expect(mask.isVisible()).eql(false); }); it('highlight again', () => { const nodes = graph.getNodes(); @@ -57,6 +75,15 @@ describe('highlight subgraph test', () => { reNodes, reEdges }); + const items = graph.getItems(); + let mask; + G6.Util.each(items, i => { + if (i.type === 'guide') { + mask = i; + return; + } + }); + expect(mask.isVisible()).eql(true); }); it('graph destroy', () => { graph.destroy(); diff --git a/test/unit/plugins/tool.textDisplay-spec.js b/test/unit/plugins/tool.textDisplay-spec.js index fe815ab04..e429693ce 100644 --- a/test/unit/plugins/tool.textDisplay-spec.js +++ b/test/unit/plugins/tool.textDisplay-spec.js @@ -2,7 +2,7 @@ const G6 = require('../../../src/index'); const TextDisplay = require('../../../plugins/tool.textDisplay/'); const expect = require('chai').expect; -describe('node size mapper test', () => { +describe('text display test', () => { const textDisplay = new TextDisplay(); const data = { nodes: [{ @@ -50,9 +50,23 @@ describe('node size mapper test', () => { it('graph change view port', () => { graph.emit('afterviewportchange', {}); + + const node1 = graph.find('node1'); + const node1label = node1.getLabel(); + const node3 = graph.find('node3'); + const node3label = node3.getLabel(); + expect(node1label.get('visible')).eql(true); + expect(node3label.get('visible')).eql(false); }); it('graph zoom', () => { graph.emit('afterzoom', {}); + + const node1 = graph.find('node1'); + const node1label = node1.getLabel(); + const node3 = graph.find('node3'); + const node3label = node3.getLabel(); + expect(node1label.get('visible')).eql(true); + expect(node3label.get('visible')).eql(false); }); it('graph destroy', () => { graph.destroy(); From 1bfd456d84dd694b540383636f5b1020b60faa21 Mon Sep 17 00:00:00 2001 From: Yanyan-Wang Date: Thu, 9 Aug 2018 16:15:42 +0800 Subject: [PATCH 4/4] refactor: maxSpanningForest template paramters --- demos/gallery-anchors-selection.html | 134 ++++++++++++++++++++ demos/gallery-case1.html | 10 +- demos/gallery-graphanalyzer.html | 4 +- demos/gallery-webIndex.html | 2 +- plugins/layout.forceAtlas2/layout.js | 6 +- plugins/template.maxSpanningForest/index.js | 101 ++++++++------- 6 files changed, 198 insertions(+), 59 deletions(-) create mode 100644 demos/gallery-anchors-selection.html diff --git a/demos/gallery-anchors-selection.html b/demos/gallery-anchors-selection.html new file mode 100644 index 000000000..266011c6a --- /dev/null +++ b/demos/gallery-anchors-selection.html @@ -0,0 +1,134 @@ + + + + + + + + 画廊-多锚点选择 + + + +
+ + + + + + \ No newline at end of file diff --git a/demos/gallery-case1.html b/demos/gallery-case1.html index d6966b6a9..5c5d6685a 100644 --- a/demos/gallery-case1.html +++ b/demos/gallery-case1.html @@ -18,9 +18,9 @@ -
-

2018 世界杯关注度、胜负分析

-

该图为 2018 年世界杯期间的相关数据。图上点越大代表该国球队关注的人数越多,连线代表双方有对战,箭头代表胜方,双箭头代表双方均有赢。

+
+

2018 世界杯关注度、胜负分析

+

该图为 2018 年世界杯期间的相关数据。图上点越大代表该国球队关注的人数越多,连线代表双方有对战,箭头代表胜方,双箭头代表双方均有赢。

@@ -107,13 +107,13 @@ img.src = './assets/data/footer.png'; img.setAttribute('width', 130); img.style.setProperty('margin', '0pt'); - img.style.setProperty('margin-top', '-120pt'); + img.style.setProperty('margin-top', '400pt'); img.style.setProperty('position', 'absolute'); parent.appendChild(img); var footer = document.createElement("a"); footer.style.setProperty('margin', '20pt'); - footer.style.setProperty('margin-top', '-30pt'); + footer.style.setProperty('margin-top', '485pt'); footer.style.setProperty('position', 'absolute'); footer.style.setProperty('color', 'rgb(126,131,139)'); footer.style.setProperty('text-decoration', 'none'); diff --git a/demos/gallery-graphanalyzer.html b/demos/gallery-graphanalyzer.html index 1a8ef1a83..5dfe135d3 100644 --- a/demos/gallery-graphanalyzer.html +++ b/demos/gallery-graphanalyzer.html @@ -100,9 +100,9 @@ // }); // }); const minimap = document.getElementById('minimap'); - const legend = document.getElementById('legend'); + // const legend = document.getElementById('legend'); if (minimap !== undefined) minimap.style.display = 'none'; - if (legend !== undefined) legend.style.display = 'none'; + // if (legend !== undefined) legend.style.display = 'none'; }); diff --git a/demos/gallery-webIndex.html b/demos/gallery-webIndex.html index 3291216cf..06a9a9b40 100644 --- a/demos/gallery-webIndex.html +++ b/demos/gallery-webIndex.html @@ -71,7 +71,7 @@ interactive: false, textDisplay: false, node_label: null, - edge_style(model) { + edgeStyle(model) { return { stroke: graph.find(model.target).getModel().color, strokeOpacity: 0.8 diff --git a/plugins/layout.forceAtlas2/layout.js b/plugins/layout.forceAtlas2/layout.js index 9f2365243..b4894bbfb 100644 --- a/plugins/layout.forceAtlas2/layout.js +++ b/plugins/layout.forceAtlas2/layout.js @@ -159,11 +159,11 @@ class Layout { loading.style.setProperty('background-color', '#fff'); loading.style.setProperty('position', 'absolute'); const parent = graph.getGraphContainer().parentNode; - const divHeight = parent.offsetHeight ? parent.offsetHeight : 500; - const divWidth = parent.offsetWidth ? parent.offsetWidth : 500; + const divHeight = parent.offsetHeight ? parent.offsetHeight : 600; + const divWidth = parent.offsetWidth ? parent.offsetWidth : 600; loading.style.setProperty('width', divWidth + 'px'); loading.style.setProperty('height', divHeight + 'px'); - loading.style.setProperty('margin-top', (-parent.offsetHeight) + 'px'); + loading.style.setProperty('margin-top', 0 + 'px');// (-parent.offsetHeight)s loading.style.zIndex = 999; parent.appendChild(loading); // the loading image diff --git a/plugins/template.maxSpanningForest/index.js b/plugins/template.maxSpanningForest/index.js index 902144cac..ebbc758fc 100644 --- a/plugins/template.maxSpanningForest/index.js +++ b/plugins/template.maxSpanningForest/index.js @@ -37,21 +37,12 @@ class Plugin { callBack: 'showAll' }] }, - layout: { - auto: 'once', // true false once - processer: new Layout({ - kr: 120, - kg: 8.0, - mode: 'common', - prevOverlapping: true, - dissuadeHubs: false, - maxIteration: 1000, - barnesHut: true, - ks: 0.1, - ksmax: 10, - tao: 0.1, - ...options.layoutCfg - }) + layoutCfg: { + kr: 120, + kg: 8.0, + prevOverlapping: true, + maxIteration: 1000, + barnesHut: true }, fisheye: true, menu: null, @@ -61,11 +52,22 @@ class Plugin { stroke: '#4F7DAB', strokeOpacity: 0.65 }, + activedEdgeStyle: { + endArrow: true, + stroke: '#4C7295', + strokeOpacity: 1 + }, nodeStyle: { stroke: '#696969', strokeOpacity: 0.4, lineWidth: 1 }, + activedNodeStyle: { + stroke: '#fff', + lineWidth: 1, + shadowColor: '#6a80aa', + shadowBlur: 20 + }, node_label(model) { return { text: model.id, @@ -75,12 +77,12 @@ class Plugin { }; }, interactive: true, - textDisplay: true, - ...options - }); + textDisplay: true + }, options); } init() { const graph = this.graph; + const highlighter = new G6.Plugins['tool.highlightSubgraph'](); if (this.fisheye) { const fisheye = new G6.Plugins['tool.fisheye']({ @@ -94,9 +96,17 @@ class Plugin { } graph.addPlugin(highlighter); graph.on('beforeinit', () => { - const layout = graph.get('layout'); + let layout = graph.get('layout'); if (!layout) { - graph.set('layout', this.layout); + const { kr, kg, prevOverlapping, maxIteration, barnesHut } = this.layoutCfg; + layout = { + auto: 'once', // true false once + processer: new Layout({ + kr, kg, prevOverlapping, + maxIteration, barnesHut + }) + }; + graph.set('layout', layout); } this.graph.activeItem = item => { this.activeItem(item); @@ -134,7 +144,9 @@ class Plugin { this.setStyle(); this.interactive && this.setListener(); const menuCfg = this.menuCfg; - this.menu = new Menu({ menuCfg, graph }); + if (menuCfg !== null) { + this.menu = new Menu({ menuCfg, graph }); + } }); } setStyle() { @@ -164,19 +176,10 @@ class Plugin { let style = {}; let preStyle = {}; if (item.type === 'node') { - style = { - stroke: '#fff', - lineWidth: 1, - shadowColor: '#6a80aa', - shadowBlur: 20 - }; + style = this.activedNodeStyle; preStyle = this.nodeStyle; } else if (item.type === 'edge') { - style = { - endArrow: true, - stroke: '#4C7295', - strokeOpacity: 1 - }; + style = this.activedEdgeStyle; preStyle = this.edgeStyle; } else return; @@ -229,22 +232,24 @@ class Plugin { shape, item }) => { - if (shape && item.isNode) { - const menuX = item.getModel().x * graph.getMatrix()[0] + graph.getMatrix()[6]; - const menuY = item.getModel().y * graph.getMatrix()[0] + graph.getMatrix()[7]; - this.menu.show(item, menuX, menuY); - graph.draw(); - } else { - this.menu.hide(); - // restore the highlighted graph and hide the edges which are not tree edges. - graph.unhighlightGraph(); - const edges = graph.getEdges(); - Util.each(edges, edge => { - if (edge.isVisible() && !edge.getModel().isTreeEdge) { - edge.hide(); - } - }); - graph.draw(); + if (this.menuCfg !== null) { + if (shape && item.isNode) { + const menuX = item.getModel().x * graph.getMatrix()[0] + graph.getMatrix()[6]; + const menuY = item.getModel().y * graph.getMatrix()[0] + graph.getMatrix()[7]; + this.menu.show(item, menuX, menuY); + graph.draw(); + } else { + this.menu.hide(); + // restore the highlighted graph and hide the edges which are not tree edges. + graph.unhighlightGraph(); + const edges = graph.getEdges(); + Util.each(edges, edge => { + if (edge.isVisible() && !edge.getModel().isTreeEdge) { + edge.hide(); + } + }); + graph.draw(); + } } });