目录
数据可视化
一、HTML基础
1、什么是 HTML?
2、了解HTML
二、Javascript可视化基础
1、Javascript直方图
2、树与文字树
三、D3基础篇
1、直方图
2、环图
四、D3重点篇
1、力导向图可视化
2、连接数据库
数据可视化
一、HTML基础
1、什么是 HTML?
1.1、HTML 是用来描述网页的一种语言。
- HTML 指的是超文本标记语言 (Hyper Text Markup Language)
- HTML 不是一种编程语言,而是一种标记语言 (markup language)
- 标记语言是一套标记标签 (markup tag)
- HTML 使用标记标签来描述网页
2.2、HTML 文档 = 网页
- HTML 文档描述网页
- HTML 文档包含 HTML 标签和纯文本
- HTML 文档也被称为网页
Web 浏览器的作用是读取 HTML 文档,并以网页的形式显示出它们。
2、了解HTML
- <html> 与 </html> 之间的文本描述网页
- <body> 与 </body> 之间的文本是可见的页面内容
什么是SVG?
- SVG 指可伸缩矢量图形 (Scalable Vector Graphics)
- SVG 用于定义用于网络的基于矢量的图形
- SVG 使用 XML 格式定义图形
- SVG 图像在放大或改变尺寸的情况下其图形质量不会有损失
- SVG 是万维网联盟的标准
HTML推荐的学习网站:W3C
二、Javascript可视化基础
1、Javascript直方图
1.1、添加矩形
回想一下,我们平常是用什么来表示直方图的呢?
一组矩形。
那么在JavaScript里是不是同样的,也可以一组来表示呢?当然可以!
第一步,画直方图首先要准备一张“纸”。也就是HTML里的SVG——准备画布。
var w = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;//设置svg的width(三种是为了使不同的web浏览器都可以识别)
var h = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;//同样的,设置svg的height。
var svg = document.getElementById("mysvg");
svg.setAttribute("width", w);
svg.setAttribute("height", h);
第二步,添加矩形。SVG提供了<circle>、<ellipse>、<line>、< polyline>、<rect>、<polygon>等6种基本的图形元素和<path>路径元素。可以对各种类型的几何图元进行描述。 我们使用下面的代码来添加一组表示矩形元素的变量。
var rect = new Array(10);
然后我们需要用函数createElement()来将rect中的每一个变量添加到svg的元素中。
for(var i=0;i<10;i++)
{
rect[i]=document.createElement("rect");
svg.appendChild(rect[i]);
}
添加了矩形元素之后,我们再添加一组矩形高度的变量来来表示直方图的数据。
var height=[387, 361.02, 276.7, 250.19, 250.02, 201.7, 177.16, 161.05, 156.16, 148.17];
第三步,将矩形元素在网页上显示。我们使用outerHTML,获取元素内的html内容和文本,并显示在网页上。
for(var i=0;i<rect.length;i++)
{
rect[i].outerHTML = "<rect x=" + (i * w / rect.length) + " y=" + (h - height[i]) + " width=" +(0.9 * w / rect.length) + " height=" + height[i] + ">";
}
设置矩形的x、y坐标、宽度和高度。要注意的是,html的坐标(0,0)是在网页的左上角。代码里写的是(h-height[i]),是为了让每个矩形的底部位于同一水平线上,符合常规认知。
实施以上步骤,画出的图如下所示:
接下来,我们可以给直方图加以润色。在rect标签中添加fill属性来给直方图“上色”。
显示数据:添加一组text标签,显示直方图的数据
for(var i=0;i<rect.length;i++)
{
txt[i].outerHTML = "<text x=" + (i * w / rect.length + 10) + " y=" + (h - height[i] - 10) + ">" + height[i] + "</text>";
}
这里没有截取完整
直方图实例代码:
<html>
<head>
<title>
直方图
</title>
</head>
<body>
<h1 style="text-align:center">2020年全国城市GDP排名(1-10)</h1>
<h3 style="text-align:right">单位:十亿</h3>
<svg id="mysvg">
</svg>
<script>
var w = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;//设置svg的width(三种是为了使不同的web浏览器都可以识别)
var h = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;//同样的,设置svg的height。
var svg = document.getElementById("mysvg");
svg.setAttribute("width", w);
svg.setAttribute("height", h);
var rect = new Array(10);
var txt = new Array(10);
var height = [387, 361.02, 276.7, 250.19, 250.02, 201.7, 177.16, 161.05, 156.16, 148.17];
for(var i=0;i<rect.length;i++)
{
rec[i]=document.createElement("rect");
svg.appendChild(rect[i]);
txt[i] = document.createElement("text");
svg.appendChild(txt[i]);
var r = Math.floor(Math.random() * 255);
var g = Math.floor(Math.random() * 255);
var b = Math.floor(Math.random() * 255);
rec[i].outerHTML = "<rect x=" + (i * w / rect.length) + " y=" + (h - height[i]) + " width=" +
(0.9 * w / rect.length) + " height=" + height[i] + " fill='rgb(" + r + "," + g + "," + b + ")'>";
txt[i].outerHTML = "<text x=" + (i * w / rect.length + 10) + " y=" + (h - height[i] - 10) + ">" + height[i] + "</text>";
}
</script>
</body>
</html>
2、树与文字树
2.1、分型二叉树
1、添加画布,并设置宽和高:
<svg id="mysvg"></svg>
<script>
...
var w = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var h = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
var mysvg = document.getElementById("mySvg");//添加画布
w = w * 0.98;
h = h * 0.98;
//设置画布的宽、高
mysvg.setAttribute("width", w);
mysvg.setAttribute("height", h);
...
</script>
2、我们可以先画迭代次数为1的树
//设置树的初始点,
var x0 = w / 2;
var y0 = h;
//设置枝干长度
var L = 500;
//设置衰减率
var rate = 0.7;
//设置终点
var x2 = x0 + L * rate * Math.random() * Math.cos(a);
var y2 = y0 + L * rate * Math.random()* Math.sin(a);
var svgline = document.createElement("line");
mysvg.appendChild(svgline);
//画“枝干”
svgline.outerHTML = "<line x1=" + x0 + " y1=" + y0 + " x2=" + x2 + " y2=" + y2 + " />";
图:
3、迭代2次:
我们可以把这一块做一点处理,写成一个函数:
function show(x0, y0, L, rate, a, count) {
var x1 = x0;
var y1 = y0;
var r = 1;
//var r = Math.random();
//设置“枝干”终点坐标
var x2 = x1 + L * rate * r * Math.cos(a);
var y2 = y1 + L * rate * r * Math.sin(a);
var svgline = document.createElement("line");
mysvg.appendChild(svgline);
//iter++;
//stroke:设置颜色,stroke-width:设置svgline的宽度,理解为“枝干”的粗细程度
svgline.outerHTML = "<line x1=" + x1 + " y1=" + y1 + " x2=" + x2 + " y2=" + y2 + " style='stroke:rgb(50,100,0);stroke-width:"+(count)+"' />";
//设置角度
var aL = a - Math.PI / 4;
var aR = a + Math.PI / 4;
if (count > 0) {
show(x2, y2, L * rate, rate, aL, count - 1);//显示左枝
show(x2, y2, L * rate, rate, aR, count - 1);//显示右枝
}
}
show(x0, y0, L * rate, rate, -Math.PI / 2, count);//调用函数
4、迭代多次
5、添加随机性
我们可以给这棵树添加一些随机性的东西,让它看起来比较自然。添加一个变量r。
var r = Math.random();
var x2 = x1 + L * rate * r * Math.cos(a);
var y2 = y1 + L * rate * r * Math.sin(a);
同时也改变了迭代角度:
var aL = a - Math.PI / 7;
var aR = a + Math.PI / 7;
6、修饰:我们给这棵树稍微修饰一下,树上除了枝干,还会有果实、花之类的
7、完整代码
<html>
<head>
<title>
分型二叉树
</title>
</head>
<body>
<svg id="mySvg">
</svg>
<script>
var w = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var h = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
var mysvg = document.getElementById("mySvg");
w = w * 0.98;
h = h * 0.98;
mysvg.setAttribute("width", w);
mysvg.setAttribute("height", h);
var x0 = w / 2;
var y0 = h;
var L = 500;
var rate = 0.7;
var a = 0;
var count = 7;
var iter = 100;
function show(x0, y0, L, rate, a, count) {
var x1 = x0;
var y1 = y0;
var r = Math.random();
var x2 = x1 + L * rate * r * Math.cos(a);
var y2 = y1 + L * rate * r * Math.sin(a);
var svgline = document.createElement("line");
mysvg.appendChild(svgline);
iter++;
svgline.outerHTML = "<line x1=" + x1 + " y1=" + y1 + " x2=" + x2 + " y2=" + y2 + " style='stroke:rgb(50,"+(iter)+",0);stroke-width:"+(count)+"' />";
var aL = a - Math.PI / 7;
var aR = a + Math.PI / 7;
if (count > 0) {
show(x2, y2, L * rate, rate, aL, count - 1);
show(x2, y2, L * rate, rate, aR, count - 1);
if (count == 1) {
var circle = document.createElement("circle");
mysvg.appendChild(circle);
circle.outerHTML = "<circle cx= " + x2 + " cy= " + y2 + " r=" + 5*Math.random() + " fill='pink'>";
}
}
}
show(x0, y0, L * rate, rate, -Math.PI / 2, count);
</script>
</body>
</html>
2.2、文字树
其实经过上面分型二叉树的实现,我们应该也能知道文字树实现的大概过程,最主要的是文字的旋转和自适应“枝干”长度。
1、文字的旋转:使用text标签设置文字的x、y坐标、颜色、内容(x、y坐标是指的文字的左下角)。使用rotate()对文字进行旋转的操作。
<text x=300 y=200 fill="red" transform="rotate(45)">春江花月夜</text>
2、自适应长度:fontsize设置“枝干”的粗细,str.length为文字的长度。
var r = Math.random();
var fontsize = 3 * count * (0.5 + 0.5 * r);
var L = str.length * fontsize;
完整代码
<html>
<head>
<title>
文字二叉树
</title>
</head>
<body>
<svg id="mySvg" >
</svg>
<script>
var w = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var h = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
var mysvg = document.getElementById("mySvg");
w = w * 0.98;
h = h * 0.98;
mysvg.setAttribute("width", w);
mysvg.setAttribute("height", h);
var x0 = w / 2;
var y0 = h;
var rate = 0.7;
var a = 0;
var count = 8;
var iter = 100;
var txt1 = new Array;
var str = "春江潮水连海平";
function show(x0, y0, rate, a, count) {
var r = Math.random();
var fontsize = 3 * count * (0.5 + 0.5 * r);
var L = str.length * fontsize;
var x1 = x0;
var y1 = y0;
var x2 = x1 + L * Math.cos(a);
var y2 = y1 + L * Math.sin(a);
iter++;
var aL = a - Math.PI / 6 * (0.5 + 0.5 * r);
var aR = a + Math.PI / 6 * (0.5 + 0.5 * r);
var words = document.createElement("text");
mysvg.appendChild(words);
words.outerHTML = "<text x=" + x1 + " y=" + y1 + " transform='rotate(" + (a * 180 / Math.PI) + "," + x1 + "," + y1 + ")' fill='green' font-size=" + fontsize + ">" + str + "</text>";
if (count > 0) {
show(x2, y2, rate, aL, count - 1);
show(x2, y2, rate, aR, count - 1);
if (count == 1) {
var circle = document.createElement("circle");
mysvg.appendChild(circle);
circle.outerHTML = "<circle cx= " + x2 + " cy= " + y2 + " r=" + 5*Math.random() + " fill='pink'>";
}
}
}
show(x0, y0, rate, -Math.PI / 2, count);
</script>
</body>
</html>
三、D3基础篇
1、直方图
1.1、d3的版本:v3(我们老师说v3的版本较为稳定)
第一行是d3.v3.min.js这个文件下载在本地(这样写是和htm文件放在同一目录下)
第二行则是直接引用网页链接,较简单,但是在使用的时候要确保连接了网络。
(文件我是直接复制网页内容,然后命名为d3.v3.min.js存在本地)
<script src="d3.v3.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
1.2、 添加矩形
svg.selectAll("rect") //选中矩形标签
.data(dataset) //选择数据
.enter() //进入数据
.append("rect") //显示矩形
.attr("x", function (d, i) { return i * w / dataset.length; }) //设置x坐标
.attr("y", function (d) { return (h - 0.5 * d) - 20; }) //设置y坐标
.attr("width", function(d){ return 0.9 * w / dataset.length ; }) //设置矩形的宽度
.attr("height", function (d) { return 0.5*d; }) //设置矩形的高度
.attr("fill", color); //设置颜色
1.3、添加数据说明
svg.selectAll("text") //选中text标签
.data(dataset) //选中数据
.enter() //进入数据
.append("text") //显示文本
.attr("fill", "#4682B4") //填充颜色
.attr("font-size", "14px") //设置字体大小
.attr("text-anchor", "middle") //设置文本居中(基于x、y坐标)
.attr("x", function (d, i) { return i * w / dataset.length+15; }) //设置文本x坐标
.attr("y", function (d) { return (h - 0.5 * d) - 30; }) //设置文本y坐标
.text(function (d) { return d; });
1.4、添加年份
//定义一个类
bar1 = svg.append("g").attr("class", "bar1");
var l = dataset.length;
//用类显示
bar1.selectAll("text")
.data(txt)
.enter()
.append("text")
.attr("fill", "black")
.attr("font-size", "12px").attr("text-anchor", "middle")
.attr("x", function (d,i) { return i * w / l+18; })
.attr("y", function (d) { return h ; })
.text(function (d) { return d; });
结果展示:
完整代码:
<html>
<head>
<title>
d3直方图
</title>
</head>
<body>
<script src="d3.v3.min.js"></script>
<script>
var w = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var h = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
w = w * 0.98;
h = h * 0.98;
//定义画布
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//定义变量
var dataset = new Array(53);
dataset = [3.7, 4.1, 4.6, 4.9, 5.4, 6.0, 7.3, 9.1, 10.4, 12.2, 15.2, 17.2, 18.9, 22.1, 27.2, 35.6, 48.5, 60.4, 70.8,
78.8, 83.8, 89.4, 99.1, 109.3, 120.5, 136.6, 161.4, 186.0, 219.0, 270.7, 321.2, 347.9, 410.4, 483.4, 537.3, 588.1,
642.1, 683.4, 737.1, 820.1, 896.9, 986.5, 1016.0];
var txt = ["1978年", " ", " ", " ", "1982年", " ", " ", " ", "1986年", " ", " ", " ",
"1990年", " ", " ", " ", "1994年", " ", " ", " ", "1998年", " ", " ", " "," 2002年",
"", "", "", "2006年", "", " ", " ", "2010年", " ", " ", " ", "2014年", " ",
" ", " ", "2018年", " ", "2020年"];
var color = d3.scale.category20();
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function (d, i) { return i * w / dataset.length; })
.attr("y", function (d) { return (h - 0.5 * d) - 20; })
.attr("width", function(d){ return 0.9 * w / dataset.length ; })
.attr("height", function (d) { return 0.5*d; })
.attr("fill", color);
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.attr("fill", "#4682B4")
.attr("font-size", "14px")
.attr("text-anchor", "middle")
.attr("x", function (d, i) { return i * w / dataset.length+15; })
.attr("y", function (d) { return (h - 0.5 * d) - 30; })
.text(function (d) { return d; });
bar1 = svg.append("g").attr("class", "bar1");
var l = dataset.length;
bar1.selectAll("text").data(txt).enter().append("text").attr("fill", "black")
.attr("font-size", "12px").attr("text-anchor", "middle")
.attr("x", function (d,i) { return i * w / l+18; })
.attr("y", function (d) { return h ; })
.text(function (d) { return d; });
//添加标题
svg.append("text").attr("font-size", "24px")
.attr("text-anchor", "middle").attr("x", w / 2).attr("y", 50).text("1978年至2020年全国国内生产总值");
svg.append("text").attr("font-size", "14px")
.attr("x", w/2+50).attr("y", 80).text("(单位:千亿元)");
</script>
</body>
</html>
2、环图
2.1、画一个完整的环图:
//定义画布
var svg = d3.select("body")
.append("svg").attr("width", w)
.attr("height", h);
//startAngle:起始角度,endAngle:终止角度
var dataset = { startAngle: 0, endAngle: Math.PI*2 };
//innerRadius:内半径outerRadius:外半径
var arcPath = d3.svg.arc().innerRadius(100).outerRadius(200);
svg.append("path")
.attr("d", arcPath(dataset))
.attr("fill", "yellow")
.attr("stroke", "blue")
.attr("transform","translate("+w/2+","+h/2+")");
2.2、分段
var dataset = [{ startAngle: 0, endAngle: 1 }, { startAngle: 1, endAngle: 2 }, { startAngle: 2, endAngle:3 },
{ startAngle: 3, endAngle: 4 }, { startAngle: 4, endAngle: Math.PI * 2 }];
2.3显示数据
var dataset = [ ["小米", 60.8], ["三星", 58.4],["联想", 47.3],["苹果", 46.6], ["华为", 41.3], ["酷派", 40.1], ["其他", 111.5]];
var pie = d3.layout.pie().value(function (d) { return d[1]; });
var piedata = pie(dataset);
console.log(piedata);
svg.selectAll("path")
.data(piedata)
.enter()
.append("path")
.attr("d", function (d) { return arcPath(d); })
.attr("fill", "yellow")
.attr("stroke", "blue")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
svg.selectAll("text").data(piedata).enter().append("text")
.attr("fill", "black").attr("text-anchor", "middle")
.attr("transform", function (d) {
var x = arcPath.centroid(d)[0];
var y = arcPath.centroid(d)[1];
return "translate(" + (w / 2 + x) + "," + (h / 2 + y) + ")";
})
.text(function (d) { return d.value });
结果展示:
完整代码:
!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
.container {
margin: 30px auto;
width: 1000px;
height: 800px;
}
polyline {
fill: none;
stroke: #000000;
stroke-width: 2px;
stroke-dasharray: 5px;
}
</style>
</head>
<body>
<center>
<h1><br>家暴案件中施暴者和受害者关系比例</br></h1>
<h3><p align="center">单位:件数</p></h3>
</center>
<div class="container">
<svg width="100%" height="100%"></svg>
</div>
<h3><p align="center">数据来源:《中华人民共和国反家庭暴力法》实施三周年监测报告</p></h3>
<script src="d3.v3.min.js"></script>
<script>
window.onload = function () {
var w = 1200;
var h = 1000;
// 创建一个分组用来组合要画的图表元素
var main = d3.select('.container svg').append('g')
.classed('main', true)
.attr('transform', "translate(" + (w / 3 + 50) + ',' + h / 3 + ')');
// 模拟数据
//var dataset =[["婚内关系",233],["离婚中",101],["亲子",38],["分居并离婚中",25],["婚内分居",24],["其他",16],["前配偶关系",12]];
//main.append("text").attr("font-size", "28px")
// .attr("text-anchor", "start ").attr("x", 30).attr("y", 0).text("家暴案件中施暴者和受害者关系比例");
var dataset = [
{ name: '婚内关系(51.9%)', value: 233 },
{ name: '其他(3.6%)', value: 16 },
{ name: '离婚中(22.5%)', value: 101 },
{ name: '婚内分居(5.3%)', value: 24 },
{ name: '分居并离婚中(5.6%)', value: 25 },
{ name: '前配偶关系(2.7%)', value: 12 },
{ name: '亲子(8.5%)', value: 38 }
];
var color = d3.scale.category20();
// 转换原始数据为能用于绘图的数据
var pie = d3.layout.pie()
.sort(null)
.value(function (d) {
return d.value;
});
// pie是一个函数
var pieData = pie(dataset);
// 创建计算弧形路径的函数
var radius = 200;
var arc = d3.svg.arc()
.innerRadius(0)
.outerRadius(radius);
var outerArc = d3.svg.arc()
.innerRadius(1.2 * radius)
.outerRadius(1.2 * radius);
var oArc = d3.svg.arc()
.innerRadius(1.1 * radius)
.outerRadius(1.1 * radius);
var slices = main.append('g').attr('class', 'slices');
var lines = main.append('g').attr('class', 'lines');
var labels = main.append('g').attr('class', 'labels');
// 添加弧形元素(g中的path)
var arcs = slices.selectAll('g')
.data(pieData)
.enter()
.append('path')
.attr('fill', function (d, i) {
//console.log(i);
return getColor(i);
})
.attr('d', function (d) {
return arc(d);
})
.on("mouseover", function (d, i) {
d3.select(this)
.attr("fill", "#FFC0C8");
})
.on("mouseout", function (d, i) {
d3.select(this)
.transition()
.duration(500)
.attr("fill", function (d, i) {
//console.log(i);
return getColor(i);
})
.attr("stroke", "white")
})
// 添加文字标签
var texts = labels.selectAll('text')
.data(pieData)
.enter()
.append('text')
.attr('dy', '0.35em')
.attr('fill', function (d, i) {
return getColor(i);
})
.text(function (d, i) {
return d.data.name;
})
.style('text-anchor', function (d, i) {
return midAngel(d) < Math.PI ? 'start' : 'end';
})
.attr('transform', function (d, i) {
// 找出外弧形的中心点
var pos = outerArc.centroid(d);
// 改变文字标识的x坐标
pos[0] = radius * (midAngel(d) < Math.PI ? 1.5 : -1.5);
return 'translate(' + pos + ')';
})
.style('opacity', 1);
var polylines = lines.selectAll('polyline')
.data(pieData)
.enter()
.append('polyline')
.attr('points', function (d) {
return [arc.centroid(d), arc.centroid(d), arc.centroid(d)];
})
.attr('points', function (d) {
var pos = outerArc.centroid(d);
pos[0] = radius * (midAngel(d) < Math.PI ? 1.5 : -1.5);
return [oArc.centroid(d), outerArc.centroid(d), pos];
})
.style('opacity', 0.5);
};
function midAngel(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
function getColor(idx) {
var palette = [
'#2ec7c9', '#b6a2de', '#5ab1ef', '#ffb980', '#d87a80',
'#8d98b3', '#e5cf0d', '#97b552', '#95706d', '#dc69aa',
'#07a2a4', '#9a7fd1', '#588dd5', '#f5994e', '#c05050',
'#59678c', '#c9ab00', '#7eb00a', '#6f5553', '#c14089'
]
return palette[idx % palette.length];
}
</script>
</body>
</html>
四、D3重点篇
1、力导向图可视化
1.1、基于line的力导向
var color = d3.scale.category20();//颜色
var force = d3.layout.force().charge(-120).linkDistance(100).size([w, h]);
//a.json是和htm文件在同一目录下的存储着结点信息的文件。
d3.json("a.json", function (error, graph) {
force.nodes(graph.nodes)
.links(graph.links)
.start();
//连线
var lin = svg.selectAll(".link")
.data(graph.links)
.enter()
.append("line")
.attr("class", "link")
.style("stroke-width", 1)
.style("stroke", "red");
//显示结点
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter()
.append("circle")//绘制成圆
.attr("class", "node")
.attr("r", 16)
.attr("cx", 100)
.attr("cy", 100)
.style("fill", "pink")
.call(force.drag);//结点可拖动的关键
force.on("tick", function () {
node.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; });
lin.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; });
})
})
也可以直接将结点信息写在htm文件中。下图是以《人民的名义》为例。
为了区分每个人在关系网络里的“重要性”,我们可以在结点里添加下列代码
.attr("r", function (d) { return d.weight * 3;})//关系越多,结点越大
var text = svg.selectAll(".forcetxt")
.data(nodes)
.enter()
.append("text")
.attr("class", "forcetxt")
.attr("x", 100)
.attr("y", 100)
.text(function (d) { return d.name; });//返回结点的name属性
再在force.on中添加text的x、y坐标
text.attr("x", function (d) { return d.x; })
.attr("y", function (d) { return d.y; });
- 添加力导向边名称:
var edges_text = svg.selectAll(".linetext")
.data(edges)
.enter()
.append("text")
.attr("class","linetext")
.text(function(d){
return d.relation;
})
.style("stroke","gray")
.style("font-size",8);
- 同样在force.on中添加下列代码
edges_text.attr("x",function(d){ return (d.source.x + d.target.x) / 2 ; });
edges_text.attr("y",function(d){ return (d.source.y + d.target.y) / 2 ; });
var img_h=50;
var img_w=50;
var radius=23;
var circles=svg.selectAll("forceCircle")
...
.attr("fill", function(d, i){
//创建圆形图片
var defs = svg.append("defs").attr("id", "imgdefs");
var catpattern = defs.append("pattern")
.attr("id", "catpattern" + i)
.attr("height", 1)
.attr("width", 1);
catpattern.append("image")
.attr("x", - (img_w / 2 - radius+5.8))
.attr("y", - (img_h / 2 - radius+3.5))
.attr("width", img_w+11)
.attr("height", img_h+6)
.attr("xlink:href","image/"+d.image);
return "url(#catpattern" + i + ")";
})
...
- 添加文本提示框
var circles=svg.selectAll("forceCircle")
...
.on("mouseover",function(d,i){ //加入提示框
tooltip.html("角色简介:"+d.intro)
.style("left",(d3.event.pageX)+"px")
.style("top",(d3.event.pageY+20)+"px")
.style("opacity",1.0);
})
...
1.2、基于path的力导向
- 基于path的文字
<svg width="100%" height="100%">
<defs>
//设定路径
<path id="mypath" stroke="blue"
d="M 10 200
C 200 100 300 0 400 100
C 500 200 600 300 700 200
C 800 100 900 100 900 100 "/>
</defs>
<use xlink:href="#mypath" fill="none" stroke="blue"></use>
<text font-size="30" fill="green">
<textPath xlink:href="#mypath">
后海有树的院子,夏代有工的玉,此时此刻的云,二十来岁的你……</textPath></text>
</svg>
- 基于path的力导向
<style type="text/css">
path{
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
circle {
stroke: #333;
stroke-width: 1.5px;
}
text {
font: 10px sans-serif;
pointer-events: none;
}
</style>
...
//用路径创建边
var path = svg.selectAll("path")
.data(edges)
.enter()
.append("path")
.attr("id", function(d,i) {
return "edgepath" +i;
})
.attr("class","edges");
var pathtext = svg.selectAll('g')
.data(edges)
.enter()
.append("text")
.append('textPath')
.attr("text-anchor", "middle")//居中
.attr("startOffset","50%")
.attr('xlink:href', function(d,i) { return "#edgepath" + i; })
.text(function(d) { return d.relation; });
...
function tick() {
path.attr("d", function(d) {
var dx = d.target.x - d.source.x;//增量
var dy = d.target.y - d.source.y;
return "M" + d.source.x + ","+ d.source.y + "L" + d.target.x + "," + d.target.y;
});
circle.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
nodetext.attr("x",function(d){return d.x;});
nodetext.attr("y",function(d){return d.y;});
}
2、链接数据库
链接数据库用玫瑰显示字母表
<div id="wc"></div>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page language="java" %>
<%@ page import="com.mysql.jdbc.Driver" %>
<%@ page import="java.sql.*" %>
<%
//out.print("<center><h1><font color=black>Matrix Word Cloud English Learning</h1></center>");
//
String driverName="com.mysql.jdbc.Driver";
//账户名
String userName="root";
// 账户密码
String userPasswd="password";
// 数据库名
String dbName="test";
//表名
String tableName="test1";
//
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/"+dbName+"?serverTimezone=GMT%2B8","root","password");
Statement statement = connection.createStatement();
int count[]=new int[26];
for(int i=0;i<26;i++){
int aa=Integer.valueOf('a')+i;
char cha = (char) aa;
//out.print(aa);
//out.print(cha);
//String sql="SELECT * FROM "+tableName+" where english like 'a%' "+"order by english";
String sql="SELECT * FROM "+tableName+" where english like '"+cha+"%' "+"order by english";
ResultSet rs = statement.executeQuery(sql);
String str;
int j=0;
while(rs.next()) {
str=(rs.getString(2)).substring(0,1);
//out.print(str+" ");
j++;
}
count[i]=j;
//out.print(" "+j+" <br>");
rs.close();
}
statement.close();
connection.close();
%>
//将Java变量传递给js中的变量
<%for(int i=0;i <count.length;i++)
{%>
dataset[<%=i%>][1]=" <%=count[i]%> ";
<%}
%>