D3.js学习(五)

上一节咱们已经学习了如何设置填充区域,其实理解了他的实现原理仍是很是简单了。这一节中, 咱们主要学习多条曲线的绘制,以及给不一样的曲线指定不一样的纵坐标。html

 

新的数据

因为咱们要画两条曲线,因此咱们要在原来的基础上新增一组测试数据,如今咱们的数据是这样的:app

date    close    open
1-May-12    58.13    3.41
30-Apr-12    53.98    4.55
27-Apr-12    67.00    6.78
26-Apr-12    89.70    7.85
25-Apr-12    99.00    8.92
24-Apr-12    130.28    9.92
23-Apr-12    166.70    10.13
20-Apr-12    234.98    12.23
19-Apr-12    345.44    13.45
18-Apr-12    443.34    16.04
17-Apr-12    543.70    18.03
16-Apr-12    580.13    21.02
13-Apr-12    605.23    22.34
12-Apr-12    622.77    20.15
11-Apr-12    626.20    21.26
10-Apr-12    628.44    31.04
9-Apr-12    636.23    35.04
5-Apr-12    633.68    41.02
4-Apr-12    624.31    43.05
3-Apr-12    629.32    46.03
2-Apr-12    618.63    51.03
30-Mar-12    599.55    53.42
29-Mar-12    609.86    57.82
28-Mar-12    617.62    59.01
27-Mar-12    614.48    56.03
26-Mar-12    606.98    58.01

咱们把data-close做为一个数据集,把data-open做为一个数据集。如今咱们把这些数据存在文件data2.tsv中,并将文件导入:
//Get the data
  d3.tsv("../data/data2.tsv", function(error, data){
    data.forEach(function(d){
      d.date = parseDate(d.date);
      d.close = +d.close;
      d.open = +d.open;
    });
在这里须要注意的是,记得要作一个数据的转换,确保d.open中存储的是一个数字!

定义新的曲线

像前面定义曲线同样,咱们定义次日曲线的时候彻底能够按照定义第一条曲线的方法进行定义:dom

//定义线条2
  var valueline2 = d3.svg.line()
    .interpolate("basis")
    .x(function(d){ return x(d.date) })
    .y(function(d){ return y(d.open) });

 

绘制新的曲线

为了区别于第一条曲线,咱们给新的曲线添加一个样式,把它变成抢眼的红色:svg

//绘制线条2
    svg.append("path")
      .attr("class", "line")
      .style("stroke", "red")
      .attr("d", valueline2(data));

 

这样,咱们的曲线就绘制成功啦,效果以下:
image学习

 

改进

虽然咱们已经把图形绘制出来,可是,咱们的代码仍是不完善的,比方说,若是个人d.open有个值很是很是大,他比d.close中的任何一个值都要大不少,那么咱们图形绘制出来会变成什么效果呢?
image测试

红色线条是否是跑到画布外面去了!也就是说咱们的画布已经没法容纳这个最大的d.open值了,由于咱们以前设置y轴的规模(domain)时用的是d.close的最大值:spa

 y.domain([0, d3.max(data, function(d){
      return d.close;
    })]);


因此,咱们要对它进行一个改进,咱们要取两组值中的最大值:3d

y.domain([0, d3.max(data, function(d){
      return Math.max(d.close, d.open);
    })]);
这样,咱们就解决了图像超出画布的问题了,不过咱们的数据怎么变化,都是适应的:

image

两条纵坐标轴

仔细观察原来的数据,咱们会发现,d.open的值相对于d.close的取发展趋势更加平稳。可是,若是咱们要更好的体现它的细节(也就是把趋势放大)的话改怎么作呢?很简单,给他们设置不一样的坐标轴!code

//定义坐标轴的范围
 
  var x = d3.time.scale().range([0, width]);
  var y = d3.scale.linear().range([height, 0]);
  var y2 = d3.scale.linear().range([height, 0]);

y跟y2的范围(也就是像素高)应该是同样的。咱们把y2的tick标签放在右边,这样看起来会更对称:orm

//定义坐标轴
  var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5);
  var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5);
  var y2Axis = d3.svg.axis().scale(y2).orient("right").ticks(5);

如今,咱们还须要修改一下咱们的valueline,让valueline2使用y2做为纵轴方向的基准:

//定义线条1
  var valueline = d3.svg.line()
    .interpolate("basis")
    .x(function(d){return x(d.date);})
    .y(function(d){return y(d.close);});
  //定义线条2
  var valueline2 = d3.svg.line()
    .interpolate("basis")
    .x(function(d){ return x(d.date) })
    .y(function(d){ return y2(d.open) });

同时,咱们还要给他们设置不一样的规模:

//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;
    })]);
    y2.domain([0, d3.max(data, function(d){
      return d.open;
    })]);

最后,咱们再来绘制它们!

//绘制x坐标轴
svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);
//绘制y坐标轴
svg.append("g")
  .attr("class", "y axis")
  .call(yAxis);
//绘制y2坐标轴
svg.append("g")
  .attr("class", "y axis")
  .attr("transform", "translate(" + width + ", 0)")
  .style("fill", "red")
  .call(y2Axis);

最后的效果以下:
image

 

下一节,咱们将学习如何x轴的tick标签不少的状况下,如何旋转标签,使他们更便于阅读!

相关文章
相关标签/搜索