Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chartjs - keeping 2 graphs aligned side by side

Jsfiddle: http://jsfiddle.net/8gvkmLxL/

I have 2 bar graphs that are next to each other and I want them to be aligned relative to their x-axis. I'm having trouble achieving this as the graph height changes according to the length of the labels (see jsfiddle link). What's the best way to maintain consistency of height of the actual charts (as opposed to the canvas)

var data,ctx,mychart; 

data = {
    labels: ["Iantojones","Jackharkness","Owenharper"],
    datasets: [
        {
            label: "My First dataset",
            fillColor: "rgba(220,220,220,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: [50, 88, 15]
        }
    ]
};

ctx = document.getElementById("chart_a").getContext("2d");
mychart = new Chart(ctx).Bar(data);

data = {
    labels: ["Dmitri.Ivanovich.Mendeleev","Yuri.Alekseyevich.Gagarin","Alexey.Arkhipovich.Leonov"],
    datasets: [
        {
            label: "My First dataset",
            fillColor: "rgba(220,220,220,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: [50, 88, 15]
        }
    ]
};

ctx = document.getElementById("chart_b").getContext("2d");
mychart = new Chart(ctx).Bar(data);

data = {
    labels: ["Iantojones","Jackharkness","Owenharper"],
    datasets: [
        {
            label: "My First dataset",
            fillColor: "rgba(220,220,220,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: [50, 88, 15]
        }
    ]
};

ctx = document.getElementById("chart_c").getContext("2d");
mychart = new Chart(ctx).Bar(data);

data = {
    labels: ["Dmitri.Ivanovich","Yuri.Alekseyevich","Alexey.Arkhipovich"],
    datasets: [
        {
            label: "My First dataset",
            fillColor: "rgba(220,220,220,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: [50, 88, 15]
        }
    ]
};

ctx = document.getElementById("chart_d").getContext("2d");
mychart = new Chart(ctx).Bar(data);
#chart_a,
#chart_c {
    width: 320px;
    height: 200px;
}

#chart_b,
#chart_d {
    width: 320px;
    height: 350px;
}

.label {
    text-align: center; 
    width: 600px; 
    font-size: 20px; 
    font-weight: bold; 
    margin: 20px;
}

.chart_container {
    float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.js"></script>
<div id="aligned">
  <div class="label">Aligned</div>  
  <div class="chart_container">
    <canvas id="chart_a"></canvas>  
  </div>

  <div class="chart_container">
    <canvas id="chart_b"></canvas>  
  </div>
</div>

<div id="unaligned">
  <div class="label">Unligned</div>  
  <div class="chart_container">
    <canvas id="chart_c"></canvas>  
  </div>

  <div class="chart_container">
    <canvas id="chart_d"></canvas>  
  </div>
</div>
like image 658
redgetan Avatar asked Jun 17 '15 19:06

redgetan


People also ask

Which is better D3 or chart JS?

Chart. js provides a selection of ready to go charts which can be styled and configured while D3 offers building blocks which are combined to create virtually any data visualisation.

What is utils in ChartJS?

The Utils file contains multiple helper functions that the chart. js sample pages use to generate charts. These functions are subject to change, including but not limited to breaking changes without prior notice. Because of this please don't rely on this file in production environments.


1 Answers

A Bit of Hackery :-)

Chart.js calculates the top and bottom coordinates of the chart area and then uses this to draw the chart (points, bars, lines...). So if we manage to set / override the bottom coordinate of this chart area we can lift up / push down the x axis.

This bottom coordinate is in <<myChart instace>>.scale.endPoint. So if we overwrite this before the chart is drawn we have control over where the x axis is drawn.

To do this we create a new chart type and override the draw function, like this.

Chart.types.Bar.extend({
    name: "BarAlt",
    draw: function(){
        this.scale.endPoint = 200;
        Chart.types.Bar.prototype.draw.apply(this, arguments);
    }
});

Instead of passing in a hard coded value (200) we could configure this via options. So

Chart.types.Bar.extend({
    name: "BarAlt",
    draw: function(){
        this.scale.endPoint = this.options.endPoint;
        Chart.types.Bar.prototype.draw.apply(this, arguments);
    }
});

and

ctx = document.getElementById("chart_a").getContext("2d");
mychart1 = new Chart(ctx).BarAlt(data, {
    endPoint: 200
});

In fact, if we size both charts to be of the same height and width, we could even set this option to be same as the endPoint from the chart with the larger labels, thus aligning the x axis', like so

#chart_a,
#chart_b {
    width: 320px;
    height: 350px;
}

and assuming chart_b had the large labels and we drew that first (as myChart2)

ctx = document.getElementById("chart_a").getContext("2d");
mychart1 = new Chart(ctx).BarAlt(data, {
    endPoint: mychart2.scale.endPoint
});

(and we don't have to use BarAlt for myChart2 because we don't need to control it's x axis position)


Now, all seems well and good, except for the fact that the bars seem to be animating from the original postion, which is a bit ugly. So we put in the easiest fix we can think of - turn off the animation!

ctx = document.getElementById("chart_a").getContext("2d");
mychart1 = new Chart(ctx).BarAlt(data, {
    endPoint: mychart2.scale.endPoint,
    animation: false
});

Working fiddle - http://jsfiddle.net/2kmf10hg/

I took the liberty of removing the 2nd set of charts.

like image 147
potatopeelings Avatar answered Oct 06 '22 00:10

potatopeelings