161 lines
4.1 KiB
JavaScript
161 lines
4.1 KiB
JavaScript
/**
|
|
* @author: winyuan
|
|
* @data: 2019/07/05
|
|
* @repository: https://github.com/winyuan
|
|
* @description: 图的布局方式/图的初始化
|
|
*/
|
|
|
|
import d3 from '../plugins/d3-installer'
|
|
import theme from '../theme'
|
|
|
|
/**
|
|
* 图的布局方式/图的初始化
|
|
* @type {{commonGraph: (function(*, *): G6.Graph)}}
|
|
*/
|
|
const initGraph = {
|
|
/**
|
|
* 一般布局
|
|
* @param G6
|
|
* @param options
|
|
* @returns {G6.Graph}
|
|
*/
|
|
commonGraph: function(G6, options) {
|
|
let graphData = options.graphData
|
|
let themeStyle = theme.defaultStyle // todo...先使用默认主题,后期可能增加其它风格的主体
|
|
// 生成G6实例
|
|
let graph = new G6.Graph({
|
|
plugins: options.plugins,
|
|
container: options.container,
|
|
width: options.width,
|
|
height: options.height,
|
|
// layout: {
|
|
// type: 'random',
|
|
// width: options.width,
|
|
// height: options.height
|
|
// },
|
|
defaultNode: {
|
|
type: 'cc-rect',
|
|
labelCfg: {
|
|
position: 'bottom'
|
|
}
|
|
},
|
|
defaultEdge: {
|
|
type: 'cc-line',
|
|
labelCfg: {
|
|
position: 'center',
|
|
autoRotate: false
|
|
}
|
|
},
|
|
nodeStateStyles: themeStyle.nodeStyle,
|
|
// nodeStyle: {
|
|
// selected: {
|
|
// shadowColor: '#626262',
|
|
// shadowBlur: 8,
|
|
// shadowOffsetX: -1,
|
|
// shadowOffsetY: 3
|
|
// }
|
|
// },
|
|
edgeStateStyles: themeStyle.edgeStyle,
|
|
// edgeStyle: {
|
|
// default: {
|
|
// stroke: '#e2e2e2',
|
|
// lineWidth: 3,
|
|
// lineAppendWidth: 10
|
|
// },
|
|
// selected: {
|
|
// shadowColor: '#626262',
|
|
// shadowBlur: 3
|
|
// }
|
|
// },
|
|
modes: options.modes
|
|
})
|
|
// 将 read 方法分解成 data() 和 render 方法,便于整个生命周期的管理
|
|
graph.read(graphData)
|
|
graph.render()
|
|
// 返回G6实例
|
|
return graph
|
|
},
|
|
/**
|
|
* 力导布局
|
|
* @param G6
|
|
* @param options
|
|
* @returns {*}
|
|
*/
|
|
forceLayoutGraph: function(resolve, G6, options) {
|
|
let graphData = options.graphData
|
|
let themeStyle = theme.defaultStyle // todo...先使用默认主题,后期可能增加其它风格的主体
|
|
// 生成G6实例
|
|
let graph = new G6.Graph({
|
|
container: options.container,
|
|
width: options.width,
|
|
height: options.height,
|
|
nodeStateStyles: themeStyle.nodeStyle,
|
|
edgeStateStyles: themeStyle.edgeStyle
|
|
})
|
|
// 初始化力导布局
|
|
let simulation = d3
|
|
.forceSimulation()
|
|
.force(
|
|
'link',
|
|
d3
|
|
.forceLink()
|
|
.id(function(d) {
|
|
return d.id
|
|
})
|
|
.distance(linkDistance)
|
|
.strength(0.5)
|
|
)
|
|
.force('charge', d3.forceManyBody().strength(-500).distanceMax(500).distanceMin(100))
|
|
.force('center', d3.forceCenter(options.width / 2, options.height / 2))
|
|
// 定义节点数据
|
|
simulation.nodes(graphData.nodes).on('tick', ticked)
|
|
// 定义连线数据
|
|
let edges = []
|
|
for (let i = 0; i < graphData.edges.length; i++) {
|
|
edges.push({
|
|
id: graphData.edges[i].id,
|
|
source: graphData.edges[i].source,
|
|
target: graphData.edges[i].target
|
|
})
|
|
}
|
|
simulation.force('link').links(edges)
|
|
graph.data(graphData)
|
|
graph.render()
|
|
|
|
function linkDistance(d) {
|
|
return 150
|
|
}
|
|
|
|
function ticked() {
|
|
// protect: planA: 移除事件监听器 planB: 手动停止力模拟
|
|
if (graph.destroyed) {
|
|
// simulation.nodes(graphData.nodes).on('tick', null)
|
|
simulation.stop()
|
|
return
|
|
}
|
|
if (!graph.get('data')) {
|
|
// 若是第一次渲染,定义数据,渲染
|
|
graph.data(graphData)
|
|
graph.render()
|
|
} else {
|
|
// 后续渲染,直接刷新所有点和边的位置
|
|
graph.refreshPositions()
|
|
}
|
|
}
|
|
|
|
// 控制时间: 只布局10秒
|
|
let t = setTimeout(function() {
|
|
simulation.stop()
|
|
resolve(graph)
|
|
}, 10000)
|
|
|
|
// 判断force-layout结束
|
|
simulation.on('end', () => {
|
|
clearTimeout(t)
|
|
resolve(graph)
|
|
})
|
|
}
|
|
}
|
|
|
|
export default initGraph
|