在这个dome中d3只用于位置计算和缩放,在关系图谱中,大量节点的情况下,对比与svg,canvas有着性能优势,因为它不需要频繁操作dom节点,不需要创建深层次的dom结构。 使用原生的canvas api比较复杂,很多第三方库提供了更加方便操作canvas的库,这里选用的是zrender。 canvas的一些比较复杂的东西比如事件,层级在zrender中也可以很好地实现。
zrender
api文档:ecomfe.github.io/zrender-doc… 仓库地址:github.com/ecomfe/zren… demo:github.com/ecomfe/zren… 由于目前最新版本对一些功能的支持和文档不一样(图形文字),所以当前demo采用4.3.2版本。
核心api
初始化
选择html中对应存在的dom作为容器,返回一个实例对象,用于创建图形,这里要记得给#main设置宽高
const zr = zrender.init(document.querySelector('#main'));
创建一个圆形
<body>
<div id="main" style="width:100vw;height:100vh"></div>
<script src="../lib/zrender.v4.3.2.js"></script>
<script>
const zr = new zrender.init(document.querySelector('#main'));
console.log(zr);
const circle = new zrender.Circle({
shape: {
// 圆中心点x坐标
cx: 100,
// 圆中心点y坐标
cy: 100,
// 圆半径
r: 100
},
style: {
// 设置圆样式
fill: 'blue',
stroke: 'black',
// 设置圆内文本样式
text: '圆内文本',
textFill: 'white',
fontSize: 20,
// 缩放文本大小跟随
transformText: true
}
})
zr.add(circle)
</script>
</body>
创建一条直线
const line = new zrender.Line({
shape: {
// 起始x坐标
x1: 100,
// 起始y坐标
y1: 300,
// 结束x坐标
x2: 100,
// 结束y坐标
y2: 500
},
style: {
// 线条颜色
stroke: 'blue',
// 线条粗细
lineWidth: 2,
text: '直线中间的文本',
// 文字的包围矩形背景色
textBackgroundColor: '#fff',
}
})
zr.add(line);
绘制三角形
const polygon = new zrender.Polygon({
shape: {
// 填充图形的坐标
points: [[x3, y3], [x4, y4], [x2, y2]],
},
style: {
fill: '填充颜色',
opacity
},
z
})
创建带箭头的直线
箭头的位置需要一些三角函数的运算,下面代码为封装好的绘制函数,offset为0的时候尖端是个矩形,可以调整为负数实现更好的效果,当前这个dome中,由于箭头指向圆变,所以要偏移圆半径的距离。
const zr = new zrender.init(document.querySelector('#main'));
/*
x1,y1:起点坐标
x2,y2:终点坐标
offset:箭头距离终点偏移量
l:箭头大小控制参数
*/
function drawArrow(zr, x1, y1, x2, y2, offset = 0, l = 10) {
const line = new zrender.Line({
shape: {
x1,
y1,
x2,
y2
},
style: {
// 线条颜色
stroke: 'blue',
// 线条粗细
lineWidth: 2,
text: '直线中间的文本',
// 文字的包围矩形背景色
textBackgroundColor: '#fff',
}
})
const a = Math.atan2((y2 - y1), (x2 - x1));
let tx = x2;
let ty = y2
// 偏移长度
let totalLength = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
x2 = x1 + (totalLength - offset) * Math.cos(a)
y2 = y1 + (totalLength - offset) * Math.sin(a)
// D点x轴坐标
const x3 = x2 - l * Math.cos(a + 30 * Math.PI / 180);
// D点y轴坐标
const y3 = y2 - l * Math.sin(a + 30 * Math.PI / 180);
// C点x轴坐标
const x4 = x2 - l * Math.cos(a - 30 * Math.PI / 180);
// C点y轴坐标
const y4 = y2 - l * Math.sin(a - 30 * Math.PI / 180);
const polygon = new zrender.Polygon({
shape: {
// 填充图形的坐标
points: [[x3, y3], [x4, y4], [x2, y2]],
},
style: {
fill: '填充颜色',
opacity: 1
},
z: 1
})
zr.add(line);
zr.add(polygon)
}
drawArrow(zr, 200, 200, 300, 300);
d3.js
这是一个强大的可视化库,感兴趣更多细节可以查看文档或者我之前的文章,这个demo中主要使用了d3的Force布局。