python知识图谱可视化_知识图谱可视化

## 人物关系知识图谱

#### 一、背景

将结构化数据通过关系预处理程序处理为图数据库可以查询的数据,示例是将其中一部分(人物关系数据)可视化表示。

#### 二、用到的技术

技术点:图数据库Neo4j,d3.js,java,css,spring boot

开发工具:IDEA专业版(可找学生账号注册免费使用一年,社区版不支持WEB开发)

#### 三、项目结构以及代码实现过程

实现思路这样:

1,先定义基础的展示页面index.html

2、完成画图js(graph.js)

3,提供一个基础的拿数据接口加载测试绘图数据和绘图需要的数据(例如节点选中之后的小图标加载)

4、页面从数据接口请求数据之后,调用绘图JS在页面完成画图操作(请求数据的接口可以很方便的改为从图数据库拿取数据进行展示)

主要文件目录说明:

>1、data目录

bg.jpg可视化背景图片数据

CircularPartition.json节点圆形分区图工具栏需要加载的数据

test.json可视化需要展示的数据格式

>2、images

此目录存储节点属性图片数据

>3、js

d3.js version-3.2.8

>4、src

JS以及其它HTML等源码

>5、index.html

知识图谱可视化入口文件

>6、拿数据接口

通过数据Type id加载圆形分区图数据和测试知识图谱构图数据(type等于1加载圆形分区数据,type是等于2加载测试知识图谱展示数据)

GET:http://localhost:7476/knowledge-graph/hello/dataSource/type/{id}

做图过程(graph.js):

```

// 定义画布 (radius是鼠标点击生成圆形分区图的半径)

var width = 1345, height = 750, color = d3.scale.category20();

var svg = d3.select("body")

.append("svg")

.attr("id", "svgGraph")

.attr("width", width)

.attr("height", height)

.append("g")

.attr("id", "svgOne")

.call(d3.behavior.zoom() // 自动创建事件侦听器

.scaleExtent([0.1, 10]) // 缩放允许的级数

.on("zoom", zoom)

)

.on("dblclick.zoom", null); // remove双击缩放

```

```

// 实时获取SVG画布坐标

function printPosition() {

var position = d3.mouse(svg.node());

return position;

}

```

```

// 缩放函数

function zoom() {

// translate变换矢量(使用二元组标识)scale当前尺度的数字

svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); // 画布缩放与移动

// svg.attr("transform", "scale(" + d3.event.scale + ")"); // 画布缩放

}

```

```

// 设置连线箭头属性

function setMarkers() {

svg.append("g")

.attr("id", "lineAndText")

.selectAll("marker")

.data(edges)

.enter()

.append("marker")

.attr("id", function (d) {

return d.id;

})

.attr("viewBox", "0 -5 10 10") // 坐标系的区域

.attr("class", "arrow")

.attr("refX", 27) // refX,refY在viewBox内的基准点,绘制时此点在直线端点上(要注意大小写)

.attr("refY", 0)

.attr("markerWidth", 10) // 标识的大小

.attr("markerHeight", 18) // 标识的大小

.attr("markerUnits", "userSpaceOnUse") // 标识大小的基准,有两个值:strokeWidth(线的宽度)和userSpaceOnUse(图形最前端的大小)

.attr("orient", "auto") // 绘制方向,可设定为:auto(自动确认方向)和 角度值

.append("path")

.attr("d", "M0,-5L10,0L0,5")

.attr("fill", "#ccc");

}

```

```

// 添加连线

function add_edges() {

setMarkers(); // 设置连线箭头属性

var svg_edges = svg.select("#lineAndText")

.selectAll("line")

.data(edges)

.enter()

.append("line")

.attr("id", function (d) {

return d.id;

})

.style("stroke", "#ccc")

.style("stroke_width", 1)

.attr("marker-end", function (d) {

return "url(#" + d.id + ")";

})

.attr("stroke", "#999")

.on("mouseover", function (d) { // 鼠标选中时触发

mouseSelectLine(d);

addToolTip(d); //添加提示框的div

})

.on("mouseout", function () {

d3.select("#relation").remove();

d3.select("#tooltip").remove();

});

return svg_edges;

}

```

```

// 求直线与圆的交点

// 函数参数说明:cx:圆X轴坐标 cy:圆y轴坐标 r:圆半径 stx:起点直线的X轴坐标 sty:起点直线的轴坐标 edx:终点直线的X轴坐标 edy:终点直线的Y轴坐标

// 返回值:交点坐标(x,y)

function getPoint(cx, cy, r, stx, sty, edx, edy) {

// 求直线

var k = (edy - sty) / (edx - stx);

var b = edy - k * edx;

//列方程

var x1, y1, x2, y2;

var c = cx * cx + (b - cy) * (b - cy) - r * r;

var a = (1 + k * k);

var b1 = (2 * cx - 2 * k * (b - cy));

var tmp = Math.sqrt(b1 * b1 - 4 * a * c);

x1 = (b1 + tmp) / (2 * a);

y1 = k * x1 + b;

x2 = (b1 - tmp) / (2 * a);

y2 = k * x2 + b;

// 过滤距离最近的坐标

var p = {};

function lineIf(lx, ly, lxx, lyy) {

var d = Math.sqrt((lx - lxx) * (lx - lxx) + (ly - lyy) * (ly - lyy));

return d;

}

if (cx != stx) { // stx, sty

var d1 = lineIf(x1, y1, stx, sty);

var d2 = lineIf(x2, y2, stx, sty);

if (d1 < d2) {

p.x = x1;

p.y = y1;

} else {

p.x = x2;

p.y = y2;

}

} else { // edx, edy

var d1 = lineIf(x1, y1, edx, edy);

var d2 = lineIf(x2, y2, edx, edy);

if (d1 < d2) {

p.x = x1;

p.y = y1;

} else {

p.x = x2;

p.y = y2;

}

}

return p;

}

```

```

// 鼠标选中关系添加显示效果

function mouseSelectLine(d) {

var p1 = getPoint(d.source.x, d.source.y, 20, d.source.x, d.source.y, d.target.x, d.target.y);

var p2 = getPoint(d.target.x, d.target.y, 20, d.source.x, d.source.y, d.target.x, d.target.y);

var json = [p1, p2];

//构造默认线性生成器

var line = d3.svg.line()

.x(function (d) { //指定x存取器为:取每个数据元素的x属性的值

return d.x;

})

.y(function (d) { //指定y存取器为:取每个数据元素的y属性的值

return d.y;

});

svg.append('path')

.attr({

"d": function () { //生成路径数据

return line(json);

},

"id": "relation"

})

.style({

"stroke": "#87CEFA", //path颜色

"stroke-width": 6 //path粗细

});

}

```

```

// 添加节点

function add_nodes() {

var svg_nodes = svg.append("g")

.attr("id", "circleAndText")

.selectAll("circle")

.data(nodes)

.enter()

.append("g")

.call(force.drag().on("dragstart", function (d) {

d3.select("#eee").remove(); // 删除节点扇形

d3.select("#sel").remove(); // 删除节点选中

d3.event.sourceEvent.stopPropagation(); // 画布拖动与节点拖动分离

d3.select(this).attr("r", 20 * 2);

})

.on("dragend", function (d) {

d3.select("#eee").remove(); // 删除节点扇形

d3.select("#sel").remove(); // 删除节点选中

d.fixed = true; // 拖动结束后节点固定

d3.select(this).attr("r", 20);

})

)

.on("click", function (d) { // 鼠标点击时触发

// 在当前节点处画三页扇形

d3.select("#eee").remove();

drawCirclePartition(d);

})

.on("mouseover", function (d) { // 光标放在某元素上s

mouseSelect(d); // 鼠标选中效果

addToolTip(d); //添加提示框的div

})

.on("mouseout", function (d) {

d3.select("#sel").remove(); // 删除节点选中

d3.select("#tooltip").remove();

d3.select("#tooltipCir").remove();

});

svg_nodes.append("circle")

.attr("id", function (d) {

return d.index;

})

.attr("r", 20)

.attr("fill", function (d, i) {

return color(i);

});

svg_nodes.append("image")

.attr("class", "circle")

.attr("xlink:href", function (d) {

var img = d.image;

if (img != undefined) {

return "http://222.216.195.154:7476/knowledge-graph/path/images/" + d.image

} else {

return null;

}

})

.attr("x", "-20px")

.attr("y", "-20px")

.attr("width", "40px")

.attr("height", "40px");

svg_nodes.append("svg:text")

.style("fill", "#ccc")

.attr("dx", 20)

.attr("dy", 8)

.text(function (d) {

return d.name

});

return svg_nodes;

}

```

```

//添加提示框的div

function addToolTip(d) {

var htmlStr;

if (d.source && d.target && d.type) {

htmlStr = "name:" + d.type + "

";

} else {

htmlStr = "id:" + d.id + "

" + "name:" + d.name + "

";

}

var position = printPosition(d);

var tooltip = d3.select("body").append("div")

.attr("class", "tooltip") //用于css设置类样式

.attr("opacity", 0.0)

.attr("id", "tooltip");

htmlStr = htmlStr + "locx:" + position[0] + "

" + "locy:" + position[1] + "

";

if (d.image != undefined) {

htmlStr = htmlStr + "

";

}

tooltip.html(htmlStr)

.style("left", (d3.event.pageX) + "px")

.style("top", (d3.event.pageY + 20) + "px")

.style("opacity", 0.75);

}

function addToolTipCir(d) {

var htmlStr;

if (d.name == "☿") {

htmlStr = "notes:解锁当前节点

";

}

if (d.name == "✂") {

htmlStr = "notes:裁剪当前节点与关系

";

}

if (d.name == "✠") {

htmlStr = "notes:拓展当前节点与关系

";

}

if (d.name == "◎") {

htmlStr = "notes:释放所有锁定的节点

";

}

if (d.name == "오") {

htmlStr = "notes:锁定所有节点

";

}

var tooltip = d3.select("body").append("div")

.attr("class", "tooltip") //用于css设置类样式

.attr("opacity", 0.0)

.attr("id", "tooltipCir");

tooltip.html(htmlStr)

.style("left", (d3.event.pageX) + "px")

.style("top", (d3.event.pageY + 20) + "px")

.style("opacity", 0.75);

}

```

```

// 生成圆弧需要的角度数据

var arcDataTemp = [{startAngle: 0, endAngle: 2 * Math.PI}];

var arc_temp = d3.svg.arc().outerRadius(26).innerRadius(20);

```

```

// 鼠标选中节点添加显示效果

var svg_selectNode;

function mouseSelect(d) {

svg_selectNode = svg.append("g")

.attr("id", "sel")

.attr("transform", "translate(" + d.x + "," + d.y + ")")

.selectAll("path.arc")

.data(arcDataTemp)

.enter()

.append("path")

.attr("fill", "#87CEFA")

.attr("d", function (d, i) {

return arc_temp(d, i);

});

}

```

```

// 全局停止力作用之间的影响

function stopForce() {

for (var i = 0; i < nodes.length; i++) {

var obj = nodes[i];

obj.fixed = true;

}

}

```

```

// 全局开始力作用之间的影响

function startForce() {

for (var i = 0; i < nodes.length; i++) {

var obj = nodes[i];

obj.fixed = false;

}

force.resume();

}

```

```

var nodesMark = [], edgesMark = [], indexNodeMark = []; // 缓存中所有已加载的数据标记

// 节点添加圆形分区(添加三页扇形)

function drawCirclePartition(d) {

// 圆形分区布局(数据转换)

var radius = 40;

var partition = d3.layout.partition()

.sort(null)

.size([2 * Math.PI, radius * radius]) // 第一个值域时2 PI,第二个值时圆半径的平方

.value(function (d) {

return 1;

});

// 绘制圆形分区图

// 如果以圆形的形式来转换数据那么d.x和d.y分别代表圆弧的绕圆心

// 方向的起始位置和由圆心向外的起始位置d.dx和d.dy分别代表各自的宽度

var arc = d3.svg.arc()

.startAngle(function (d) {

return d.x;

})

.endAngle(function (d) {

return d.x + d.dx;

})

.innerRadius(function (d) {

return 26;

})

.outerRadius(function (d) {

return 80;

});

var circlePart = partition.nodes(dataCirclePartition);

// "☿" 释放固定的节点

function releaseNode() {

d.fixed = false;

// force.start(); // 开启或恢复结点间的位置影响

force.resume();

}

// "✂" 删除当前节点以及当前节点到其它节点之间的关系

function removeNode() {

var newNodes = [];

for (var i = 0; i < nodes.length; i++) {

var obj = nodes[i];

if (obj.id != d.id) {

newNodes.push(obj);

}

}

var newedges = [];

for (var i = 0; i < edges.length; i++) {

var obj = edges[i];

if ((d.index != obj.source.index) && (d.index != obj.target.index)) {

newedges.push(obj);

}

}

nodes = newNodes;

edges = newedges;

var nIndex = function (d) {

return d.index;

};

var lIndex = function (d) {

return d.id;

};

// 通过添加'g'元素分组删除

svg.select("#circleAndText").selectAll("circle")

.data(nodes, nIndex)

.exit()

.remove();

svg.select("#circleAndText").selectAll("image")

.data(nodes, nIndex)

.exit()

.remove();

svg.select("#circleAndText").selectAll("text")

.data(nodes, nIndex)

.exit()

.remove();

svg.select("#lineAndText").selectAll("line")

.data(edges, lIndex)

.exit()

.remove();

svg.select("#lineAndText").selectAll("text")

.data(edges, lIndex)

.exit()

.remove();

}

```

```

// 扩展当前节点,距离为1

// 1.从rawData(rawNodes/rawEdges)中找出当前节点需要扩展的节点与关系数据

// 2.拿出需要扩展的数据到node/edges中去除已经绑定图形元素的数据

// 3.将过滤出的未绑定图形元素需要扩展的数据重新调用构图方法进行构图

// 添加从服务器实时加载数据的功能:基本思想与1~3类似

function extendNode() {

var index = d.index;

var arrEdges = [], arrIndex = [], arrNodes = [];

for (var i = 0; i < rawEdges.length; i++) {

if ((index == rawEdges[i].source.index) || (index == rawEdges[i].target.index)) {

arrEdges.push(rawEdges[i]);

if (index != rawEdges[i].source.index) {

arrIndex.push(rawEdges[i].source.index);

} else if (index != rawEdges[i].target.index) {

arrIndex.push(rawEdges[i].target.index);

}

}

edgesMark.push(rawEdges[i].id);

}

for (var i = 0; i < rawNodes.length; i++) {

for (var j = 0; j < arrIndex.length; j++) {

var obj = arrIndex[j];

if (rawNodes[i].index == obj) {

arrNodes.push(rawNodes[i]);

}

}

nodesMark.push(rawNodes[i].id);

indexNodeMark.push(rawNodes[i].index);

}

// nodes.push(arrNodes);

// edges.push(arrEdges);

var nodesRemoveIndex = [];

for (var i = 0; i < arrNodes.length; i++) {

var obj = arrNodes[i];

for (var j = 0; j < nodes.length; j++) {

var obj2 = nodes[j];

if (obj.index == obj2.index) {

nodesRemoveIndex.push(i);

}

}

}

var edgesRemoveIndex = [];

for (var i = 0; i < arrEdges.length; i++) {

var obj = arrEdges[i];

for (var j = 0; j < edges.length; j++) {

var obj2 = edges[j];

if (obj.id == obj2.id) {

edgesRemoveIndex.push(obj.id);

}

}

}

var coverNodes = [];

for (var i = 0; i < arrNodes.length; i++) {

var obj = arrNodes[i];

if (!isInArray(nodesRemoveIndex, i)) {

nodes.push(obj);

coverNodes.push(obj);

}

}

var coverEdges = [];

for (var i = 0; i < arrEdges.length; i++) {

var obj = arrEdges[i];

if (!isInArray(edgesRemoveIndex, obj.id)) {

edges.push(obj);

coverEdges.push(obj);

}

}

// console.log("找出需要扩展的数据");

// console.log(arrEdges);

// console.log(arrNodes);

// console.log("添加到原始需要绑定图形元素的数据集集合/与rawNodes,rawEdges服务器加载的原始数据保持区分");

// console.log(nodes);

// console.log(edges);

// 添加从服务器请求扩展数据

// var url = "http://222.216.195.154:7476/knowledge-graph/hello/dataSource/node/extend/" + d.id + "";

// d3.json(url, function (error, json) { // 服务器加载知识图谱数据

// if (error) {

// return console.warn(error);

// }

// console.log("从服务器请求的扩展数据:");

// var serverNodes = json.nodes;

// var serverEdges = json.links;

// console.log(serverNodes);

// console.log(serverEdges);

// console.log(nodesMark);

// console.log(edgesMark);

// // 重新设置INDEX

// var maxIndex = Math.max.apply(null, indexNodeMark);

// console.log("MAX:" + maxIndex);

//

// for (var i = 0; i < serverNodes.length; i++) {

// if (!isInArray(nodesMark, serverNodes[i].id)) {

// serverNodes[i].index = maxIndex + 1

// maxIndex = maxIndex + 1;

// nodes.concat(serverNodes[i]);

// console.log(serverNodes[i]);

// }

// }

// for (var i = 0; i < serverEdges.length; i++) {

// if (!isInArray(edgesMark, serverEdges[i].id)) {

// edges.concat(serverEdges);

// console.log(serverEdges[i]);

// }

// }

// console.log("服务器加载并且合并之后的数据:");

// console.log(nodes);

// console.log(edges);

// d3.select("#svgGraph").select("#svgOne").selectAll("*").remove(); // 清空SVG中的内容

// buildGraph();

// });

d3.select("#svgGraph").select("#svgOne").selectAll("*").remove(); // 清空SVG中的内容

buildGraph();

}

var arcs = svg.append("g")

.attr("id", "eee")

.attr("transform", "translate(" + d.x + "," + d.y + ")")

.selectAll("g")

.data(circlePart)

.enter()

.append("g")

.on("click", function (d) { // 圆形分区绑定Click事件

if (d.name == "☿") {

releaseNode();

}

if (d.name == "✂") {

removeNode();

}

if (d.name == "✠") {

extendNode();

}

if (d.name == "◎") {

startForce();

}

if (d.name == "오") {

stopForce();

}

d3.select("#eee").remove();

d3.select("#tooltipCir").remove();

});

arcs.append("path")

.attr("display", function (d) {

return d.depth ? null : "none"; // hide inner ring

})

.attr("d", arc)

.style("stroke", "#fff")

.style("fill", "#A9A9A9")

.on("mouseover", function (d) {

d3.select(this).style("fill", "#747680");

addToolTipCir(d); //添加提示框的div

})

.on("mouseout", function () {

d3.select("#tooltipCir").remove();

d3.select(this).transition()

.duration(200)

.style("fill", "#ccc")

var array = printPosition();

var distance = Math.sqrt(Math.pow((d.x - array[0]), 2) + Math.pow((d.y - array[1]), 2));

if (distance > 80) {

d3.select("#eee").remove(); // 删除节点扇形

}

});

arcs.append("text")

.style("font-size", "16px")

.style("font-family", "simsun")

.style("fill", "white")

.attr("text-anchor", "middle")

.attr("transform", function (d, i) {

// 平移和旋转

var r = 0;

if ((d.x + d.dx / 2) / Math.PI * 180 < 180) // 0-180度以内的

r = 180 * ((d.x + d.dx / 2 - Math.PI / 2) / Math.PI);

else // 180-360度

r = 180 * ((d.x + d.dx / 2 + Math.PI / 2) / Math.PI);

return "translate(" + arc.centroid(d) + ")" + "rotate(" + r + ")";

})

.text(function (d) {

return d.name;

});

return arcs;

}

```

```

// 添加描述关系文字

function add_text_edges() {

var svg_text_edges = svg.select("#lineAndText")

.selectAll("line.text")

.data(edges)

.enter()

.append("text")

.attr("id", function (d) {

return d.id;

})

.style("fill", "#ccc")

.attr("x", function (d) {

return (d.source.x + d.target.x) / 2

})

.attr("y", function (d) {

return (d.source.y + d.target.y) / 2

})

.text(function (d) {

return d.type;

})

.on("mouseover", function (d) { // 鼠标选中时触发

mouseSelectLine(d);

addToolTip(d); //添加提示框的div

})

.on("mouseout", function () {

d3.select("#relation").remove();

d3.select("#tooltip").remove();

})

.on("click", function () {

});

return svg_text_edges;

}

```

```

// 对于每一个时间间隔进行更新

function refresh() {

force.on("tick", function () { // 对于每一个时间间隔

// 更新连线坐标·

svg_edges.attr("x1", function (d) {

return d.source.x;

})

.attr("y1", function (d) {

return d.source.y;

})

.attr("x2", function (d) {

return d.target.x;

})

.attr("y2", function (d) {

return d.target.y;

});

// 更新节点以及文字坐标

svg_nodes.attr("transform", function (d) {

return "translate(" + d.x + "," + d.y + ")";

});

// 更新关系文字坐标

svg_text_edges.attr("x", function (d) {

return (d.source.x + d.target.x) / 2

})

.attr("y", function (d) {

return (d.source.y + d.target.y) / 2

});

});

}

```

```

var force, nodes = [], edges = [], rawNodes, rawEdges, mapNodes = new Map(); // 构建知识图谱需要操作的数据 (rawNodes, rawEdges将加载的原始构图数据缓存一份)

// 知识图谱可视化构建

function graph(data) {

// 先清空布局中的图形元素

// d3.select("#svgGraph").select("#svgOne").selectAll("*").remove();

// var serverD = data.nodes;

// var serverE = data.links;

// 去除NODES中重复的节点,如果有节点重复即将EDGES中的数据重新设置source值和target值

// serverD,serverE,nodes,edges

// var filterServerD = [];

// for (var i = 0; i < serverD.length; i++) {

// if (!isInArray(nodesIndexId, serverD[i].id)) {

// filterServerD.push(serverD[i]);

// }

// }

// 去重之后重新调整filterServerD的NODE index值

// mapNodes.forEach(function (value, key) {

// console.log(value);

// console.log(key);

// if (isInArray(nodesIndexId,key)){

//

// }

// });

// recordNodesIndex(serverD);

// console.log(nodesIndexValue);

// 多数组连接

// nodes = nodes.concat(data.nodes);

// edges = edges.concat(data.links);

// console.log(nodes);

// console.log(edges);

// rawNodes = nodes;

// rawEdges = edges;

// // 定义力布局(数据转换)

// force = d3.layout.force()

// .nodes(nodes) // 指定节点数组

// .links(edges) // 指定连线数组

// .size([width, height]) // 指定范围

// .linkDistance(150) // 指定连线长度

// // .gravity(0.02) // 设置引力避免跃出布局

// .friction(0.9) // 设置摩擦力速度衰减

// .charge(-400); // 相互之间的作用力

// force.start(); // 开始作用

// buildGraph();

}

```

```

var svg_edges, svg_nodes, svg_text_edges; // 需要动态更新的函数(dynamic update function)

// Strat build Knowledge Graph/Vault

function buildGraph() {

console.log("开始构建可视化知识图谱:");

console.log(nodes);

console.log(edges);

svg_edges = add_edges(); // 添加连线与箭头

svg_nodes = add_nodes(); // 添加节点与文字

svg_text_edges = add_text_edges(); // 添加描述关系的文字

refresh(); // 对于每一个时间间隔进行更新

force.resume(); // 必须添加否则图形元素更新不及时

}

```

```

// 服务器加载数据

var dataCirclePartition;

function load() {

d3.json("http://222.216.195.154:7476/knowledge-graph/hello/dataSource/type/1", function (error, root) { // 服务器加载节点圆形分区数据

if (error) {

return console.warn(error);

}

dataCirclePartition = root;

});

d3.json("http://222.216.195.154:7476/knowledge-graph/hello/dataSource/type/2", function (error, json) { // 服务器加载知识图谱数据

if (error) {

return console.warn(error);

}

console.log("初始加载:");

console.log(json.nodes);

console.log(json.links);

graph(json);

});

// d3.json("http://222.216.195.154:7476/knowledge-graph/hello/dataSource/node/extend/99817", function (error, json) { // 服务器加载知识图谱数据

// if (error) {

// return console.warn(error);

// }

// console.log("初始加载:");

// console.log(json);

// graph(json);

// });

}

// 初始化图数据库配置信息

startNeo4j();

// 执行知识图谱数据可视化

load();

// 传入NODE ID与NODE INDEX,节点的INDEX与构图时数据加载的顺序密切相关

function loadById(id, maxNodeIndex, nodesIdList) {

// var para = ["id:" + id, "maxNodeIndex:" + maxNodeIndex, "nodesIdList:" + nodesIdList];

var para = {"id": id, "maxNodeIndex": maxNodeIndex, "nodesIdList": nodesIdList};

console.log(para);

d3.json("http://222.216.195.154:7476/knowledge-graph/hello/dataSource/node/idIndex/" + para, function (error, data) { // 服务器加载知识图谱数据

if (error) {

return console.warn(error);

}

console.log("动态ID加载的数据:");

console.log(nodesMark);

console.log(edgesMark);

console.log(nodes);

console.log(edges);

console.log(data);

graph(data);

});

}

function loadZdrSearch(json) {

d3.json("http://222.216.195.154:7476/knowledge-graph/hello/dataSource/type/1", function (error, root) { // 服务器加载节点圆形分区数据

if (error) {

return console.warn(error);

}

dataCirclePartition = root;

});

graph(json);

}

// 执行知识图谱数据可视化

// loadById(id);

```

启动入口类KnowledgeGraphApplication之后,

调用接口:http://localhost:7476/knowledge-graph/hello/index

此接口调用控制类加载index.html,HTML中调用了js文件加载展示数据,详细的实现过程请看完整的代码注释。

>代码目录结构说明一:

![代码目录结构说明](/contentImages/image/20180708/1NODaHkjOQEv1cSUoil.png)

>代码目录结构说明二:

![代码目录结构说明](/contentImages/image/20180708/URaahjGrTTzIC2iqcxV.png)

#### 四、可视化效果(所有可视化效果均带有力布局效果)

######1.节点与关系均带有选中效果,节点关系裁剪与扩展

☿解锁当前节点

✂ 剪切当前节点于关系

✠ 扩展当前节点与关系

오 固定所有节点

◎ 解锁所有节点

>实体扩展功能:

![实体扩展功能](/contentImages/image/20180708/8dvzXzSMkz65KW1OFsd.png)

>节点效果:

![节点效果](/contentImages/image/20180708/o8Xhzc2DYLoNXfIzbMY.png)

######2.完整示例

>完整效果显示示例一:

![完整示例](/contentImages/image/20180708/WowrmiblqPuogs6Wwgt.png)

>完整效果显示示例二:

![](/contentImages/image/20180708/oosOoMBoeFcRGIKem79.png)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/409717.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[html] 编写一个布局,让文字环绕在图片的周围

[html] 编写一个布局&#xff0c;让文字环绕在图片的周围 让图片 float 就可以了&#xff0c;如果还想要实现文字圆形环绕图片的效果&#xff0c;可以使用 shape-outside: circle(); 属性个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c;…

[html] input上传文件可以同时选择多张吗?怎么设置?

[html] input上传文件可以同时选择多张吗&#xff1f;怎么设置&#xff1f; <input type"file" multiple />个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关…

My97DatePicker详细说明

js 时间插件 http://www.mysuc.com/test/My97DatePicker/#m311转载于:https://www.cnblogs.com/guyg/archive/2012/07/06/2579623.html

hsv白色h值是多少_ShaderToy系列:HSV

前言这次呢&#xff0c;继续再来看一个iq大神的简单作品&#xff0c;作品虽简单&#xff0c;但是却包含了很多知识点&#xff0c;先放上最终效果&#xff1a;ShaderToy地址&#xff1a;https://www.shadertoy.com/view/MsS3Wc不过本篇改动较大&#xff0c;最终效果与ShaderToy上…

saltstack mysql_saltstack学习五:return及入库_MySQL

return的用法网上太多资料了&#xff0c;利用return把结果存入数据库网上已经有现在的&#xff1a;1、在master端创建数据库&#xff1a;CREATE DATABASE saltDEFAULT CHARACTER SET utf8DEFAULT COLLATE utf8_general_ci;USE salt;---- Table structure for table jids--DROP …

[html] input上传图片怎样触发默认拍照功能

[html] input上传图片怎样触发默认拍照功能 使用 capture 属性&#xff0c;capture 的值可以是&#xff1a;camera 打开摄像头user 打开前置摄像头environment 打开后置摄像头以上几个属性都不能保证设备会按照设置的一样打开前置或后置摄像头&#xff0c;如果设备不支持的话&…

|DataDirectory|的使用

Ado.net2.0中新增加了一个MagicValue,可以在应用程序的配置文件的数据库链接串种使用|DataDirectory| ,例如: <connectionStrings><add name"ConnectionString"connectionString"data source.;Integrated SecuritySSPI;AttachDBFilename|DataDirector…

腾讯云对象存储 python_python 云存储

广告关闭云服务器1核2G首年99年&#xff0c;还有多款热门云产品满足您的上云需求存储桶 bucketxml python sdk 存储桶名称由两部分组成&#xff1a;用户自定义字符串 和 appid&#xff0c;两者以中划线“-”相连。 例如 mybucket1-1250000000&#xff0c;其中 mybucket1 为用户…

mysql php 入门_PHP入门教程之PHP操作MySQL的方法分析

本文实例讲述了PHP操作MySQL的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;设置Zend 软件所有 UTF-8 编码设置单个项目 UTF-8 的编码Demo1.phpheader(Content-Type:text/html; charsetutf-8;);//第一步&#xff0c;连接到 Mysql 服务器 3306//第二步参数&#…

[html] 举例说明Shadow DOM的应用场景有哪些?

[html] 举例说明Shadow DOM的应用场景有哪些&#xff1f; 可以将 shadow DOM 视为“DOM中的DOM”。它是自己独立的DOM树&#xff0c;具有自己的元素和样式&#xff0c;与原始DOM完全隔离。可以应用在组件中。个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃…

Spring in Action 3 (翻译)

第一部分 Spring的核心 用Spring我们可以做很多工作。但是当你取其核心时你会发现&#xff0c;Spring最主要的特征就是依赖注入-DI&#xff08;Dependency Injection&#xff09;和面向切面编程-AOP&#xff08;Aspect Oriented Programming&#xff09;。在第一章“开始Sprin…

and or not 优先级_快速划分测试用例优先级

在工程工期时间有限的情况下&#xff0c;怎么解决测试工期和全部测试用例执行时间之间的矛盾呢&#xff1f;怎么样的设计才能算测试用例引自:IEEE Standard 610 (1990):A set of test inputs, execution conditions, and expected results developed for a particular objectiv…

Mysql索引是有序的吗_mysql组合索引的有序性转

昨天同事关于军规里的一条mysql索引的问题咨询我&#xff0c;才发现自己也不太了解组合索引的规则。于是来记录一下&#xff1a;【推荐】如果有order by的场景&#xff0c;请注意利用索引的有序性。order by 最后的字段是组合索引的一部分&#xff0c;并且放在索引组合顺序的最…

工作405-关于vue组件开发过程中一直报错:This relative module was not found:

问题描述 在项目过程中&#xff0c;当我在路由映射表中添加url和对应组件时一直报This relative module was not found:这样的错误。检查了十几遍发现组件创建&#xff0c;导出&#xff0c;引入都没错&#xff0c;一时间心态崩了。 最后问题的解决 在看了二十几遍后才发现原来…

地址和指针的概念

地址和指针的概念转载于:https://www.cnblogs.com/LoveFishC/archive/2012/07/23/3846506.html

工作406- Error:Node Sass version 5.0.0 is incompatible with ^4.0.0 问题解决

Error:Node Sass version 5.0.0 is incompatible with ^4.x 问题解决 此错误来自sass-loader.因为node-sasslatest为v5.0.0,而sass-loader期望值为^4.0.0 目前解决方案如下&#xff1a; //卸载 node-sass npm uninstall node-sass //然后安装最新版本&#xff08;5.0之前&…

keil写文字怎么会乱码_主持稿怎么写才会吸引人

现在你是不是想要知道一个主持人它是怎么样把我们都吸引到节目当中来的&#xff0c;当然就是靠的主持稿了&#xff0c;那这个时候你就想要知道了&#xff0c;它应该要怎么写才会吸引人呢&#xff0c;最主要的一点就是需要我们一来就先声夺人&#xff0c;很多的优秀主持人都会这…

dropdownlist三级联动怎么实现_一张表实现三级联动

今天是七夕&#xff0c;七夕快乐&#xff0c;大家今天有没有人约呢&#xff1f;相信大部分的Access玩家都是玩Excel的高手&#xff0c;很多的功能在Excel中实现对大家来说都是小菜&#xff0c;比如今天要讲的联动。那么&#xff0c;我们现在就来讲一下在Access中怎么用一张表实…

Windows Phone开发(29):隔离存储C 转:http://blog.csdn.net/tcjiaan/article/details/7447469...

本文是隔离存储的第三节&#xff0c;大家先喝杯咖啡放松&#xff0c;今天的内容也是非常简单&#xff0c;我们就聊一件东东——用户设置。当然了&#xff0c;可能翻译为应用程序设置合适一些&#xff0c;不过没关系&#xff0c;只要大家明白&#xff0c;它就是用于保存我们的应…

工作407-启动vue项目出现Module build failed (from ./node_modules/sass-loader/dist/cjs.js): ValidationError: I

This dependency was not found:* !!vue-style-loader!css-loader?{"sourceMap":true}!../../node_modules/vue-loader/lib/style-compiler/index?{"vue":true,"id":"data-v-ef68022e","scoped":true,"hasInlineConf…