文章目录
一、数据可视化
屈华民在《大数据时代的可视化与协同创新》一文中曾说过:
可视化,简要地讲,就是把数据转换为图形图像的方式,帮助人们理解大量的和复杂的数据。
由此可见,数据可视化的本质是分析数据、清晰有效地传达与沟通信息,是十分具有现实意义的。本篇博客简单记录了笔者在数据可视化课程中的学习。
二、Javascript
2.1 JavaScript直方图绘制
(1)代码
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Percentage of Australian men doing regular physical activity:2010</title>
</head>
<body>
<h2><center>Percentage of Australian men doing regular physical activity:2010</center></h2>
<svg id="mysvg" width=800 height=600></svg>
<script>
var w = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var h = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
var svg=document.getElementById("mysvg");
svg.setAttribute("width",w);
svg.setAttribute("height",h);
var rec=new Array(6);
var txt=new Array(6);
var title=new Array(6);
var height=new Array(52.8,42.2,39.5,43.1,45.1,46.7);
var age=new Array("AGE15-24","AGE25-34","AGE35-44","AGE45-54","AGE55-64","AGE65+");
for(var i=0;i<6;i++){
rec[i]=document.createElement("rect");
svg.appendChild(rec[i]);
txt[i]=document.createElement("text");
svg.appendChild(txt[i]);
title[i]=document.createElement("text");
svg.appendChild(title[i]);
rec[i].outerHTML="<rect x="+(i*w/rec.length)+" y="+(h-height[i]*10)+" width="+(w*0.9/rec.length)+" height="+(height[i]*10)+" fill='rgb(0,0,"+(height[i]*20-750)+")'>";
txt[i].outerHTML="<text x="+(i*w/rec.length)+" y="+(h-height[i]*10)+">"+height[i]+"</text>";
title[i].outerHTML="<text x="+((i*w/rec.length)+50)+" y="+(h-height[i]*10)+">"+age[i]+"</text>";
}
</script>
</body>
</html>
(2)实验结果
(3)总结
这是笔者第一次实现JavaScript直方图的绘制,当时对数据本身的选取并不重视。数据可视化主要是借助于图形化手段,有效地传达与沟通信息,所选取的信息应具有时效性、参考价值。笔者在后面的可视化实现中会更重视数据本身。
2.2 基于JavaScript和SVG的二叉树
(1)代码
<html>
<body>
<h2><center>仿真二叉树</center></h2>
<svg id="mysvg" width=800 height=600>
</svg>
<script>
var w=window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var h=window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
var svg=document.getElementById("mysvg");
svg.setAttribute("width",w);
svg.setAttribute("height",h);
w=w*0.98;
h=h*0.98;
var x0=w/2;
var y0=h;
var L=200;
var rate=0.92;
var a=-Math.PI/2;
var count=11;
function show(x0,y0,L,rate,a,count){
var x1=x0;
var y1=y0;
var x2=x1+L*Math.cos(a);
var y2=y1+L*Math.sin(a);
var L=L*rate*(0.5+Math.random()*0.5);
var aL=a-Math.PI/4.5*(0.5+Math.random()*0.5);
var aR=a+Math.PI/4.5*(0.5+Math.random()*0.5);
var lineX=document.createElement("line");
svg.appendChild(lineX);
lineX.outerHTML="<line x1="+x1+" y1="+y1+" x2="+x2+" y2="+y2+" stroke='green' stroke-width="+count+" />";
if(count>0){
show(x2,y2,L,rate,aL,count-1);
show(x2,y2,L,rate,aR,count-1);
}
}
show(x0,y0,L,rate,a,count);
</script>
</body>
</html>
(2)实验结果
2.3 基于JavaScript和SVG的文字树
(1)代码
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<h2><center>文字二叉树</center></h2>
<svg id="mysvg" width=800 height=600>
</svg>
<script>
var w=window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var h=window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
var svg=document.getElementById("mysvg");
svg.setAttribute("width",w);
svg.setAttribute("height",h);
w=w*0.98;
h=h*0.98;
var str="这是一棵文字树";
var x0=w/2;
var y0=h;
var L=200;
var rate=0.6;
var a=-Math.PI/2;
var count=7;
var fontsize=20;
function show(x0,y0,L,rate,a,count){
var fontsize=count*3;
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);
var aL=a-Math.PI/6*(0.5+0.5*Math.random());
var aR=a+Math.PI/6*(0.5+0.5*Math.random());
var words=document.createElement("text");
svg.appendChild(words);
words.outerHTML="<text x="+x1+" y="+y1+" transform='rotate("+a*180/Math.PI+","+x1+","+y1+")' fill='rgb(0,"+(250-count*30)+",0)' font-size="+fontsize+">"+str+"</text>";
if(count>0){
show(x2,y2,L,rate,aL,count-1);
show(x2,y2,L,rate,aR,count-1);
if (count==1){
var apple=document.createElement("circle");
svg.appendChild(apple);
apple.outerHTML="<circle cx="+x2+" cy="+y2+" r="+6*Math.random()+" fill='rgb("+(150+100*Math.random())+",0,0)'/>";
}
}
}
show(x0,y0,L,rate,a,count);
show(x0,y0,L,rate,a,count);
</script>
</body>
</html>
(2)实验结果
三、D3
3.1 D3直方图的绘制
(1)代码
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<h2><center>当前热映电影的豆瓣评分</center></h2>
<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.9;
var dataset=new Array(10);
dataset=[8.8,7.4,6.6,3.7,6.7,8.2,2.8,7.2,8.1,7.4];
var film=new Array(10);
film=["阿凡达","又见奈良","21座桥","合法伴侣","哥斯拉大战金刚","波斯语课","日不落酒店","寻龙传说","你好李焕英","五尺天涯"];
var color = d3.scale.category10();
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x",function(d,i){
return (w/dataset.length)*i;
})
.attr("y",function(d){
return h-20-d*50;
})
.attr("width",(w/dataset.length)-10)
.attr("height",function(d){
return 50*d;
})
.attr("fill",function(d,i){
return color(i);
});
svg.selectAll("text.title")
.data(film)
.enter()
.append("text")
.attr("font-size","18px")
.attr("x",function(d,i){
return (w/dataset.length)*i+10;
})
.attr("y",h-20)
.attr("dx",(w/dataset.length)/2-70)
.attr("dy","18px")
.text(function(d){
return d;
});
svg.selectAll("text.value")
.data(dataset)
.enter()
.append("text")
.attr("font-size","18px")
.attr("x",function(d,i){
return (w/dataset.length)*i+10;
})
.attr("y",function(d){
return h-40-d*50;
})
.attr("dx",(w/dataset.length)/2-70)
.attr("dy","18px")
.text(function(d){
return d;
});
</script>
</body>
</html>
(2)实验结果
3.2 饼图和环图的绘制
用D3绘制饼图有两种方法,一种是基于弧度的可视化,一种是基于数据的可视化。
基于弧度的可视化
(1)代码
<html>
<head>
<meta charset="UTF-8">
</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.9;
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
var dataset=[{startAngle:0,endAngle:1},
{startAngle:1,endAngle:2},
{startAngle:2,endAngle:4},
{startAngle:4,endAngle:5},
{startAngle:5,endAngle:Math.PI*2}];
var arcPath=d3.svg.arc()
.innerRadius(150)
.outerRadius(300)
svg.selectAll("path")
.data(dataset)
.enter()
.append("path")
.attr("d",function(d){
return arcPath(d)
})
.attr("fill","yellow")
.attr("stroke","blue")
.attr("transform","translate("+w/2+","+h/2+")");
</script>
</body>
</html>
(2)实验结果
基于数据的可视化
(1)代码
<html>
<head>
<meta charset="UTF-8">
</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.9;
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
var dataset=[["农业",90],["工业",200],["第三产业",400]];
var pie=d3.layout.pie()
.value(function(d){return d[1];});
var piedata=pie(dataset);
var arc=d3.svg.arc()
.innerRadius(100)
.outerRadius(300)
svg.selectAll("path")
.data(piedata)
.enter()
.append("path")
.attr("d",function(d){
return arc(d)
})
.attr("fill","yellow")
.attr("stroke","blue")
.attr("transform","translate("+w/2+","+h/2+")");
</script>
</body>
</html>
(2)实验结果
基于弧度的电影数据可视化:
(1)代码
<html>
<head>
<meta charset="UTF-8">
<center><font size="8"><strong>2020年各题材电影票房占比</strong></font></center>
</head>
<body>
<div style="position: absolute; bottom: 630px; right: 465px;"><font size="2"><strong>数据来源:艺恩数据</strong></font></div>
<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.9;
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
var dataset=[["剧情",23],["喜剧",21],["战争",18],["动画",15],["动作",13],["爱情",5],["其他",5]];
var pie=d3.layout.pie()
.value(function(d){return d[1];});
var piedata=pie(dataset);
var arc=d3.svg.arc()
.innerRadius(100)
.outerRadius(200)
var arcs=svg.selectAll("g")
.data(piedata)
.enter()
.append("g")
.attr("transform","translate("+(w/2)+","+(h/2)+")");
arcs.append("path")
.attr("d",function(d){
return arc(d)
})
.attr("fill","#7bbfea")
.attr("stroke","white")
.on("mouseover",function(d){
d3.select(this)
.attr("fill","#f8aba6")
})
.on("mouseout",function(d){
d3.select(this)
.attr("fill","#7bbfea")
});
svg.selectAll("text")
.data(piedata)
.enter()
.append("text")
.attr("fill","white")
.attr("text-anchor","middle")
.attr("transform",function(d){
var x=arc.centroid(d)[0];
var y=arc.centroid(d)[1];
return "translate("+(w/2+x)+","+(h/2+y)+")";
})
.text(function(d){return d.value+"%"});
arcs.append("line")
.attr("stroke","#cde6c7")
.attr("x1",function(d){ return arc.centroid(d)[0]*1.34;})
.attr("y1",function(d){ return arc.centroid(d)[1]*1.34;})
.attr("x2",function(d){ return arc.centroid(d)[0]*1.5;})
.attr("y2",function(d){ return arc.centroid(d)[1]*1.5;});
arcs.append("text")
.attr("fill","#145b7d")
.attr("transform",function(d){
var x=arc.centroid(d)[0]*1.6;
var y=arc.centroid(d)[1]*1.6;
return "translate("+x+","+y+")";
})
.attr("text-anchor","middle")
.text(function(d){
return d.data[0];
});
</script>
</body>
</html>
(2)实验结果
3.3 力导向图可视化
用D3绘制力导向图有两种方法,一种是基于直线Line的,一种是基于路径Path的。
基于直线Line的力导向图可视化
(1)代码
<html>
<head>
<meta charset="UTF-8">
<center><font size="8"><strong>巴黎圣母院人物关系图</strong></font></center>
</head>
<body>
<div style="position: absolute; bottom: 630px; right: 525px;"><font size="2"><strong>数据来源:百度</strong></font></div>
<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.9;
var nodes=[{name:"埃斯梅拉达"},{name:"卡西莫多"},{name:"克洛德"},{name:"甘果瓦"},{name:"菲比斯"},{name:"若望"},{name:"小百合"},{name:"居第尔"}];
var edges=[{source:0,target:1,relation:"爱慕"},
{source:0,target:2,relation:"由爱生恨"},
{source:0,target:3,relation:"名义夫妻"},
{source:0,target:4,relation:"爱慕"},
{source:1,target:2,relation:"养父子"},
{source:1,target:4,relation:"被逮捕&逮捕"},
{source:2,target:3,relation:"师生"},
{source:2,target:4,relation:"情敌"},
{source:2,target:5,relation:"兄弟"},
{source:4,target:6,relation:"订婚"},
{source:0,target:7,relation:"母女"},
{source:2,target:7,relation:"上下级"}];
var color=d3.scale.category20();
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
var force=d3.layout.force()
.nodes(nodes)
.links(edges)
.size([w,h])
.linkDistance(300)
.charge(-600)
.on("tick",tick)
.start();
var path=svg.selectAll("path")
.data(edges)
.enter()
.append("path")
.attr("id",function(d,i){return "edgepath"+i;})
.attr("stroke","grey");
var circle=svg.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.attr("r",function(d){
if(d.weight<3){
return d.weight*10;
}
else{
return d.weight*5;
}
})
.attr("fill",function(d,i){
return color(i);
})
.call(force.drag);
var ntext=svg.selectAll("ntext")
.data(nodes)
.enter()
.append("text")
.attr("class",".ntext")
.attr("fill","black")
.attr("text-anchor","middle")
.attr("dy",function(d){
if(d.weight<3){
return d.weight*10+12;
}
else{
return d.weight*5+12;
}
})
.text(function(d){return d.name;})
.style("font-size","14px");
var etext=svg.selectAll("etext")
.data(edges)
.enter()
.append("text")
.append("textPath")
.attr("xlink:href",function(d,i){return "#edgepath"+i;})
.attr("class",".etext")
.attr("startOffset","50%")
.attr("fill","grey")
.attr("text-anchor","middle")
.text(function(d){return d.relation;})
.style("font-size","14px");
function tick(){
path.attr("d",function(d){
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+")";
})
ntext.attr("x",function(d){return d.x;})
.attr("y",function(d){return d.y;});
}
</script>
</body>
</html>
基于路径Path的力导向图可视化
<html>
<head>
<meta charset="UTF-8">
<center><font size="8"><strong>巴黎圣母院人物关系图</strong></font></center>
<style>
path{
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
circle {
stroke: #333;
stroke-width: 1.5px;
}
text {
font: 10px sans-serif;
pointer-events: none;
}
.tooltip{
position: absolute;
width: 240px;
height: auto;
font-family: simsun;
font-size: 12px;
text-align: left;
color: black;
border-width: 1px solid black;
background-color: A9A9A9;
border-radius: 3px;
}
.tooltip:after{
content: '';
position: absolute;
bottom: 100%;
left: 20%;
margin-left: -3px;
width: 0;
height: 0;
border-bottom: 12px solid rgb(182, 174, 174);
border-right: 12px solid transparent;
border-left: 12px solid transparent;
}
</style>
</head>
<body>
<div style="position: absolute; bottom: 630px; right: 525px;"><font size="2"><strong>数据来源:百度</strong></font></div>
<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.9;
var nodes=[{name:"埃斯梅拉达",intro:"埃斯梅拉达是雨果笔下集真、善、美于一体的完美的艺术形象。她在小时候被吉普赛人从妓女母亲的呵护下偷走,流浪街头以卖艺为生,虽然饱尝人世的艰辛与苦难,但是却始终保持着一颗善良纯真、乐于助人的心。她是美丽善良的,当乞丐国王要绞死甘果瓦时,她承诺要与甘果瓦结婚救下了他的命;当卡西莫多接受刑法口渴难耐时,只有她站出来以德报怨为他送水。她是勇敢执着的,当克洛德威胁她,只要接受他的爱就能够获得自由时,她斩钉截铁地拒绝了;当菲比斯不顾她的安危死活时,却依然痴心执着的爱着他。"},
{name:"卡西莫多",intro:"卡西莫多是一个有着几何形的脸,四面体的鼻子,马蹄形的嘴,参差不齐的牙齿,独眼,耳聋,驼背,难听而忠厚的声音的畸形儿。他幼时被父母遗弃在巴黎圣母院门口,后被克洛德收养,成为敲钟人。为报恩,他对克洛德言听计从,绑架了埃斯梅拉达。但在遇到埃斯梅拉达之后,他真诚善良、忠实勇敢的本性被复活了。他奋不顾身地去救处于危险中的埃斯梅拉达,并且不图任何回报。"},
{name:"克洛德",intro:"克洛德从小接受了良好的宗教教育,是一个勤奋好学、积极向上、知识渊博的青年,他收养丑陋的卡西莫多、照顾年少的弟弟,是有些许善良的。在成为巴黎圣母院的副主教遇到美丽的埃斯梅拉达后,克洛德真实的人性开始表现出来,内心强烈的占有欲迫使他去跟踪、绑架、强抢埃斯梅拉达,这并不是真正意义上的爱情,只是人性中的贪婪和欲望而已。他对埃斯梅拉达的占有欲已经超越了教会思想的束缚,不顾任何人的想法采用极端的做法只能造成悲剧的结局。"},
{name:"甘果瓦",intro:"流浪诗人,曾因误闯乞丐王国要被绞死,行刑前被埃斯梅拉达以名义婚姻的形式救下。长时间的流浪使他更清楚地认识这个时代和社会,在爱情和物质面前更倾向于选择实际的物质。"},
{name:"菲比斯",intro:"菲比斯表面上是一个英俊潇洒、美好的皇家卫队队长,深受女孩子的欢迎和喜爱,但是内在却是一个口蜜腹剑、风流成性的伪君子。一方面,菲比斯并不爱他的表妹,却因为表妹的丰厚嫁妆和贵族地位,而同意和表妹结婚,这是一个将金钱、地位摆在第一位的人;另一方面,他虚伪地爱着埃斯梅拉达,因其美丽的外表才一时兴起去追求。单纯的埃斯梅拉达却死心塌地爱上了这个男子,当克洛德因嫉妒袭击菲比斯时,他侥幸逃脱一劫,埃斯梅拉达却冤死在了绞刑架上。"},
{name:"若望",intro:"巴黎圣母院副主教克洛德之弟,一个游戏人生的小混混,后不满哥哥的所作所为,加入“圣母院”暴动队伍,死于伽西莫多之手。"},
{name:"小百合",intro:"菲比斯的原未婚妻,最终和甘果瓦成婚。"},
{name:"居第尔",intro:"埃斯梅拉达的母亲。她在监狱里认出了自己的女儿,在得知分散15年后刚刚找回的骨肉马上就要被吊死了后发狂一样地保护女儿,最后死在女儿的绞架下。"}];
var edges=[{source:0,target:1,relation:"爱慕"},
{source:0,target:2,relation:"由爱生恨"},
{source:0,target:3,relation:"名义夫妻"},
{source:0,target:4,relation:"爱慕"},
{source:1,target:2,relation:"养父子"},
{source:1,target:4,relation:"被逮捕&逮捕"},
{source:2,target:3,relation:"师生"},
{source:2,target:4,relation:"情敌"},
{source:2,target:5,relation:"兄弟"},
{source:4,target:6,relation:"订婚"},
{source:0,target:7,relation:"母女"},
{source:2,target:7,relation:"上下级"},
{source:3,target:6,relation:"夫妻"}];
var color=d3.scale.category20();
var force=d3.layout.force()
.charge(-600)
.linkDistance(300)
.size([w,h]);
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
force.nodes(nodes)
.links(edges)
.start();
var tooltip=d3.selectAll("body")
.append("div")
.attr("class","tooltip")
.style("opacity",0.0);
var link=svg.selectAll()
.data(edges)
.enter()
.append("line")
.attr("class","link")
.style("stroke-width",1)
.style("stroke","grey")
.style("opacity",0.4);
var node=svg.selectAll(".node")
.data(nodes)
.enter()
.append("circle")
.attr("class","node")
.attr("r",function(d){
if(d.weight<3){
return d.weight*10;
}
else{
return d.weight*5;
}
})
.attr("cx",100)
.attr("cy",100)
.style("fill",function(d,i){return color(i);})
.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);
})
.on("mousemove",function(d){
tooltip.style("left",(d3.event.pageX)+"px")
.style("top",(d3.event.pageY+20)+"px"); })
.on("mouseout",function(d){
tooltip.style("opacity",0.0); })
.call(force.drag);
var text=svg.selectAll(".forcetxt")
.data(nodes)
.enter()
.append("text")
.attr("class","forcetxt")
.attr("text-anchor","middle")
.attr("x",function(d){return d.x;})
.attr("y",function(d){return d.y;})
.attr("dy",function(d){
if(d.weight<3){
return d.weight*10+12;
}
else{
return d.weight*5+12;
}
})
.text(function(d){return d.name;})
.style("font-size","14px");
var edges_text=svg.selectAll(".linetext")
.data(edges)
.enter()
.append("text")
.attr("class","linetext")
.attr("fill","grey")
.attr("x",100)
.attr("y",200)
.text(function(d){return d.relation;})
.style("font-size","14px");
force.on("tick",function(){
node.attr("cx",function(d){return d.x;})
.attr("cy",function(d){return d.y;});
link.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;});
text.attr("x",function(d){return d.x;})
.attr("y",function(d){return d.y;});
edges_text.attr("x",function(d){ return (d.source.x + d.target.x) / 2 ; })
.attr("y",function(d){ return (d.source.y + d.target.y) / 2 ; });
})
</script>
</body>
</html>
(2)实验结果
四、JavaScrip与MySql的连接
JavaScript连接MySql数据库中的六级单词数据并进行可视化
(1)数据库
(2)代码
<!DOCTYPE html>
<body>
<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=blue>Matrix Word Cloud English Learning</h1></center>");
String driverName="com.mysql.jdbc.Driver";
String userName="root";
String userPasswd="54.wfy";
String dbName="flask";
String tableName="map_enword";
int count[]=new int[26];
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/"+dbName+"?serverTimezone=GMT%2B8","root","54.wfy");
Statement statement = connection.createStatement();
for(int i=0;i<26;i++){
int aa=Integer.valueOf('a')+i;
char cha = (char) aa;
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(" "+count[i]+" <br>");
rs.close();
}
statement.close();
connection.close();
%>
<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*2.3;
var color=d3.scale.category10();
var dataset=new Array(26);
var name=new Array(26);
var name1=new Array(26);
<% for (int i=0;i<26;i++){ %>
dataset[<%=i%>]="<%=count[i]%>";
<% } %>
name1=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
var name=name1.join('');
var ww=w/dataset.length;
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
var rect=svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x",function(d,i){return i*w/dataset.length})
.attr("y",function(d){return h-d*0.6-90})
.attr("width",ww*0.95)
.attr("height",function(d){return d*0.6})
.attr("fill",function(d,i){return color(i)});
var value=svg.selectAll("text.value")
.data(dataset)
.enter()
.append("text")
.attr("x",function(d,i){return i*w/dataset.length})
.attr("y",function(d){return h-d*0.6-90})
.text(function(d){return d})
.attr("dx",ww/2)
.attr("dy","-1em")
.attr("text-anchor","middle")
.attr("fill",function(d,i){return color(i)});
var title=svg.selectAll("text.title")
.data(name)
.enter()
.append("text")
.attr("x",function(d,i){return i*w/name.length})
.attr("y",function(d){return h-60})
.text(function(d){return d})
.attr("dx",ww/2)
.attr("dy","-lem")
.attr("text-anchor","middle")
.attr("fill",function(d,i){return color(i)});
//饼图
/* var pie=d3.layout.pie()
.value(function(d){return d;});
var piedata=pie(dataset);
var arc=d3.svg.arc()
.innerRadius(100)
.outerRadius(300)
svg.selectAll("path")
.data(piedata)
.enter()
.append("path")
.attr("d",function(d){
return arc(d)
})
.attr("fill",function(d,i){return color(i);})
.attr("transform","translate("+w/2+","+(h/2-400)+")");
*/
var dataset2 =new Array();
for(var i=0;i<26;i++){
dataset2[i]=new Array();
for(var j=0;j<2;j++){
dataset2[i][j]=1;
}
}
var datas=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
dataset2[0][0]='a'; dataset2[1][0]='b'; dataset2[2][0]='c'; dataset2[3][0]='d'; dataset2[4][0]='e'; dataset2[5][0]='f';
dataset2[6][0]='g'; dataset2[7][0]='h'; dataset2[8][0]='i'; dataset2[9][0]='j'; dataset2[10][0]='k'; dataset2[11][0]='l';
dataset2[12][0]='m'; dataset2[13][0]='n'; dataset2[14][0]='o'; dataset2[15][0]='p'; dataset2[16][0]='q'; dataset2[17][0]='r';
dataset2[18][0]='s'; dataset2[19][0]='t'; dataset2[20][0]='u'; dataset2[21][0]='v'; dataset2[22][0]='w'; dataset2[23][0]='x';
dataset2[24][0]='y'; dataset2[25][0]='z';
<%for(int i=0;i <count.length;i++){%>dataset2[<%=i%>][1]=" <%=count[i]%> ";<%}%>
var pie = d3.layout.pie()
.value(function (d) { return d[1]; });
innerRadius=30
var arcPath=d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(function (d) {
var value=d.value;
return value*0.6+ innerRadius;});
var piedata = pie(dataset2);
var arcs=svg.selectAll("path")
.data(piedata).enter()
.append("path")
.attr("d", function (d) { return arcPath(d); })
.attr("fill", function(d,i){return color(i);})
.attr("transform", "translate("+ w / 2 + "," + h / 3 +")");
arcs.append("path")
.attr("fill",function(d,i){
return color(i);})
.attr("d",arcPath)
var rect=svg.selectAll("rect")
.data(dataset2)
.enter()
.append("rect")
.attr("x",function(d,i){return i*w/dataset2.length})
.attr("y",function(d){return h-d[1]-30})
.attr("width",ww*0.95)
.attr("height",function(d){return d[1]})
.attr("fill",function(d,i){return color(i)});
bar1 = svg.append("g").attr("class", "bar1");
bar1.selectAll("text")
.data(piedata)
.enter()
.append("text")
.attr("fill","white")
.attr("transform",function(d){
var x=arcPath.centroid(d)[0];
var y=arcPath.centroid(d)[1];
return "translate("+(w/2+x)+","+(y+h/3)+")";})
.attr("text-anchor","middle")
.attr("font-size",function(d){
return d.data[1]*0.05+"px";})
.text(function(d){return d.data[0]});
</script>
</body>
(3)实验结果
JavaScript连接MySql数据库中的疫苗接种情况数据并进行可视化
(1)数据库
(2)代码
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
</head>
<body>
<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>疫苗接种人数</h1></center>");
String driverName="com.mysql.jdbc.Driver";
String userName="root";
String userPasswd="54.wfy";
String dbName="yimiao";
String tableName1="renshu";
String tableName2="baifenbi";
String tableName3="douyou";
String country1[]=new String[25];
double data1[]=new double[25];
String country2[]=new String[25];
double data2[]=new double[25];
String country3[]=new String[25];
double data31[]=new double[25];
double data32[]=new double[25];
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/"+dbName+"?serverTimezone=GMT%2B8","root","54.wfy");
Statement statement = connection.createStatement();
for(int i=1;i < 21;i++){
String sql="SELECT * FROM "+tableName1+" where id='"+i+"'";
String str=" ";
double per=1;
ResultSet rs = statement.executeQuery(sql);
while(rs.next()){
str=rs.getString(2);
per=rs.getDouble(3);
}
country1[i-1]=str;
data1[i-1]=per;
//out.print(country[i-1]+" ");
//out.print(data[i-1]);
rs.close();
}
for(int i=1;i < 21;i++){
String sql="SELECT * FROM "+tableName2+" where id='"+i+"'";
String str=" ";
double per=1;
ResultSet rs = statement.executeQuery(sql);
while(rs.next()){
str=rs.getString(2);
per=rs.getDouble(3);
}
country2[i-1]=str;
data2[i-1]=per;
//out.print(country[i-1]+" ");
//out.print(data[i-1]);
rs.close();
}
for(int i=1;i < 17;i++){
String sql="SELECT * FROM "+tableName3+" where id='"+i+"'";
String str=" ";
double per1=1;
double per2=1;
ResultSet rs = statement.executeQuery(sql);
while(rs.next()){
str=rs.getString(2);
per1=rs.getDouble(3);
per2=rs.getDouble(4);
}
country3[i-1]=str;
data31[i-1]=per1;
data32[i-1]=per2;
//out.print(country[i-1]+" ");
//out.print(data[i-1]);
rs.close();
}
statement.close();
connection.close();
%>
<div style="position: absolute; bottom: 2150px; right: 365px;"><font size="8"><strong>COVID-19疫苗接种人数(单位:百万)</strong></font></div>
<div style="position: absolute; bottom: 1400px; right: 340px;"><font size="8"><strong>COVID-19疫苗接种人次(单位:次/百人)</strong></font></div>
<div style="position: absolute; bottom: 680px; right: 340px;"><font size="8"><strong>COVID-19疫苗接种人数与人次对比</strong></font></div>
<div style="position: absolute; bottom: 2100px; right: 365px;"><font size="2"><strong>数据来源:Our World in Data</strong></font></div>
<script src="d3.v3.min.js"></script>
<script>
var width=window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var height=window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
w=width*0.98;
h=height*3;
var color=d3.scale.category10();
var dataset1=new Array(20);
var country1=new Array(20);
var dataset2=new Array(20);
var country2=new Array(20);
var dataset31=new Array(16);
var dataset32=new Array(16);
var country3=new Array(16);
<% for (int i=0;i<20;i++){ %>
dataset1[<%=i%>]= "<%=data1[i]%>";
country1[<%=i%>]= "<%=country1[i]%>";
<% } %>
<% for (int i=0;i<20;i++){ %>
dataset2[<%=i%>]= "<%=data2[i]%>";
country2[<%=i%>]= "<%=country2[i]%>";
<% } %>
<% for (int i=0;i<16;i++){ %>
dataset31[<%=i%>]= "<%=data31[i]%>";
dataset32[<%=i%>]= "<%=data32[i]%>";
country3[<%=i%>]= "<%=country3[i]%>";
<% } %>
var w1=w/dataset1.length;
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
var rect=svg.selectAll("rect1")
.data(dataset1)
.enter()
.append("rect")
.attr("x",function(d,i){return i*w/dataset1.length})
.attr("y",function(d){return h-2*height-d*3-80})
.attr("width",w1*0.95)
.attr("height",function(d){return d*3})
.attr("fill",function(d,i){return color(i)});
var value=svg.selectAll("text.value1")
.data(dataset1)
.enter()
.append("text")
.attr("x",function(d,i){return i*w/dataset1.length})
.attr("y",function(d){return h-2*height-d*3-80})
.text(function(d){return d})
.attr("dx",w1/2)
.attr("dy","-1em")
.attr("text-anchor","middle")
.attr("fill",function(d,i){return color(i)});
svg.selectAll("text.title1")
.data(country1)
.enter()
.append("text")
.attr("font-size","13px")
.attr("x",function(d,i){
return (w/dataset1.length)*i;
})
.attr("y",h-2*height-70)
.attr("dx",(w/dataset1.length)/2-35)
.attr("dy","13px")
.text(function(d){
return d;
})
.attr("fill",function(d,i){return color(i)});
var w2=w/dataset2.length;
var rect=svg.selectAll("rect2")
.data(dataset2)
.enter()
.append("rect")
.attr("x",function(d,i){return i*w/dataset2.length})
.attr("y",function(d){return h-height-d*3-80})
.attr("width",w2*0.95)
.attr("height",function(d){return d*3})
.attr("fill",function(d,i){return color(i)});
var value=svg.selectAll("text.value2")
.data(dataset2)
.enter()
.append("text")
.attr("x",function(d,i){return i*w/dataset2.length})
.attr("y",function(d){return h-height-d*3-80})
.text(function(d){return d})
.attr("dx",w2/2)
.attr("dy","-1em")
.attr("text-anchor","middle")
.attr("fill",function(d,i){return color(i)});
svg.selectAll("text.title2")
.data(country2)
.enter()
.append("text")
.attr("font-size","13px")
.attr("x",function(d,i){
return (w/dataset2.length)*i;
})
.attr("y",h-height-70)
.attr("dx",(w/dataset2.length)/2-35)
.attr("dy","13px")
.text(function(d){
return d;
})
.attr("fill",function(d,i){return color(i)});
var w3=w/dataset31.length;
var rect=svg.selectAll("rect31")
.data(dataset31)
.enter()
.append("rect")
.attr("x",function(d,i){return i*w/dataset31.length+4;})
.attr("y",function(d){return h-d*3-80})
.attr("width",w3*0.4)
.attr("height",function(d){return d*3})
.attr("fill",function(d,i){return color(i)});
var value=svg.selectAll("text.value31")
.data(dataset31)
.enter()
.append("text")
.attr("x",function(d,i){return i*w/dataset31.length-w3/2+20;})
.attr("y",function(d){return h-d*3-80})
.text(function(d){return d})
.attr("dx",w3/2)
.attr("dy","-1em")
.attr("text-anchor","middle")
.attr("fill",function(d,i){return color(i)});
var rect=svg.selectAll("rect32")
.data(dataset32)
.enter()
.append("rect")
.attr("x",function(d,i){return i*w/dataset32.length+w3/2-4;})
.attr("y",function(d){return h-d*3-80})
.attr("width",w3*0.4)
.attr("height",function(d){return d*3})
.attr("fill",function(d,i){return color(i)});
var value=svg.selectAll("text.value32")
.data(dataset32)
.enter()
.append("text")
.attr("x",function(d,i){return i*w/dataset32.length+w3/2-30;})
.attr("y",function(d){return h-d*3-80})
.text(function(d){return d})
.attr("dx",w3/2)
.attr("dy","-1em")
.attr("text-anchor","middle")
.attr("fill",function(d,i){return color(i)});
svg.selectAll("text.title3")
.data(country3)
.enter()
.append("text")
.attr("font-size","13px")
.attr("x",function(d,i){
return (w/dataset31.length)*i;
})
.attr("y",h-70)
.attr("dx",(w/dataset31.length)/2-25)
.attr("dy","13px")
.text(function(d){
return d;
})
.attr("fill",function(d,i){return color(i)});
</script>
</body>
(3)实验结果