D3实现分片柱状图

1.简要

在集成项目上做开发是,用到第三方提供的组件,组件不能满足X轴自定义的需求,于是被委派研究一下D3,看看D3有没有什么解决方案。

纵观D3的template,发现官方提供的模板并不能满足需求,D3的基本组件做的不是很好,或者说我研究的不够透彻,毕竟现在很多情况下

我们都是拿来主义,一旦一个组件能被使用便管不了许多,又由于项目赶时间,所以也就半透半熟的拿过来改吧改吧,先看一看效果图,由于

整个集成项目的背景和框架,这种风格还比较适合整个界面的风格,先看一看效果图


2.实现方法

D3提供的很多数据格式大部分都是通过CSV文件读取的,而这个文件在我们项目开发的时候不可能去单独创建生成这个文件,我们一般使用的都是实时从后台获取的数据(从后台读取在写到csv文件,前端再去读取这个文件,纯属是脱掉裤子放屁,多此一举。尽管D3提供了直接读取csv文件的方法,但是操作性太差,倒不如我们自己可以提供一种自己根据stack柱状图的格式要求在定义自己的返回格式,这样对于前后台的数据处理就相对来说简单多了)。下面就跟来看一下这种封装格式:
var dataset = [
                { name: "Success" ,
                  numbers: [	{ name:"Guest", value: 200 },
                        { name:"BYOD", value: 251 },
                        { name:"Corporate", value: 211 },
                        { name:"Unknown", value: 151 }
                        ] },
                { name: "Failure" ,    
		numbers: [{ name:"Guest", value: 354 },
{ name:"BYOD", value: 61 }, { name:"Corporate", value: 123 }, { name:"Unknown", value: 105 }] } ];

有没有感觉这种json的格式要比官方提供的csv格式的要舒服的多
书归正传,开始D3的stack之旅。

2.1 引入js文件

<script src="https://d3js.org/d3.v4.min.js"></script>
这个文件可以用官网的,也可以下载之后引入到html页面中

2.2 定义div

<div id="authentication_id"></div>

2.3 定义dataset 

//
      var width  = 1000;	//SVG width
      var height = 700;	//SVG height

      var svg = d3.select("#"+id)			//select div id
          .append("svg")
          .attr("width", width)	//set <svg> width
          .attr("height", height);//set <svg>height

      //1. init dataset
      var dataset = [
          { name: "Success" ,
              sales: [	{ year:"Guest", profit: 150 },
                  { year:"BYOD", profit: 321 },
                  { year:"Corporate", profit: 54 },
                  { year:"Unknown", profit: 123 }
                  ] },
          { name: "Failure" ,
              sales: [	{ year:"Guest", profit: 432 },
                  { year:"BYOD", profit: 321 },
                  { year:"Corporate", profit: 54 },
                  { year:"Unknown", profit: 105 }] }
      ];


      //2. change the data format which stack support
      var stack = d3.layout.stack()
          .values(function(d){ return d.sales; })
          .x(function(d){ return d.year; })
          .y(function(d){ return d.profit; });

      var data = stack(dataset);



      //3. draw

      //the outside border
      var padding = { left:150, right:100, top:30, bottom:30 };

      //set X-axis scale
      var xRangeWidth = width - padding.left - padding.right;

      var xScale = d3.scale.ordinal()
          .domain(data[0].sales.map(function(d){ return d.year; }))
          .rangeBands([0, xRangeWidth],0.3);

      //set y-axis scale

      //set Domain most value
      var maxProfit = d3.max(data[data.length-1].sales, function(d){
          return d.y0 + d.y;
      });

      //set range most value
      var yRangeWidth = height - padding.top - padding.bottom;

      var yScale = d3.scale.linear()
          .domain([0, maxProfit])		//Domain
          .range([0, yRangeWidth]);	//range


      //set color scale
      var color = d3.scale.category10();

      //add group element
      var groups = svg.selectAll("g")
          .data(data)
          .enter()
          .append("g")
          .style("fill",function(d,i){ return color(i); });

      //add rectangle
      var rects = groups.selectAll("rect")
          .data(function(d){ return d.sales; })
          .enter()
          .append("rect")
          .attr("x",function(d){ return xScale(d.year); })
          .attr("y",function(d){ return yRangeWidth - yScale( d.y0 + d.y ); })
          .attr("width",function(d){ return xScale.rangeBand(); })
          .attr("height",function(d){ return yScale(d.y); })
          .attr("transform","translate(" + padding.left + "," + padding.top + ")");

      //add axis
      var xAxis = d3.svg.axis()
          .scale(xScale)
          .orient("bottom");

      yScale.range([yRangeWidth, 0]);

      var yAxis = d3.svg.axis()
          .scale(yScale)
          .orient("left");

      svg.append("g")
          .attr("class","axis")
          .attr("transform","translate(" + padding.left + "," + (height - padding.bottom) +  ")")
          .call(xAxis);

      svg.append("g")
          .attr("class","axis")
          .attr("transform","translate(" + padding.left + "," + (height - padding.bottom - yRangeWidth) +  ")")
          .call(yAxis);

      //add group tabs
      var labHeight = 50;
      var labRadius = 10;

      var labelCircle = groups.append("circle")
          .attr("cx",function(d){ return width - padding.right*0.98; })
          .attr("cy",function(d,i){ return padding.top * 2 + labHeight * i; })
          .attr("r",labRadius);

      var labelText = groups.append("text")
          .attr("x",function(d){ return width - padding.right*0.8; })
          .attr("y",function(d,i){ return padding.top * 2 + labHeight * i; })
          .attr("dy",labRadius/2)
          .text(function(d){ return d.name; });


这样就可以实现我们要的效果



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值