前言
使用D3.js搭建Centos7/etc的知识图谱。本来想搭建Centos7整体的知识图谱,但是Centos7目录太多,页面加载不了。D3.js是一个JavaScript库,用于创建数据驱动的文档。所有代码都在一个HTML里,安装VScode里的插件就可以运行。以下是插件:
一、效果图
整体图(图元是圆圈):
整体图文本(图元是文本)
输入etc,会找到所有名为etc的节点。
二、关键代码
1.定义的4个图元
const render_init = function(){
lines = mainsvg.append('g')
.attr('class','lines')
.selectAll('line').data(links).join('line')
.attr('stroke','black')
.attr('stroke-width',1)
.attr('opacity',1); //设置透明度 0-1
// Add text to each line
linetexts = mainsvg.append('g')
.attr('class','linetexts')
.selectAll('text').data(links).join('text')
.text(d => d.relation)
.attr('font-size', 30)
.attr('opacity',0); //设置透明度 0-1
circles = mainsvg.append('g')
.attr('class','circles')
.selectAll('circle').data(nodes).join('circle')
.attr('r',d => (d3.max(nodes, d => d.depth) - d.depth +1)*5)
.attr('title','节点')
.attr('fill',d => color(d.depth))
.attr('name', d => d.name)
.attr('index', d => d.index)
.on('mouseover', mouseover_circles)
.on('mouseout', mouseout_circles)
.call(d3.drag()
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended));
texts = mainsvg.append('g')
.attr('class','texts')
.selectAll('text').data(nodes).join('text')
.attr('fill',d => color(d.depth))
.attr('name', d => d.name)
.attr('font-size', d => (d3.max(nodes, d => d.depth) -d.depth +1)*3)
.text(d => d.name)
.attr('index', d => d.index)
.on('mouseover', mouseover_texts)
.on('mouseout', mouseout_texts)
.call(d3.drag()
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended));
}
2.创建力导向图模拟
simulation = d3.forceSimulation(nodes)
.force('manyBody',d3.forceManyBody().strength(-30))
.force('center', d3.forceCenter(width/2,height/2))
.force("link",d3.forceLink(links).strength(0.1).distance(tdistance))
.on('tick',ticked)
3.模式切换(就是圆和文本两种模式)
$('#mode span').click(function(event) {
// 把mode里面所有span的active全部去掉
// 把被点击的这个设置为active
$('#mode span').removeClass('active')
$(this).addClass('active')
if ($(this).text() == 'Circles') {
// 隐藏所有文本里面的svg元素
// 把node里面的显示出来
$('.texts text').hide();
$('.circles circle').show();
}
else {
$('.texts text').show();
$('.circles circle').hide();
}
});
4.搜索框
// 搜索框
$('#search input').keyup(function(event) {
var name = $(this).val();
var isActive = function(d) {
return d.name.toLowerCase().indexOf(name.toLowerCase()) >= 0 ? '' : 'inactive';
};
// 如果输入为空,全部显示出来
if (name == '') {
d3.selectAll('#svg1 .texts text, #svg1 .circles circle, #svg1 .lines line')
.attr('class', '');
d3.selectAll("#svg1 .linetexts text")
.attr('fill-opacity', 0);
}
else { // 筛选,判断这三个东西里的元素是否包含输入的东西
d3.selectAll('#svg1 .circles circle, #svg1 .texts text')
.attr('class', isActive);
d3.selectAll("#svg1 .lines line")
.attr('class', 'inactive');
d3.selectAll("#svg1 .linetexts text")
.attr('fill-opacity', 0);
}
});
5.鼠标移入移出
移入显示节点和相连的节点以及该节点详细信息。移除恢复到整体图。
function mouseover_circles(event, d) {
if (!dragging) {
var name = d3.select(this).attr('name');
var index = String(d3.select(this).attr('index'));
$('#info h4').css('color',d3.select(this).attr('fill')).text(name);
$('#info p').remove();
$('#info').append('<p><span>Depth:</span> ' + d.depth + '</p>');
//展示ner.json里面的内容
if (typeof(info[index]) != "undefined") {
for (var key in info[index]) {
var value = info[index][key]
var flag_none = false;
for (var item in value) {
if (value[item] == null || value[item] == 'N/A' || value[item] == '') {
flag_none = true;
break;
}
}
if (flag_none == true) { // 排除为空的属性值
continue;
}
$('#info').append('<p><span>' + key + ':</span> ' + info[index][key] + '</p>');
}
}
// Highlight the selected node and its neighbors
const neighbors = links.filter(link => link.source.index === d.index || link.target.index === d.index);
const neighborNodes = neighbors.map(link => link.source.index === d.index ? link.target : link.source);
// Hide all lines and circles
lines.style('opacity', 0);
circles.style('opacity', 0);
linetexts.style('opacity', 0);
// Highlight the selected node and its neighbors
circles.filter(node => node.index === d.index || neighborNodes.includes(node))
.style('opacity', 1);
lines.filter(link => link.source.index === d.index || link.target.index === d.index)
.style('opacity', 1); //opacity 0-1
linetexts.filter(link => link.source.index === d.index || link.target.index === d.index)
.style('opacity', 1);
}
}
// Define the mouseout function to reset the view
function mouseout_circles(event, d) {
if (!dragging) {
// Reset the opacity of all lines and circles
lines.style('opacity', 0.8);
circles.style('opacity', 1);
linetexts.style('opacity', 0);
}
}
三、总结
还有一些其他效果如拖拽、放缩等。代码和数据集我会上传。我后期还会再增加几个功能。