• D3.js学习(一)


    从今天开始我将和大家一起学习D3.js(Data-Driven Documents),由于国内关于D3的学习资料少之又少,所以我觉得很有必要把自己学习过程记录下来,供同学们参考,如果文章有有哪些表达有错误的还希望同学们帮我指出来。当然了, 可以的话我希望大家都可以去看看英文资料(文章后面将列英文资源),毕竟那才是原汁原味的D3。 好了, 废话到此,下面我们开始我们的学习之旅吧!

    什么是D3.js?

    一句话:D3.js是一个操纵数据的javascript库!

    从一个简单的例子开始

    学习一个新的东西其实很简单,我们先来一个效果图,然后我们再一条条改它的语句,对比呈现的效果来学习这条属性的作用,好了,下面就是我们要做的:

    image

    看上去是不是挺复杂的呢?下面我们来看看他的源码到底是怎样的呢?

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Simple Graph</title>
        <style type = "text/css">
        body{ font: 12px Arial;}
        path{
            stroke: steelblue;
            stroke-width: 2;
            fill: none;
        }
        .axis path,
        .axis line{
            fill: none;
            stroke: grey;
            stroke-width: 1;
            shape-rendering: crispEdges;
        }
        </style>
        <script type="text/javascript" src="script/d3.v3.js"></script>
    </head>
    <body>
        
        <script type="text/javascript">
        var margin = {top:30, right:20, bottom: 30, left: 50};
        width = 600 - margin.left -margin.right;
        height = 270 - margin.top - margin.bottom;
     
        var parseDate = d3.time.format("%d-%b-%y").parse;
     
        var x = d3.time.scale().range([0, width]);
        var y = d3.scale.linear().range([height, 0]);
     
        var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5);
        var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5);
     
        //?
        var valueline = d3.svg.line()
            .x(function(d){return x(d.date);})
            .y(function(d){return y(d.close);});
     
        var svg = d3.select("body")
            .append("svg")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
            .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
     
        //Get the data
        d3.tsv("data/data.tsv", function(error, data){
            data.forEach(function(d){
                d.date = parseDate(d.date);
                d.close = +d.close;
            });
     
            //Scale(规模) the range of the data
            x.domain(d3.extent(data, function(d){
                return d.date;
            }));
            y.domain([0, d3.max(data, function(d){
                return d.close;
            })]);
     
            //Add the valueline path
            svg.append("path")
                .attr("d", valueline(data));
     
            //Add the X Axis
            svg.append("g")
                .attr("class", "x axis")
                .attr("transform", "translate(0," + height + ")")
                .call(xAxis);
            //Add the Y Axis
            svg.append("g")
                .attr("class", "y axis")
                .call(yAxis);
        });
     
        </script>
    </body>
    </html>

    看上去是不是很复杂的样子,不要怕,下面我们对他进行一块一块的解剖微笑

     

    HTML

    上面的代码包括样式和脚本两个部分,他的结构可以简化为:

    <!DOCTYPE html>
    <meta charset="utf-8">
    <style>
        The CSS 部分
    </style>
    <body>
    <script type="text/javascript" src="d3/d3.v3.js"></script>
    <script>
        The D3 JavaScript code is here
    </script>
    </body>

     

    CSS

    css部分主要是对元素设定样式,上面图表的CSS样式为

    body{ font: 12px Arial;}
    path{
        stroke: steelblue;
        stroke-width: 2;
        fill: none;
    }
    .axis path,
    .axis line{
        fill: none;
        stroke: grey;
        stroke-width: 1;
        shape-rendering: crispEdges;
    }

    我们可以改变其中的样式来改变图表的显示效果,比方说设置path{ stroke: red ; …}则效果曲线将变成红色

    image

    同样的,如果我更改fill为red,我们将得到红色的填充

    image

    其中"shape-rendering”是形状渲染属性,他一共有四个属性,值为“crispEdges”表示该形状将平滑显示。跟多的属性请同学学习SVG教程

     

    D3 JavaScript

    • 设置边距和图表大小。 我们设定画布的大小为:600,height:270,用一个margin对象来存储图表的边距信息,计算出图表的宽度和高度
      var margin = {top: 30, right: 20, bottom: 30, left: 50},
      width = 600 - margin.left - margin.right,
      height = 270 - margin.top - margin.bottom;
    • 下面我们先来看获取数据的方法
      //Get the data
          d3.tsv("data/data.tsv", function(error, data){
              data.forEach(function(d){
                  d.date = parseDate(d.date);
                  d.close = +d.close;
              });
     这里我们是从data.tsv这个文件中获取数据的,所谓tsv文件,简单来说就是用tab空格把数据分割开来的一种数据格式,比方说我们的data.tsv文件的部分数据就是这样的
    date    close
    1-May-12    58.13
    30-Apr-12    53.98
    27-Apr-12    67.00
    当然了,D3允许导入的数据不仅仅只是这一种文件格式,他支持的数据格式可以为:

    text: A plain old piece of text that has options to be encoded in a particular way

    json: This is the afore mentioned JavaScript Object Notation.
    xml: Extensible Markup Language is a language that is widely used for encoding documents in a human readable forrm.
    html: HyperText Markup Language is the language used for displaying web pages.
    csv: Comma Separated Values is a widely used format for storing data where plain text
    information is separated by (wait for it) commas.
    tsv: Tab Separated Values is a widely used format for storing data where plain text
    information is separated by a tab-stop character.

    data.forEach(function(d){

    上面这一行代码可以看做把数据分成了一行一行的形式,其中,每一行当中都有一个date和close值,并对没一行数据执行下面的处理:

    d.date = parseDate(d.date); --将d.date数据用前面定义的parseDate方法来格式化,将结果返回给d.date

    d.close = +d.close; --将d.close转化为一个数字

    var parseDate = d3.time.format("%d-%b-%y").parse;
    format()的格式有很多,我们可以根据自己的需要来设定自己的个格式,当然这里的格式要与文档数据中的格式对应哦,不过现在我遇到的问题是,如何让时间显示为中文?如果有同学知道,请告诉我,我将非常感谢!
    • 设置横轴方向和纵轴方向的区域(Domains)和范围(Ranges)
    var x = d3.time.scale().range([0, width]);
    var y = d3.scale.linear().range([height, 0]);
    这段代码是为了让我们导入的数据与图表的大小相适应,range知道是图表范围的大小,他是一个尺寸大小。这段代码告诉D3我们要画些东西在x轴上,这些东西是时间/日期的一个实体。
    x.domain(d3.extent(data, function(d) { return d.date; }));
    y.domain([0, d3.max(data, function(d) { return d.close; })]);
    而domain指的是数据的区域,extent返回的是最小的date到最大的date这样一个跨度,所以,最小的date就对应于上面range的最小值0,我们可以用一幅图来形象的表达:

    image
     
    • 设置坐标轴
    下面我们来分析这里几行代码:
    var xAxis = d3.svg.axis().scale(x)
    .orient("bottom").ticks(5);
    var yAxis = d3.svg.axis().scale(y)
    .orient("left").ticks(5);
    坐标轴axis初始化方法通过d3.svg.axis()来调用,然后调用.scale(x)用前面定义的x来给坐标轴设定刻度, .orient()设定刻度相对坐标轴的位置,.ticks()告诉D3在坐标轴上设定差不多几个刻度就够了,比方说你要D3给你的X轴设定大概10个刻度:var xAxis = d3.svg.axis().scale(x).orient(“bottom”).ticks(10),效果如下
    image
    • 为line()画线函数添加数据
    var valueline = d3.svg.line()
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y(d.close); });
    关于Line函数的使用可以参照这里
    • 添加画布
    var svg = d3.select("body")
    .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
    .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")"
    );
    d3.select(“body”)选择body元素,然后在body里面增加一个子元素”svg”,给这个svg设定一些属性,再往“svg”中添加一个”g”元素并设定一些属性。
     
    • 开始画东西啦
    svg.append("path") // Add the valueline path.
        .attr("d", valueline(data));
    我们再刚才创建的svg中添加一个path路径,让后用前面的定义的 valueline来绘制一条路径。然后我们再来绘制x轴和y轴
    svg.append("g") // Add the X Axis
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);
    svg.append("g") // Add the Y Axis
        .attr("class", "y axis")
        .call(yAxis);
    两个部分最后的.call()函数来定义前面的坐标轴初始化的方法来绘制坐标轴。

    OK!,到目前为止我们的目标已经达到了,最开始要达到的效果我们已经实现,但是还有很多东西我们还没有学会,比方说坐标轴的标签? 好吧,下一节我们再来给坐标轴添加标签!微笑

     

    相关资料:

    http://d3js.org/
    http://bost.ocks.org/mike/
    https://github.com/mbostock/d3/wiki
    https://groups.google.com/forum/?fromgroups#!forum/d3-js
    http://stackoverflow.com/questions/tagged/d3.js
    https://github.com/mbostock/d3/wiki/Gallery

  • 相关阅读:
    efibootmgr命令
    GPT+UEFI双系统引导
    关于元类的一些使用心得
    队列的数组实现
    队列的链表实现
    栈的链表实现
    栈的数组实现
    单链表实现基数排序
    多项式ADT加法乘法——单链表实现
    LeetCode: 476 Number Complement(easy)
  • 原文地址:https://www.cnblogs.com/MockingBirdHome/p/3368737.html
Copyright © 2020-2023  润新知