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" ,
{ name:"BYOD", value: 61 }, { name:"Corporate", value: 123 }, { name:"Unknown", value: 105 }] } ];numbers: [{ name:"Guest", value: 354 },
有没有感觉这种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; });