双条形图创建

时间:2018-05-13 10:24:12

标签: d3.js bar-chart data-visualization

我想创建一个这样的条形图:

enter image description here

有两个图表栏一个在另一个之下,第一个向上增长而第二个向下增长。 他们有不同的规模和数据。

这就是我创造的:

var doublebarSvg1 = d3.select('#doublebar')
    .append('svg')
    .attr('class', 'doublebarSvg1')
    .attr('width', 700)
    .attr('height', 400);

var doublebarSvg2 = d3.select('#doublebar')
    .append('svg')
    .attr('class', 'doublebarSvg2')
    .attr('width', 700)
    .attr('height', 400);

var margin = {top: 0, right: 0, bottom: 0, left: 50};

var width = doublebarSvg1.attr('width') - margin.left - margin.right;
var height = doublebarSvg1.attr('height') - margin.top - margin.bottom;

var x = d3.scaleBand()
    .rangeRound([0, width])
    .padding(0.1)
    .domain(years);

var y1 = d3.scaleLinear()
    .rangeRound([height, 0])
    .domain([0, 100]);

var y2 = d3.scaleSqrt()
    .rangeRound([height, 0])
    .domain([813, 0.1]); // max value 812.05 but domain is [0, 100000]

var doublebarSvgG1 = doublebarSvg1.append('g').attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
var doublebarSvgG2 = doublebarSvg2.append('g').attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');

////////////////////////////////////////////////////////////////////////
// Tooltip.
////////////////////////////////////////////////////////////////////////
var svgTip = doublebarSvg1.append('svg').attr('id', 'tooltip');

var tip = d3.tip()
    .attr('class', 'd3-tip')
    .offset([-5, 0])
    .html(function(d) {
        return '<div><span>Country:</span> <span style=\'color:white\'>' + d.country + '</span></div>' +
                 '<div><span>Perc:</span> <span style=\'color:white\'>' + d.perc + '%</span></div>' +
                 '<div><span>Rate:</span> <span style=\'color:white\'>' + d.rate + '%</span></div>';
    });
svgTip.call(tip);

////////////////////////////////////////////////////////////////////////
// Draw a single double bar
////////////////////////////////////////////////////////////////////////
makeDoublebar1();

function makeDoublebar1() {
    // define the axes
    var xAxis = d3.axisBottom(x); 
    var yAxis1 = d3.axisLeft(y1);

    // create x axis
    doublebarSvgG1.append('g')
        .attr('class', 'x axis')
        .attr('transform', 'translate(0, ' + height + ')') 
        .call(xAxis)
        .selectAll('text')  
        .style('text-anchor', 'end')
        .attr('dx', '-.8em')
        .attr('dy', '.15em')
        .attr('transform', 'rotate(-65)');

    // create y axis
    doublebarSvgG1.append('g')
        .attr('class', 'y axis')
        .call(yAxis1)
        .append('text')
        .attr('transform', 'rotate(-90)')
        .attr('y', 6)
        .attr('dy', '.71em')
        .style('text-anchor', 'end');

    // create bar rect
    doublebarSvgG1.selectAll('.bar')
        .data(testData1) //.data(covFiltered)
        .enter().append('rect')
        .attr('fill', 'steelblue')
        .attr('class', 'bar')
        .attr('x', function(d) {
            return x(d.year); 
        })
        .attr('y', function(d) { 
            if(isNaN(d.perc)) {
                d.perc = 0;
            }
            return y1(d.perc); 
        })
        .attr('width', x.bandwidth())
        .attr('height', function(d) { 
            if(isNaN(d.perc)) {
                d.perc = 0;
            }
            return height - y1(d.perc); 
        })
        .on('mouseover', function(d) {
            d3.select(this).attr('fill', 'darkblue');
            tip.show(d);
        })
        .on('mouseout', function(d) {
            d3.select(this).attr('fill', 'steelblue');
            tip.hide(d);
        });
}

////////////////////////////////////////////////////////////////////////
// Draw a single double bar
////////////////////////////////////////////////////////////////////////
makeDoublebar2();

function makeDoublebar2() {
    // define the axes
    var xAxis = d3.axisBottom(x); 
    var yAxis2 = d3.axisLeft(y2);

    // create x axis
    doublebarSvgG2.append('g')
        .attr('class', 'x axis')
        .attr('transform', 'translate(0, 0)') 
        .call(xAxis)
        .selectAll('text')  
        .style('text-anchor', 'end')
        .attr('dx', '-.8em')
        .attr('dy', '.15em')
        .attr('transform', 'rotate(-65)');

    // create y axis
    doublebarSvgG2.append('g')
        .attr('class', 'y axis')
        .call(yAxis2)
        .append('text')
        .style('text-anchor', 'end');

    // create bar rect
    doublebarSvgG2.selectAll('.bar')
        .data(testData2)
        .enter().append('rect')
        .attr('fill', 'tomato')
        .attr('class', 'bar')
        .attr('x', function(d) { // left start point
            return x(d.year); 
        })
        .attr('y', function(d) { // top start point
            if(isNaN(d.rate)) {
                d.rate = 0;
            }
            return 0; 
        })
        .attr('width', x.bandwidth())
        .attr('height', function(d) { 
            if(isNaN(d.rate)) {
                d.perc = 0;
            }
            return y2(d.rate); 
        })
        .on('mouseover', function(d) {
            d3.select(this).attr('fill', 'red');
            tip.show(d);
        })
        .on('mouseout', function(d) {
            d3.select(this).attr('fill', 'tomato');
            tip.hide(d);
        });
}

PLUNKER here

有一些问题:

  1. 如果我用.axis {display: initial;}替换.axis {display: none;},则所有轴都会消失,但我想要两个图表之间的水平线

  2. 我希望只有一个工具提示,当用户将鼠标悬停在任意栏上时,会显示一个显示percrate值的工具提示。

  3. 更重要的是,这是创建类似图表的最明智的方法吗?

0 个答案:

没有答案