可视化新闻案例案例在哪里查询

七个经典可视化案例,展示数据思维
七个经典可视化案例,展示数据思维
图表是一种美观而强大的工具,可以帮助我们探索和诠释这个世界。数百年来,人们一直在使用图表来解释跟数据相关的种种。为了向数据可视化的历史和图表的力量致敬,我们重新制作了史上最具代表性的7张图表。
这其中一部分是用现代的方法呈现出原稿,而另一些则致力于对原图的重新制作。
图表是一种美观而强大的工具,可以帮助我们探索和诠释这个世界。数百年来,人们一直在使用图表来解释跟数据相关的种种。为了向数据可视化的历史和图表的力量致敬,我们重新制作了史上最具代表性的7张图表。
这其中一部分是用现代的方法呈现出原稿,而另一些则致力于对原图的重新制作。这项工程由Edward Tufte发起。他是一位数据可视化的专家,已经对这些以及更多的图表写过相关文章。
1. 俄法战争
1969年,Charles Minard做了一张图表,是1812年拿破仑率军攻占莫斯科的行军图,显示了军队规模的缩减。在顶端较粗的线代表了从波兰到莫斯科的行军规模变化。下方的细深色线则代表了撤退时的军队规模。线条的宽度代表了军队的规模,从400000大军缩减到了10000。底部线条是温度和时间刻度,而整个图形分布展示了行军距离。
下方是我们的现代视图。我们也可以做一个更为准确的复刻。中间的分界线代表莫斯科。蓝色的线表示温度随右侧Y轴的变化。底部的X轴则表示日期和距离。我们也可以使用一个自定义的日期格式。拖动鼠标会看到数据。D3.js带来这种交互性。也可单击并拖动缩放。
2. 约翰·雪诺(John Snow)和霍乱案例
下方是约翰·雪诺的地图,展示了1854年伦敦霍乱爆发时的发病源头。线条代表街道。黑色的长条代表了所在街区死亡的人数。圆点代表抽水泵。特别注意在宽街 (Broad Street)上的抽水泵周围的死亡人数相对集中。雪诺用他的这幅地图佐证了他极富争议的理论:霍乱是由被污染的引用水传播开来的。当政府关闭了宽街上的水泵,霍乱的蔓延也平息了。引发霍乱的病菌最终由德国物理学家罗伯特·科赫(Robert Koch)在1883年分离出来。
我们重制了这张图表,用蓝色半透明方块来表示死亡人数。 沿着灰色街道的深色块表示多人死亡。星形表示抽水泵。图中的多边形展现了基于抽水泵区域而分布的死亡人群分布:即最近的打水区域。最右侧的区域超出了地图绘制的范围。如果你将鼠标放在某个抽水泵图标上,你就可以看到这个区域内的死亡人数。放大图像则可以展开某一个群组看到详细数据。
3. 死亡原因极坐标图
弗洛伦斯·南丁格尔(Florence Nightingale)是一位著名的英国社会改革者和统计学家。她是皇家统计学会的第一位女性成员,是使用极坐标图的先驱。当向国会展示她的研究成果时,南丁格尔使用区块来解释克里米亚战争。她的区块显示了在年间克里米亚战争中人们死亡的原因。
史蒂芬(Stephen Few)在《把饼状图留给甜点》(“Save the Pies for Dessert”)一文中提到,由于饼状图不是并排展示,会使得比较规模和数值变得困难。这样的问题在极坐标图中同样存在。为了大家更好的理解,我们在Plotly中用python将她的图表录入,然后使用堆积柱状图来解决比较问题。
地图应该是最早形式的图表。下面的地图分别由马丁·瓦尔德泽米勒(Martin Waldseemüller)在1507年,亚伯拉罕·奥特柳斯(Abraham Ortelius)在1570年和伊曼纽尔-鲍文(EmanuelBowen)在1744年制作完成的。
Plotly的创建人切尔西(Chelsea Lyn)用MATLAB的3Dglobe绘制地图,展示了国家、水域、经纬度和飞行轨迹。如果你点击、长按或拖动图像,图像可被翻动和旋转。切换图像的缩放比例可以看到详细数据。
(编者注:交互效果请前往原网页查看→ https://plot.ly/~chelsea_lyn/2170/land-rivers-paris-to-new-york-city-hong-kong-london-los-angeles-to-tokyo-longitu/)
5. 汉斯·罗斯林(HansRosling)
汉斯o罗斯林是Gapminder(注:一个在线互动图表数据平台)的创办人之一,他制作了气泡图来展示每个国家四个维度的变量指标:平均寿命(y轴),GDP(x轴),七大洲(颜色)和人口数量(气泡大小)。
以下是利用Plotly绘制的。你可以通过悬停鼠标来查看数据,切换图例的轨迹,或通过点击和拖拽来缩放展示比例。获取更多信息,可查看我们基于python创建图表的教程或者网页版教程,Plotly也能进行流式数据处理。
6. Anscombe四图:为什么要制作图表
Anscombe四图展示了弗朗西斯·安斯库姆(Francis Anscombe)在1973年构造的四组数据集。数据集具有相同的线性回归参数,x、y均值,x、y方差和Pearson相关系数(精确到两位小数)。《Nature》中的一篇文章重新发布了该数据集并绘制成如下图表。
关键点是:仅仅只有统计数据会变得混淆杂乱和不完整。图表能让我们更好的理解数据。可通过阅读ggplot2和matplotlib文档去了解和制作subplots,同时可通过以往关于Anscombe主题的文章进行学习。
7. 进口量&出口量折线图
威廉·普莱费尔(WilliamPlayfair,)是一位苏格兰的工程师和政治经济学家。他发明了折线图,条形图,饼图和扇形图。他通过绘制以下轨迹图展示英国从进口量大于出口量到出口量大于进口量的时间点。
以下是利用plotly绘制的,其中y轴是对数值。
原文发布时间为:
本文来自云栖社区合作伙伴“大数据文摘”,了解相关信息可以关注“BigDataDigest”微信公众号
用云栖社区APP,舒服~
【云栖快讯】Apache旗下顶级开源盛会 HBasecon Asia 2018将于8月17日在京举行,现场仅600席,免费赠票领取入口&&
文章3252篇
专精于业务数据与地理信息融合的大数据可视化,通过图形界面轻松搭建专业的可视化应用, 满足您日...
支持以数据库为核心的结构化存储产品之间的数据传输。 它是一种集数据迁移、数据订阅及数据实时同...
大数据开发套件(Data IDE),提供可视化开发界面、离线任务调度运维、快速数据集成、多人...
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效...
阿里云总监课正式启航知识图谱可视化 - demo例子集 - 博客园
随笔 - 409, 文章 - 0, 评论 - 5, 引用 - 0
代码地址如下:
人物关系知识图谱
将结构化数据通过关系预处理程序处理为图数据库可以查询的数据,示例是将其中一部分(人物关系数据)可视化表示。
二、用到的技术
技术点:图数据库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可视化需要展示的数据格式
此目录存储节点属性图片数据
d3.js version-3.2.8
JS以及其它HTML等源码
5、index.html
知识图谱可视化入口文件
6、拿数据接口
通过数据Type id加载圆形分区图数据和测试知识图谱构图数据(type等于1加载圆形分区数据,type是等于2加载测试知识图谱展示数据)
做图过程(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());
// 缩放函数
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)
.append("marker")
.attr("id", function (d) {
.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)
.append("line")
.attr("id", function (d) {
.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_
// 求直线与圆的交点
// 函数参数说明: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 *
var x1, y1, x2, y2;
var c = cx * cx + (b - cy) * (b - cy) - 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 +
x2 = (b1 - tmp) / (2 * a);
y2 = k * x2 +
// 过滤距离最近的坐标
var p = {};
function lineIf(lx, ly, lxx, lyy) {
var d = Math.sqrt((lx - lxx) * (lx - lxx) + (ly - lyy) * (ly - lyy));
if (cx != stx) { // stx, sty
var d1 = lineIf(x1, y1, stx, sty);
var d2 = lineIf(x2, y2, stx, sty);
if (d1 & d2) {
} else { // edx, edy
var d1 = lineIf(x1, y1, edx, edy);
var d2 = lineIf(x2, y2, edx, edy);
if (d1 & d2) {
// 鼠标选中关系添加显示效果
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')
"d": function () { //生成路径数据
return line(json);
"id": "relation"
"stroke": "#87CEFA",
//path颜色
"stroke-width": 6 //path粗细
// 添加节点
function add_nodes() {
var svg_nodes = svg.append("g")
.attr("id", "circleAndText")
.selectAll("circle")
.data(nodes)
.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 = // 拖动结束后节点固定
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) {
.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.
if (img != undefined) {
return "http://222.216.195.154:7476/knowledge-graph/path/images/" + d.image
.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_
//添加提示框的div
function addToolTip(d) {
if (d.source && d.target && d.type) {
htmlStr = "name:" + d.type + "&br/&";
htmlStr = "id:" + d.id + "&br/&" + "name:" + d.name + "&br/&";
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] + "&br/&" + "locy:" + position[1] + "&br/&";
if (d.image != undefined) {
htmlStr = htmlStr + "&img src=\"http://222.216.195.154:7476/knowledge-graph/path/images/" + d.image + "\" height=\"100\" width=\"100\" /&";
tooltip.html(htmlStr)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY + 20) + "px")
.style("opacity", 0.75);
function addToolTipCir(d) {
if (d.name == "?") {
htmlStr = "notes:解锁当前节点&br/&";
if (d.name == "?") {
htmlStr = "notes:裁剪当前节点与关系&br/&";
if (d.name == "?") {
htmlStr = "notes:拓展当前节点与关系&br/&";
if (d.name == "◎") {
htmlStr = "notes:释放所有锁定的节点&br/&";
if (d.name == "?") {
htmlStr = "notes:锁定所有节点&br/&";
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_selectN
function mouseSelect(d) {
svg_selectNode = svg.append("g")
.attr("id", "sel")
.attr("transform", "translate(" + d.x + "," + d.y + ")")
.selectAll("path.arc")
.data(arcDataTemp)
.append("path")
.attr("fill", "#87CEFA")
.attr("d", function (d, i) {
return arc_temp(d, i);
// 全局停止力作用之间的影响
function stopForce() {
for (var i = 0; i & nodes. i++) {
var obj = nodes[i];
obj.fixed =
// 全局开始力作用之间的影响
function startForce() {
for (var i = 0; i & nodes. i++) {
var obj = nodes[i];
obj.fixed =
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) {
// 绘制圆形分区图
// 如果以圆形的形式来转换数据那么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.
.innerRadius(function (d) {
return 26;
.outerRadius(function (d) {
return 80;
var circlePart = partition.nodes(dataCirclePartition);
// "?" 释放固定的节点
function releaseNode() {
// force.start(); // 开启或恢复结点间的位置影响
force.resume();
// "?" 删除当前节点以及当前节点到其它节点之间的关系
function removeNode() {
var newNodes = [];
for (var i = 0; i & nodes. i++) {
var obj = nodes[i];
if (obj.id != d.id) {
newNodes.push(obj);
var newedges = [];
for (var i = 0; i & edges. i++) {
var obj = edges[i];
if ((d.index != obj.source.index) && (d.index != obj.target.index)) {
newedges.push(obj);
nodes = newN
var nIndex = function (d) {
var lIndex = function (d) {
// 通过添加'g'元素分组删除
svg.select("#circleAndText").selectAll("circle")
.data(nodes, nIndex)
.remove();
svg.select("#circleAndText").selectAll("image")
.data(nodes, nIndex)
.remove();
svg.select("#circleAndText").selectAll("text")
.data(nodes, nIndex)
.remove();
svg.select("#lineAndText").selectAll("line")
.data(edges, lIndex)
.remove();
svg.select("#lineAndText").selectAll("text")
.data(edges, lIndex)
.remove();
// 扩展当前节点,距离为1
// 1.从rawData(rawNodes/rawEdges)中找出当前节点需要扩展的节点与关系数据
// 2.拿出需要扩展的数据到node/edges中去除已经绑定图形元素的数据
// 3.将过滤出的未绑定图形元素需要扩展的数据重新调用构图方法进行构图
// 添加从服务器实时加载数据的功能:基本思想与1~3类似
function extendNode() {
var index = d.
var arrEdges = [], arrIndex = [], arrNodes = [];
for (var i = 0; i & rawEdges. 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. i++) {
for (var j = 0; j & arrIndex. 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. i++) {
var obj = arrNodes[i];
for (var j = 0; j & nodes. j++) {
var obj2 = nodes[j];
if (obj.index == obj2.index) {
nodesRemoveIndex.push(i);
var edgesRemoveIndex = [];
for (var i = 0; i & arrEdges. i++) {
var obj = arrEdges[i];
for (var j = 0; j & edges. j++) {
var obj2 = edges[j];
if (obj.id == obj2.id) {
edgesRemoveIndex.push(obj.id);
var coverNodes = [];
for (var i = 0; i & arrNodes. i++) {
var obj = arrNodes[i];
if (!isInArray(nodesRemoveIndex, i)) {
nodes.push(obj);
coverNodes.push(obj);
var coverEdges = [];
for (var i = 0; i & arrEdges. 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.
var serverEdges = json.
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. 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. 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)
.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) {
// 添加描述关系文字
function add_text_edges() {
var svg_text_edges = svg.select("#lineAndText")
.selectAll("line.text")
.data(edges)
.append("text")
.attr("id", function (d) {
.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) {
.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_
// 对于每一个时间间隔进行更新
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.
// var serverE = data.
// 去除NODES中重复的节点,如果有节点重复即将EDGES中的数据重新设置source值和target值
// serverD,serverE,nodes,edges
// var filterServerD = [];
// for (var i = 0; i & serverD. 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 =
// rawEdges =
// // 定义力布局(数据转换)
// 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_ // 需要动态更新的函数(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 dataCircleP
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 =
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();
// 执行知识图谱数据可视化
// 传入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 =
graph(json);
// 执行知识图谱数据可视化
// loadById(id);
启动入口类KnowledgeGraphApplication之后,
调用接口:
此接口调用控制类加载index.html,HTML中调用了js文件加载展示数据,详细的实现过程请看完整的代码注释。
代码目录结构说明一:
代码目录结构说明二:
四、可视化效果(所有可视化效果均带有力布局效果)
1.节点与关系均带有选中效果,节点关系裁剪与扩展
? 解锁当前节点
? 剪切当前节点于关系
? 扩展当前节点与关系
? 固定所有节点
◎ 解锁所有节点
实体扩展功能:
2.完整示例
完整效果显示示例一:
完整效果显示示例二:
知识图谱可视化
代码地址如下:
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

我要回帖

更多关于 大数据可视化案例 的文章

 

随机推荐