这一章节介绍堆叠柱状图的画法,下面直接上图和数据。
1、准备数据
const stackBarData = [ { year: 2015, HW: 3740, XM: 920, MAC: 980, www: 490 }, { year: 2016, HW: 1400, XM: 1840, MAC: 960, www: 1400 }, { year: 2017, HW: 640, XM: 930, MAC: 620, www: 400 }, { year: 2018, HW: 920, XM: 480, MAC: 1600, www: 400 } ]; const stackBarKeys = Object.keys(stackBarData[0]).splice(1, 5);// 1、处理数据 const data = d3.stack() .keys(stackBarKeys) .order(d3.stackOrderNone)(stackBarData);
为了方便起见,这边在知道长度的情况下获取了每个柱子区间对应的label。
2、create dimensions
const dms = { width: 1400, height: 600, margin: { top: 50, right: 150, left: 30, bottom: 50 } } dms.innerWidth = dms.width - dms.margin.left - dms.margin.right; dms.innerHeight = dms.height - dms.margin.top - dms.margin.bottom;
3、draw canvas
const mainsvg = d3.select('#stack-bar') .append('svg') .attr('width', dms.width) .attr('height', dms.height) const maingroup = mainsvg.append('g') .attr('transform', `translate(${dms.margn.left}, ${dms.margin.top)`) const stackBarArea = maingroup.append('g') .attr('id', 'stack-bar-area')
4、create scale and color
const xScale = d3.scaleBand() .domain(stackBarData.map(d=>d.year)) .range([0, dms.innerWidth]) .padding(0.2) // 柱子之间的距离 const yScale = d3.scaleLinear() .domain([0, d3.max(data, d=>d3.max(d, subd =>subd[1]))]) .range([dms.innerHeight, 0]) .nice() const colors = d3.scaleOrdinal() .domain(stackBarKeys) .range(d3.schemeCategory10) // 10种颜色
5、draw data
const dataGroup = stackBarArea.selectAll('g') .data(data) .join('g') .attr('class', 'dataGroup') .attr('fill', d=>colors(d.key)) .attr('opacity', 0.8) dataGroup.selectAll('rect') .data(d=>d) .join('rect') .attr('class', 'datarect') .attr('x', d=>xScale(d.data.year)) .attr('y', d=>yScale(d[1])) .attr('width', xScale.bandwidth()) .attr('height', d=>yScale(d[0]) - yScale(d[1]))
6、create axes
const xAxis = d3.axisBottom(xScale) const xAxisGroup = maingroup.append('g') .call(xAxis) .attr('transform',`translate(0, ${dms.innerHeight})`) const yAxis = d3.axisLeft(yScale) const yAxisGroup = maingroup.append('g') .call(yAxis)
7、create legend
const legendArea = maingroup.append('g') .selectAll('g') .data(stackBarKeys) .join('g') .attr('class', 'legend') .attr('transform', (d, i) =>`translate(0, ${i * 22})`) legendArea.append('rect') .attr('x', dms.innerWidth + 5) .attr('width', 19) .attr('height', 16) .attr('fill', d=>colors(d)) .attr('opacity', 0.8) legendArea.append('text') .attr('x', dms.innerWidth + 28) .attr('y', 8) .attr('dy', '0.32em') .text(d=>d)
结束。