首先看一下节点的数据内容
nodes: [
{id: 1, name: '刘备', type: '皇上'},
{id: 2, name: '关羽', type: '将军'},
{id: 3, name: '张飞', type: '将军'},
{id: 4, name: '诸葛亮', type: '丞相'},
{id: 5, name: '小兵1', type: '士兵'},
{id: 6, name: '小兵2', type: '士兵'},
],
links: [
{source: 1, target: 2, relate: '将军'},
{source: 1, target: 3, relate: '将军'},
{source: 1, target: 4, relate: '丞相'},
{source: 2, target: 5, relate: '下属'},
{source: 2, target: 6, relate: '下属'},
{source: 3, target: 5, relate: '下属'},
],
添加箭头标记
先定义箭头标记,再在创建边的时候添加箭头标记(.attr(‘marker-end’, ‘url(#arrow)’))
// 定义箭头标记
svg.append('defs').append('marker')
.attr('id', 'arrow')
.attr('viewBox', '0 -5 10 10')
.attr('refX', 25)
.attr('refY', 0)
.attr('markerWidth', 6)
.attr('markerHeight', 6)
.attr('orient', 'auto')
.append('path')
.attr('d', 'M0,-5L10,0L0,5')
.attr('fill', 'black');
// 创建边
const link = g.selectAll('line')
.data(data.links)
.enter()
.append('line')
.attr('stroke', '#999')
.attr('stroke-width', 2)
.attr('marker-end', 'url(#arrow)') // 添加箭头标记
实现的效果
边的点击事件,点击边的时候显示相关的节点和边,鼠标移开后恢复原来的效果
const link = g.selectAll('line')
.data(data.links)
.enter()
.append('line') // 更改为 path 以便于后续添加箭头
.attr('stroke', '#999')
.attr('stroke-width', 2)
.attr('marker-end', 'url(#arrow)') // 添加箭头标记
.style('opacity', 1) // 设置初始不透明度
.on('click', function (event, d) {
// 当点击一条边时,高亮显示与之关联的节点和边
const relatedNodes = data.nodes.filter(node => node.id === d.source.id || node.id === d.target.id);
const relatedLinks = data.links.filter(link => link.source.id === d.source.id || link.source.id === d.target.id || link.target.id === d.source.id || link.target.id === d.target.id);
// 高亮显示相关节点
node.filter(function (node) {
return relatedNodes.some(relatedNode => relatedNode.id === node.id);
}).style('fill', 'orange');
// 高亮显示相关边
link.filter(function (link) {
return relatedLinks.some(relatedLink => relatedLink.source.id === link.source.id && relatedLink.target.id === link.target.id);
}).style('stroke', 'orange')
.style('stroke-width', 4)
.style('opacity', 1);
// 淡化其他节点和边
node.filter(function (node) {
return !relatedNodes.some(relatedNode => relatedNode.id === node.id);
}).style('fill', 'lightgray');
link.filter(function (link) {
return !relatedLinks.some(relatedLink => relatedLink.source.id === link.source.id && relatedLink.target.id === link.target.id);
}).style('stroke', 'lightgray')
.style('stroke-width', 1)
.style('opacity', 0.5);
})
.on('mouseout', function (event, d) {
// 当鼠标移出边时,恢复所有节点和边的原始状态
link.style('stroke', '#999') // 恢复边的颜色
.style('stroke-width', 2) // 恢复边的宽度
.style('opacity', 1); // 恢复边的不透明度
});