官网:https://antv.alipay.com/zh-cn/g6/1.x/index.html
注意:此教程基于1.x版本官方已更新到2.x,2.x重构了之前的代码。
1.从一个示例开始
我们先从官方示例 https://antv.alipay.com/zh-cn/g6/1.x/demo/other/plugin-dagre.html 开始学习如何使用G6
插件:统一分层布局
首先需要一个DOM容器来创建与初始化图表,比如代码中的
关于创建图表的参数说明可以参考文档https://antv.alipay.com/zh-cn/g6/1.x/api/graph.html我就不一一解释
创建后通过net.source(data.nodes, data.edges)
加载数据源,其中数据源格式参考以下说明,文档在https://antv.alipay.com/zh-cn/g6/1.x/api/net.html#_source
最后是通过
net.render()
来渲染显示
2.实现新增删除节点功能
新增与删除官方示例:https://antv.alipay.com/zh-cn/g6/1.x/demo/other/crud.html
根据示例我们在之前代码基础上先添加按钮用于触发
给添加网格背景
//....
const net = new G6.Net({
id: 'mountNode', // dom id
height: window.innerHeight, // 画布高
fitView: 'autoZoom',
grid: {//背景网格
forceAlign: true, // 是否支持网格对齐
cell: 10, // 网格大小
},
plugins: [plugin],
});
//....
然后就是绑定事件了(不过删除我更加习惯用键盘的delete进行删除)
//......
var i = 1;
$('#addCircle').on('click', () => {//添加圆形节点
net.add('node', {
shape: 'circle',
id: 'id' + i++,
x: 50 + i * 10,
y: 50 + i * 10
});
net.refresh();
});
$('#addRect').on('click', () => {//添加矩形
net.add('node', {
shape: 'rect',
id: 'id' + i++,
x: 50 + i * 10,
y: 50 + i * 10
});
net.refresh();
});
$('#delete').on('click', () => {//根据添加顺序删除
if (i > 1) {
i = i - 1;
const item = net.find('id' + i);
net.remove(item);
net.refresh();
}
});
//......
效果示例:
3.图编辑器效果
图编辑器官方示例:https://antv.alipay.com/zh-cn/g6/1.x/demo/other/editor.html
根据示例我们同样在之前代码基础上先添加按钮用于触发
然后可以根据需要注册自定义节点(注册自定义节点文档:https://antv.alipay.com/zh-cn/g6/1.x/api/index.html#_registerNode)
//示例......
G6.registerNode('customNode1', {
getAnchorPoints() {
return [
[0, 0.25],
[0, 0.5],
[0, 0.75],
[1, 0.25],
[1, 0.5],
[1, 0.75],
[0.25, 0],
[0.5, 0],
[0.75, 0],
[0.25, 1],
[0.5, 1],
[0.75, 1]
];
}
}, 'rect');
//......
然后就是绑定事件了
//......
$('#addCustom1').on('click', () => {//添加自定义节点图形
net.beginAdd('node', {
label: '[未定义]',
shape: 'circle'
});
});
$('#addCustom2').on('click', () => {//添加自定义节点图形
net.beginAdd('node', {label: '[未定义]'});
});
$('#addCustom3').on('click', () => {//添加自定义节点图形
net.beginAdd('node', {
label: '[未定义]',
shape: 'customNode1'//<====
});
});
$('#addLine').on('click', () => {//添加普通直线
net.beginAdd('edge', {
shape: 'line'//<====
});
});
$('#addArrowLine').on('click', () => {//添加箭头直线
net.beginAdd('edge', {
shape: 'arrow'//<====
});
});
$('#addSmooth').on('click', () => {//添加曲线
net.beginAdd('edge', {
shape: 'smooth'//<====
});
});
$('#drag').on('click', () => {//拖拽模式
net.changeMode('drag');
});
$('#edit').on('click', () => {//编辑模式
net.changeMode('edit');
});
$('#consoleJSON').on('click', () => {//控制台输入json
const saveData = net.save();
const json = JSON.stringify(saveData, null, 2);
console.log(saveData, json); // eslint-disable-line no-console
});
//.....
效果示例:
4.保存为图片
官方示例:https://antv.alipay.com/zh-cn/g6/1.x/demo/other/html2canvas.html
添加按钮
引入html2canvas插件,比如:
事件绑定:
$("#downloadImage").on('click', (bool) => {
const matrixStash = net.getMatrix(); // 缓存当前矩阵
if (bool) {
net.autoZoom(); // 图自动缩放以适应画布尺寸
}
html2canvas(net.get('graphContainer'), {
onrendered(canvas) {
const dataURL = canvas.toDataURL('image/png');
const link = document.createElement('a');
const saveName = '图片' + ('.png' || 'graph.png');//<====选中模块名称
link.download = saveName;
link.href = dataURL.replace('image/png', 'image/octet-stream');
link.click();
net.updateMatrix(matrixStash); // 还原矩阵
net.refresh();
}
});
});
5.添加提示信息
官方示例:https://antv.alipay.com/zh-cn/g6/1.x/demo/other/tooltip-cfg.html
添加提示信息十分简单直接复制粘贴改改就行
//略.....
const net = new G6.Net({
//略.....
});
net.source(data.nodes, data.edges);
net.tooltip({
title: '节点信息', // @type {String} 标题
split: ':', // @type {String} 分割符号
dx: 10, // @type {Number} 水平偏移
dy: 10 // @type {Number} 竖直偏移
});
net.node().tooltip(['id', 'label']);
net.edge().tooltip(['id']);
net.render();
//略.....
效果:
6.实现可编辑标签
可编辑标签可参考官网示例:https://antv.alipay.com/zh-cn/g6/1.x/demo/editor/mind.html
可编辑标签需要用到图表的事件,事件文档 https://antv.alipay.com/zh-cn/g6/1.x/api/graph.html#_on
以下是从官方示例里扣出来的代码,主要就是创建一个input输入框能同步显示到图表对应上方,然后对输入值进行同步绑定
有了输入框我们只要绑定图表在什么事件下显示隐藏输入框就行了
//.......
const graphContainer = net.get('graphContainer');//获取图表内部容器
graphContainer.appendChild(input);//追加input输入框
graphContainer.oncontextmenu = function (e) { return false; }//阻止默认右键菜单
net.on('contextmenu', ev => {// 鼠标右键点击事件
console.log("选中类型:", ev.itemType);
console.log(ev);
});
net.on('itemmouseenter', ev => {//子项鼠标悬浮
const item = ev.item;
net.update(item, {
color: 'red',
});
net.refresh();
});
net.on('itemmouseleave', ev => {//子项鼠标离开事件
const item = ev.item;
net.update(item, {
color: null
});
net.refresh();
});
net.on('itemmousedown', ev => {//子项鼠标按下
const item = ev.item;
net.update(item, {
color: '#9ef'
});
});
net.on('itemmouseup', ev => {//子项鼠标弹起
const item = ev.item;
net.update(item, {
color: 'null'
});
});
net.on('dragmove', () => {//拖拽隐藏
input.hide();
});
net.on('dblclick', ev => {//双击显示
const item = ev.item;
const shape = ev.shape;
if (hasClass(shape, 'label') && item && item.get('type') === 'node') {//节点的情况下
showInputLabel(item);
}
});
//.......
效果:
7.布局方向
根据文档(https://antv.alipay.com/zh-cn/g6/1.x/api/plugins.html),统一分层布局有四个方向'TB', 'BT', 'LR', or 'RL' 默认值为 'TB'
,我没找到有啥实时函数能够修改布局方向,所以简单点那就每次初始化进行修改吧。
代码示例:
效果:
最终代码效果: http://runjs.cn/detail/92edwvz9