add: subgraph layout by new layout. fix: force layout drag problem.

This commit is contained in:
shiwu.wyy 2019-09-19 14:23:38 +08:00
parent c4a0cfcb53
commit c0a77c2764
12 changed files with 3385 additions and 3789 deletions

View File

@ -12,24 +12,6 @@
<script src="../build/circular.js"></script>
<script src="../build/bundling.js"></script>
<script>
const data0 = {
"nodes": [
{"id": "0", "label": "0"},
{"id": "1", "label": "1"},
{"id": "2", "label": "2"},
{"id": "3", "label": "3"},
{"id": "4", "label": "4"}
],
"edges": [
{"source": "0", "target": "1", "value": 1},
{"source": "1", "target": "2", "value": 8},
{"source": "2", "target": "3", "value": 8},
{"source": "3", "target": "0", "value": 8},
{"source": "1", "target": "3", "value": 8},
{"source": "0", "target": "4", "value": 8}
]
};
const data = {
"nodes": [
{"id": "0", "label": "0"},
@ -130,15 +112,7 @@
{"source": "32", "target": "33"}
]
};
// data.edges.forEach((edge, i) => {
// edge.id = i;
// });
const circularLayout = new Circular({
center: [ 500, 400 ],
radius: 300,
ordering: null
});
const edgeBundling = new Bundling({
bundleThreshold: 0.1
});
@ -146,7 +120,13 @@
container: 'mountNode',
width: 1000,
height: 800,
plugins: [ circularLayout, edgeBundling ],
layout: {
type: 'circular',
center: [ 500, 400 ],
radius: 300,
ordering: null
},
plugins: [ edgeBundling ],
defaultNode: {
size: [20, 20],
color: 'steelblue'
@ -171,12 +151,10 @@
}
});
graph.data(data);
circularLayout.layout(data);
graph.render();
setTimeout(() => {
edgeBundling.bundling(data);
console.log(data.edges);
}, 1000);
</script>

View File

@ -11,24 +11,6 @@
<script src="./assets/d3-4.13.0.min.js"></script>
<script src="../build/circular.js"></script>
<script>
const data0 = {
"nodes": [
{"id": "0", "label": "0"},
{"id": "1", "label": "1"},
{"id": "2", "label": "2"},
{"id": "3", "label": "3"},
{"id": "4", "label": "4"}
],
"edges": [
{"source": "0", "target": "1", "value": 1},
{"source": "1", "target": "2", "value": 8},
{"source": "2", "target": "3", "value": 8},
{"source": "3", "target": "0", "value": 8},
{"source": "1", "target": "3", "value": 8},
{"source": "0", "target": "4", "value": 8}
]
};
const data = {
"nodes": [
{"id": "0", "label": "0"},
@ -133,16 +115,16 @@
data.edges.forEach((edge, i) => {
edge.id = i;
});
const circularLayout = new Circular({
center: [ 250, 150 ],
radius: 100,
ordering: null
});
const graph = new G6.Graph({
container: 'mountNode',
width: 500,
height: 300,
plugins: [ circularLayout ],
layout: {
type: 'circular',
center: [ 250, 150 ],
radius: 100,
ordering: null
},
defaultNode: {
size: [20, 20],
color: 'steelblue'
@ -170,24 +152,22 @@
edge.id = 'edge' + i;
return Object.assign({}, edge);
}) });
circularLayout.layout(data);
graph.render();
const spiralLayout = new Circular({
center: [ 250, 150 ],
startRadius: 10,
endRadius: 140,
startAngle: Math.PI / 4,
endAngle: 3 * Math.PI,
clockwise: false,
ordering: 'topology'
});
const graphSpiral = new G6.Graph({
container: 'mountNode2',
width: 500,
height: 300,
plugins: [ spiralLayout ],
layout: {
type: 'circular',
center: [ 250, 150 ],
startRadius: 10,
endRadius: 140,
startAngle: Math.PI / 4,
endAngle: 3 * Math.PI,
clockwise: false,
ordering: 'topology'
},
defaultNode: {
size: [20, 20],
color: 'steelblue'
@ -215,23 +195,21 @@
edge.id = 'edge' + i;
return Object.assign({}, edge);
}) });
spiralLayout.layout(data);
graphSpiral.render();
const circularDividedLayout = new Circular({
center: [ 250, 150 ],
radius: 100,
startAngle: Math.PI / 4,
endAngle: Math.PI,
divisions: 5,
ordering: 'degree'
});
const graphDivided = new G6.Graph({
container: 'mountNode2',
width: 500,
height: 300,
plugins: [ circularDividedLayout ],
layout: {
type: 'circular',
center: [ 250, 150 ],
radius: 100,
startAngle: Math.PI / 4,
endAngle: Math.PI,
divisions: 5,
ordering: 'degree'
},
defaultNode: {
size: [20, 20],
color: 'steelblue'
@ -259,7 +237,6 @@
edge.id = 'edge' + i;
return Object.assign({}, edge);
}) });
circularDividedLayout.layout(data);
graphDivided.render();
</script>
</body>

View File

@ -516,16 +516,6 @@
let clickedNodeId = -1;
let clickedNodePos = {'x': 500, 'y': 300};
const ForceLayoutPlugin = new Force({
center: [ 500, 300 ], // 向心力作用点
nodeStrength: -10, // 节点作用力
preventOverlap: true, // 是否防止节点相互覆盖
nodeRadius: 40, // 节点半径
edgeStrength: 1, // 边的作用力, 默认为根据节点的入度出度自适应
linkDistance: 100, // 默认边长度
forceSimulation: null, // 自定义 force 方法
});
// 封装点击添加边的交互
G6.registerBehavior('click-add-node', {
@ -559,7 +549,6 @@ const ForceLayoutPlugin = new Force({
allNodeModels.push(model);
});
console.log(newNodeModels);
newNodeModels.forEach((nodeModel, i) => {
// if it does not exist in nodes
let exist = false;
@ -569,9 +558,9 @@ const ForceLayoutPlugin = new Force({
return;
}
});
// them add it into graph
// then add it into graph
if (!exist) {
// set the initial positions of the new nodes to the clicked node
// set the initial positions of the new nodes at the clicked node
nodeModel.x = itemModel.x;
nodeModel.y = itemModel.y;
const node = graph.addItem('node', nodeModel);
@ -595,13 +584,15 @@ const ForceLayoutPlugin = new Force({
edges.push(edge);
}
});
edges.forEach((e, i) => {
allEdgeModels.push(e.getModel());
});
ForceLayoutPlugin.updateLayout( {'nodeStrength': -10, 'data': {'nodes': allNodeModels, 'edges': allEdgeModels}});
}
graph.changeData({
nodes: allNodeModels,
edges: allEdgeModels
});
}
});
let data = getNodeById.data;
@ -610,7 +601,15 @@ const ForceLayoutPlugin = new Force({
container: 'mountNode',
width: 1000,
height: 600,
plugins: [ ForceLayoutPlugin ],
layout: {
type: 'force',
center: [ 500, 300 ], // 向心力作用点
nodeStrength: -30, // 节点作用力
preventOverlap: true, // 是否防止节点相互覆盖
nodeSize: 40, // 节点大小 / 直径
edgeStrength: 0.1, // 边的作用力, 默认为根据节点的入度出度自适应
linkDistance: 100, // 默认边长度
},
modes: {
default: ['drag-node', 'click-select', 'click-add-node']
},
@ -643,7 +642,6 @@ const ForceLayoutPlugin = new Force({
graph.data(data);
ForceLayoutPlugin.layout(data);
graph.render();
graph.on('node:dragend', ev => {
const itemModel = ev.item.getModel();

View File

@ -353,12 +353,11 @@
container: 'mountNode',
width: 1000,
height: 600,
layout: {
type: 'force'
},
modes: {
default: [{
type: 'brush-select',
onSelect(nodes) { console.log('selected:', nodes); },
onDeselect(nodes) { console.log('deselect', nodes); }
}]
default: [ 'drag-node' ]
},
defaultNode: {
size: [10, 10],
@ -390,36 +389,22 @@
edge.id = 'edge' + i;
return Object.assign({}, edge);
}) });
const simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }).strength(0.5))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(500,300));
simulation
.nodes(data.nodes)
.on("tick", ticked);
simulation.force("link")
.links(data.edges);
graph.render();
function ticked() {
graph.refreshPositions();
}
function refreshPosition(e) {
function refreshDragedNodePosition(e) {
const model = e.item.get('model');
model.fx = e.x;
model.fy = e.y;
}
graph.on('node:dragstart', e => {
simulation.alphaTarget(0.3).restart();
refreshPosition(e);
graph.layout();
refreshDragedNodePosition(e);
});
graph.on('node:drag', e => {
refreshPosition(e);
refreshDragedNodePosition(e);
});
graph.on('node:dragend', e => {
e.item.get('model').fx = null;
e.item.get('model').fy = null;
simulation.alphaTarget(0);
});
</script>
</body>

View File

@ -347,375 +347,15 @@
]
};
const data1 = {
"nodes": [
{"id": "0"},
{"id": "1"},
{"id": "2"},
{"id": "3"},
{"id": "4"},
{"id": "5"},
{"id": "6"},
{"id": "7"}
], "edges": [
{"source": "0", "target": "1"},
{"source": "1", "target": "2"},
{"source": "2", "target": "3"},
{"source": "3", "target": "0"},
{"source": "3", "target": "4"},
{"source": "3", "target": "5"},
{"source": "3", "target": "6"},
{"source": "3", "target": "7"},
]
};
const data2 = {
"nodes": [
{"id": "11"},
{"id": "48"},
{"id": "55"},
{"id": "27"},
{"id": "25"},
{"id": "23"},
{"id": "58"},
{"id": "62"},
{"id": "64"},
{"id": "63"},
{"id": "65"},
{"id": "24"},
{"id": "26"},
{"id": "41"},
{"id": "57"},
{"id": "59"},
{"id": "61"},
{"id": "0"},
{"id": "66"},
{"id": "68"},
{"id": "69"},
{"id": "70"},
{"id": "16"},
{"id": "60"},
{"id": "71"},
{"id": "29"},
{"id": "17"},
{"id": "18"},
{"id": "19"},
{"id": "20"},
{"id": "21"},
{"id": "22"},
{"id": "49"},
{"id": "51"},
{"id": "75"},
{"id": "76"},
{"id": "34"},
{"id": "35"},
{"id": "36"},
{"id": "37"},
{"id": "38"},
{"id": "28"},
{"id": "31"},
{"id": "54"},
{"id": "2"},
{"id": "3"},
{"id": "39"},
{"id": "42"},
{"id": "43"},
{"id": "72"},
{"id": "12"},
{"id": "30"},
{"id": "33"},
{"id": "44"},
{"id": "47"},
{"id": "50"},
{"id": "52"},
{"id": "56"},
{"id": "73"},
{"id": "74"},
{"id": "1"},
{"id": "4"},
{"id": "5"},
{"id": "6"},
{"id": "7"},
{"id": "8"},
{"id": "9"},
{"id": "10"},
{"id": "13"},
{"id": "14"},
{"id": "15"},
{"id": "32"},
{"id": "40"},
{"id": "45"},
{"id": "46"},
{"id": "53"},
{"id": "67"}],
"edges": [
{"source": "1", "target": "0"},
{"source": "2", "target": "0"},
{"source": "3", "target": "0"},
{"source": "3", "target": "2"},
{"source": "4", "target": "0"},
{"source": "5", "target": "0"},
{"source": "6", "target": "0"},
{"source": "7", "target": "0"},
{"source": "8", "target": "0"},
{"source": "9", "target": "0"},
{"source": "11", "target": "0"},
{"source": "11", "target": "2"},
{"source": "11", "target": "3"},
{"source": "11", "target": "10"},
{"source": "12", "target": "11"},
{"source": "13", "target": "11"},
{"source": "14", "target": "11"},
{"source": "15", "target": "11"},
{"source": "17", "target": "16"},
{"source": "18", "target": "16"},
{"source": "18", "target": "17"},
{"source": "19", "target": "16"},
{"source": "19", "target": "17"},
{"source": "19", "target": "18"},
{"source": "20", "target": "16"},
{"source": "20", "target": "17"},
{"source": "20", "target": "18"},
{"source": "20", "target": "19"},
{"source": "21", "target": "16"},
{"source": "21", "target": "17"},
{"source": "21", "target": "18"},
{"source": "21", "target": "19"},
{"source": "21", "target": "20"},
{"source": "22", "target": "16"},
{"source": "22", "target": "17"},
{"source": "22", "target": "18"},
{"source": "22", "target": "19"},
{"source": "22", "target": "20"},
{"source": "22", "target": "21"},
{"source": "23", "target": "11"},
{"source": "23", "target": "12"},
{"source": "23", "target": "16"},
{"source": "23", "target": "17"},
{"source": "23", "target": "18"},
{"source": "23", "target": "19"},
{"source": "23", "target": "20"},
{"source": "23", "target": "21"},
{"source": "23", "target": "22"},
{"source": "24", "target": "11"},
{"source": "24", "target": "23"},
{"source": "25", "target": "11"},
{"source": "25", "target": "23"},
{"source": "25", "target": "24"},
{"source": "26", "target": "11"},
{"source": "26", "target": "16"},
{"source": "26", "target": "24"},
{"source": "26", "target": "25"},
{"source": "27", "target": "11"},
{"source": "27", "target": "23"},
{"source": "27", "target": "24"},
{"source": "27", "target": "25"},
{"source": "27", "target": "26"},
{"source": "28", "target": "11"},
{"source": "28", "target": "27"},
{"source": "29", "target": "11"},
{"source": "29", "target": "23"},
{"source": "29", "target": "27"},
{"source": "30", "target": "23"},
{"source": "31", "target": "11"},
{"source": "31", "target": "23"},
{"source": "31", "target": "27"},
{"source": "31", "target": "30"},
{"source": "32", "target": "11"},
{"source": "33", "target": "11"},
{"source": "33", "target": "27"},
{"source": "34", "target": "11"},
{"source": "34", "target": "29"},
{"source": "35", "target": "11"},
{"source": "35", "target": "29"},
{"source": "35", "target": "34"},
{"source": "36", "target": "11"},
{"source": "36", "target": "29"},
{"source": "36", "target": "34"},
{"source": "36", "target": "35"},
{"source": "37", "target": "11"},
{"source": "37", "target": "29"},
{"source": "37", "target": "34"},
{"source": "37", "target": "35"},
{"source": "37", "target": "36"},
{"source": "38", "target": "11"},
{"source": "38", "target": "29"},
{"source": "38", "target": "34"},
{"source": "38", "target": "35"},
{"source": "38", "target": "36"},
{"source": "38", "target": "37"},
{"source": "39", "target": "25"},
{"source": "40", "target": "25"},
{"source": "41", "target": "24"},
{"source": "41", "target": "25"},
{"source": "42", "target": "24"},
{"source": "42", "target": "25"},
{"source": "42", "target": "41"},
{"source": "43", "target": "11"},
{"source": "43", "target": "26"},
{"source": "43", "target": "27"},
{"source": "44", "target": "11"},
{"source": "44", "target": "28"},
{"source": "45", "target": "28"},
{"source": "47", "target": "46"},
{"source": "48", "target": "11"},
{"source": "48", "target": "25"},
{"source": "48", "target": "27"},
{"source": "48", "target": "47"},
{"source": "49", "target": "11"},
{"source": "49", "target": "26"},
{"source": "50", "target": "24"},
{"source": "50", "target": "49"},
{"source": "51", "target": "11"},
{"source": "51", "target": "26"},
{"source": "51", "target": "49"},
{"source": "52", "target": "39"},
{"source": "52", "target": "51"},
{"source": "53", "target": "51"},
{"source": "54", "target": "26"},
{"source": "54", "target": "49"},
{"source": "54", "target": "51"},
{"source": "55", "target": "11"},
{"source": "55", "target": "16"},
{"source": "55", "target": "25"},
{"source": "55", "target": "26"},
{"source": "55", "target": "39"},
{"source": "55", "target": "41"},
{"source": "55", "target": "48"},
{"source": "55", "target": "49"},
{"source": "55", "target": "51"},
{"source": "55", "target": "54"},
{"source": "56", "target": "49"},
{"source": "56", "target": "55"},
{"source": "57", "target": "41"},
{"source": "57", "target": "48"},
{"source": "57", "target": "55"},
{"source": "58", "target": "11"},
{"source": "58", "target": "27"},
{"source": "58", "target": "48"},
{"source": "58", "target": "55"},
{"source": "58", "target": "57"},
{"source": "59", "target": "48"},
{"source": "59", "target": "55"},
{"source": "59", "target": "57"},
{"source": "59", "target": "58"},
{"source": "60", "target": "48"},
{"source": "60", "target": "58"},
{"source": "60", "target": "59"},
{"source": "61", "target": "48"},
{"source": "61", "target": "55"},
{"source": "61", "target": "57"},
{"source": "61", "target": "58"},
{"source": "61", "target": "59"},
{"source": "61", "target": "60"},
{"source": "62", "target": "41"},
{"source": "62", "target": "48"},
{"source": "62", "target": "55"},
{"source": "62", "target": "57"},
{"source": "62", "target": "58"},
{"source": "62", "target": "59"},
{"source": "62", "target": "60"},
{"source": "62", "target": "61"},
{"source": "63", "target": "48"},
{"source": "63", "target": "55"},
{"source": "63", "target": "57"},
{"source": "63", "target": "58"},
{"source": "63", "target": "59"},
{"source": "63", "target": "60"},
{"source": "63", "target": "61"},
{"source": "63", "target": "62"},
{"source": "64", "target": "11"},
{"source": "64", "target": "48"},
{"source": "64", "target": "55"},
{"source": "64", "target": "57"},
{"source": "64", "target": "58"},
{"source": "64", "target": "59"},
{"source": "64", "target": "60"},
{"source": "64", "target": "61"},
{"source": "64", "target": "62"},
{"source": "64", "target": "63"},
{"source": "65", "target": "48"},
{"source": "65", "target": "55"},
{"source": "65", "target": "57"},
{"source": "65", "target": "58"},
{"source": "65", "target": "59"},
{"source": "65", "target": "60"},
{"source": "65", "target": "61"},
{"source": "65", "target": "62"},
{"source": "65", "target": "63"},
{"source": "65", "target": "64"},
{"source": "66", "target": "48"},
{"source": "66", "target": "58"},
{"source": "66", "target": "59"},
{"source": "66", "target": "60"},
{"source": "66", "target": "61"},
{"source": "66", "target": "62"},
{"source": "66", "target": "63"},
{"source": "66", "target": "64"},
{"source": "66", "target": "65"},
{"source": "67", "target": "57"},
{"source": "68", "target": "11"},
{"source": "68", "target": "24"},
{"source": "68", "target": "25"},
{"source": "68", "target": "27"},
{"source": "68", "target": "41"},
{"source": "68", "target": "48"},
{"source": "69", "target": "11"},
{"source": "69", "target": "24"},
{"source": "69", "target": "25"},
{"source": "69", "target": "27"},
{"source": "69", "target": "41"},
{"source": "69", "target": "48"},
{"source": "69", "target": "68"},
{"source": "70", "target": "11"},
{"source": "70", "target": "24"},
{"source": "70", "target": "25"},
{"source": "70", "target": "27"},
{"source": "70", "target": "41"},
{"source": "70", "target": "58"},
{"source": "70", "target": "68"},
{"source": "70", "target": "69"},
{"source": "71", "target": "11"},
{"source": "71", "target": "25"},
{"source": "71", "target": "27"},
{"source": "71", "target": "41"},
{"source": "71", "target": "48"},
{"source": "71", "target": "68"},
{"source": "71", "target": "69"},
{"source": "71", "target": "70"},
{"source": "72", "target": "11"},
{"source": "72", "target": "26"},
{"source": "72", "target": "27"},
{"source": "73", "target": "48"},
{"source": "74", "target": "48"},
{"source": "74", "target": "73"},
{"source": "75", "target": "25"},
{"source": "75", "target": "41"},
{"source": "75", "target": "48"},
{"source": "75", "target": "68"},
{"source": "75", "target": "69"},
{"source": "75", "target": "70"},
{"source": "75", "target": "71"},
{"source": "76", "target": "48"},
{"source": "76", "target": "58"},
{"source": "76", "target": "62"},
{"source": "76", "target": "63"},
{"source": "76", "target": "64"},
{"source": "76", "target": "65"},
{"source": "76", "target": "66"},
]
}
const fruchtermanLayout = new Fruchterman({
maxIteration: 8000,
gravity: 10,
center: [500, 300]
});
const graph = new G6.Graph({
container: 'mountNode',
width: 1000,
height: 600,
plugins: [ fruchtermanLayout ],
layout: {
type: 'fruchterman',
maxIteration: 8000,
gravity: 10
},
modes: {
default: ['drag-canvas']
},
@ -745,11 +385,10 @@
}
}
});
graph.data({ nodes: data2.nodes, edges: data2.edges.map((edge, i) => {
graph.data({ nodes: data.nodes, edges: data.edges.map((edge, i) => {
edge.id = 'edge' + i;
return Object.assign({}, edge);
}) });
fruchtermanLayout.layout(data2);
graph.render();
</script>
</body>

View File

@ -122,8 +122,11 @@
container: 'mountNode',
width: 1000,
height: 600,
plugins: [ MDSPlugin ],
modes: { default: [ 'drag-node' ] },
layout: {
type: 'mds',
linkDistance: 100
},
modes: { default: [ 'drag-node' ] },
defaultNode: {
size: [20, 20],
color: 'steelblue'
@ -154,7 +157,6 @@
edge.id = 'edge' + i;
return Object.assign({}, edge);
}) });
MDSPlugin.layout(data);
graph.render();
</script>

File diff suppressed because it is too large Load Diff

View File

@ -100,7 +100,7 @@
"screenshot": "node ./bin/screenshot.js",
"start": "npm run dev",
"test": "torch --compile --renderer --opts test/mocha.opts --recursive ./test/unit",
"test-live": "torch --compile --interactive --watch --opts test/mocha.opts --recursive ./test/unit/graph/controller/layout-spec.js",
"test-live": "torch --compile --interactive --watch --opts test/mocha.opts --recursive ./test/unit/",
"test-bugs": "torch --compile --renderer --recursive ./test/bugs",
"test-bugs-live": "torch --compile --interactive --watch --recursive ./test/bugs",
"test-all": "npm run test && npm run test-bugs",

View File

@ -110,6 +110,18 @@ class LayoutController {
self.layout();
}
// 重新布局
relayout() {
const self = this;
const layoutMethod = self.layoutMethod;
if (self.layoutType === 'force') {
layoutMethod.ticking = false;
layoutMethod.forceSimulation.stop();
}
layoutMethod.excute();
self.graph.refreshPositions();
}
// 控制布局动画
layoutAnimate() {
}

View File

@ -1042,6 +1042,16 @@ class Graph extends EventEmitter {
layoutController.updateLayoutCfg(layoutCfg);
}
layout() {
const layoutController = this.get('layoutController');
if (layoutController.layoutMethod) {
layoutController.relayout();
this.refreshPositions();
} else {
layoutController.layout();
}
}
/**
* 清除画布元素
* @return {object} this

View File

@ -2,10 +2,10 @@
* @fileOverview entry file
* @author huangtonger@aliyun.com
*/
// const Shape = require('./shape/');
const Global = require('./global');
const G = require('@antv/g/lib');
const Shape = require('./shape');
const Layout = require('./layout');
const Behaviors = require('./behavior');
const G6 = {
@ -15,6 +15,7 @@ const G6 = {
G,
Global,
Shape,
Layout,
registerNode: Shape.registerNode,
registerEdge: Shape.registerEdge,
registerBehavior: Behaviors.registerBehavior,

View File

@ -17,7 +17,7 @@ Layout.registerLayout('force', {
center: [ 0, 0 ], // 向心力作用点
nodeStrength: null, // 节点作用力
preventOverlap: false, // 是否防止节点相互覆盖
nodeSize: 10, // 节点大小,用于防止重叠时的碰撞检测
nodeSize: 10, // 节点大小 / 直径,用于防止重叠时的碰撞检测
edgeStrength: null, // 边的作用力, 默认为根据节点的入度出度自适应
linkDistance: 50, // 默认边长度
forceSimulation: null, // 自定义 force 方法
@ -78,9 +78,15 @@ Layout.registerLayout('force', {
}
return d.size / 2;
}
return 20;
return 10;
};
} else if (!isNaN(nodeSize)) {
nodeSize /= 2;
} else if (nodeSize.length === 2) {
const larger = nodeSize[0] > nodeSize[1] ? nodeSize[0] : nodeSize[1];
nodeSize = larger / 2;
}
// forceCollide's parameter is a radius
simulation.force('collisionForce', d3Force.forceCollide(nodeSize).strength(1));
}
// 如果有边,定义边的力