数据可视化基础——js篇

目录

数据可视化

一、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;})//关系越多,结点越大
  •  添加结点名称:添加变量text
    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]%> ";
<%}
%>

  • 24
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值