How to Fix Chart Legends Width-Height with Overflow Scroll in Chartjs

How to fix chart Legends width-height with overflow scroll in ChartJS

You can try one thing

Try to separate the legend into an different div. now you have full control of the div you can use custom placement and css of your own consider the following code :

 <div id="js-legend" class="chart-legend"></div>
document.getElementById('js-legend').innerHTML = myChart.generateLegend();

For reference see this FIDDLE

For handling legend interactive you need to extend the callback function and manipulate like this :

$("#js-legend > ul > li").on("click",function(e){
var index = $(this).index();
$(this).toggleClass("strike")
var ci = e.view.myChart;
var curr = ci.data.datasets[0]._meta[0].data[index];
curr.hidden = !curr.hidden
ci.update();
})

For Legend in action see this FIDDLE

Explanation :

I binded chart to window so that event view can get it, and later by the index manipulated the data and updated runtime used few css tricks to illustrate the strike effect.

ChartJS 2.6 - Bar chart fixed height scrollable-X

It seems to have something to do with the fact you're missing a wrapper around the canvas. Here's an updated version of your fiddle. I've added a function called addData that takes the number of new entries you want to add and the chart variable. It's not as good as it can be (because i'm not 100% sure how you want to add new data) but it's a great starting point. The trick is to not initialize the chart with all data included, you want to create the chart and then add to it later to expand the canvas, otherwise the initial render will work to fit all of the data in at that width.

https://jsfiddle.net/qmqmg82z/3/

Additional JavaScript code:

function addData(numData, chart){
for (var i = 0; i < numData; i++){
chart.data.datasets[0].data.push(Math.random() * 100);
chart.data.labels.push("Label" + i);
var newwidth = $('.chartAreaWrapper2').width() +60;
$('.chartAreaWrapper2').width(newwidth);
}
}

and then at the end of your page load function (or wherever you want to be adding new data) add this function call:

addData(5, chartFuelSpend);

But bear in mind this will require however much data you want to add and the chart instance.

And the HTML:

<div class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-FuelSpend" height="300" width="1200"></canvas>
</div>
</div>
<canvas id="axis-FuelSpend" height="300" width="0"></canvas>
</div>

I'm guessing the problem was that because the width of the single wrapper you had was changing along with the chart, it meant that the horizontal scroll wasn't being applied, this way the outer wrapper has the fixed width while the inside one and the canvas can expand.

Set height of chart in Chart.js

Seems like var ctx = $('#myChart'); is returning a list of elements. You would need to reference the first by using ctx[0].
Also height is a property, not a function.

I did it this way in my code:

var chartEl = document.getElementById("myChart");
chartEl.height = 500;

Chart.js legend took up too much spaces

First off, set canvas­'s width and height using it­'s native attributes (do not use style attribute), like so :

<canvas id="brandChart" width="700" height="350"></canvas>

note: width should be twice the height

Then, set responsive property to false in your chart options, as such :

options: {
responsive: false,
...
}

ᴅᴇᴍᴏ

var chart = new Chart(brandChart, {   type: 'doughnut',   data: {      labels: ['Etronin Home Appliances Service & trading Pte Ltd', 'Giant'],      datasets: [{         data: [30, 70],         backgroundColor: ['#2196f3', '#4caf50']      }]   },   options: {      responsive: false,      legend: {         display: true,         position: 'right',         onClick: null      },   }});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script><canvas id="brandChart" width="700" height="350"></canvas>

Chart.js max legend height

I managed to do a stupid little hack to get exactly what I wanted, and it's good enough for me, though it might be a little too hacky for other people's tastes:

Chart.Legend.prototype.afterFit = function () {
console.log('Before afterFit: ' + JSON.stringify(this.minSize) + ' ' + this.height);
this.minSize.height = this.height = 100;
console.log('After afterFit: ' + JSON.stringify(this.minSize) + ' ' + this.height);
}

console log is:

Before afterFit: {"width":1664,"height":527} 527
After afterFit: {"width":1664,"height":100} 100
Before afterFit: {"width":1664,"height":527} 527
After afterFit: {"width":1664,"height":100} 100

And the result:
Legend limited in height

I suppose to do this more cleanly, I should probably extend the Legend to override its afterFit behaviour. Will look into it, and I'll update here if it's possible to do it without too much hassle.

EDIT 19/10/2017:

Here is a "nicer" way to do this, which will look to a user like it was a built-in feature:

var origAfterFit = Chart.Legend.prototype.afterFit;
Chart.Legend.prototype.afterFit = function () {
origAfterFit.call(this);
if (this.options && this.options.maxSize) {
var maxSize = this.options.maxSize;
if (maxSize.height !== undefined) {
this.height = Math.min(this.height, maxSize.height);
this.minSize.height = Math.min(this.minSize.height, this.height);
}
if (maxSize.width !== undefined) {
this.width = Math.min(this.width, maxSize.width);
this.minSize.width = Math.min(this.minSize.width, this.width);
}
}
};

And example chart descriptor json:

{
"type" : "line",
"data" : {},
"options" : {
"legend" : {
"position" : "bottom",
"maxSize" : {
"height" : 200
},
"labels" : {
"usePointStyle" : true
}
}
}
}

How can I create a horizontal scrolling Chart.js line chart with a locked y axis?

Chart.js 2.7.2: https://jsfiddle.net/EmmaLouise/eb1aqpx8/3/

This approach handles different DPR settings and will scale the axis to match the scaling that Chart.js applies to its charts. It also calls .clearRect() on the original Y axis that Chart.js draws, clearing the pixels in the defined area which means that there is no duplication of axes or overlaps.

CSS:

.chartWrapper {
position: relative;
}

.chartWrapper > canvas {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
}

.chartAreaWrapper {
width: 600px;
overflow-x: scroll;
}

HTML

<div class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-Test" height="300" width="1200"></canvas>
</div>
</div>
<canvas id="axis-Test" height="300" width="0"></canvas>
</div>

JS:

    $(function () {
var rectangleSet = false;

var canvasTest = $('#chart-Test');
var chartTest = new Chart(canvasTest, {
type: 'bar',
data: chartData,
maintainAspectRatio: false,
responsive: true,
options: {
tooltips: {
titleFontSize: 0,
titleMarginBottom: 0,
bodyFontSize: 12
},
legend: {
display: false
},
scales: {
xAxes: [{
ticks: {
fontSize: 12,
display: false
}
}],
yAxes: [{
ticks: {
fontSize: 12,
beginAtZero: true
}
}]
},
animation: {
onComplete: function () {
if (!rectangleSet) {
var scale = window.devicePixelRatio;

var sourceCanvas = chartTest.chart.canvas;
var copyWidth = chartTest.scales['y-axis-0'].width - 10;
var copyHeight = chartTest.scales['y-axis-0'].height + chartTest.scales['y-axis-0'].top + 10;

var targetCtx = document.getElementById("axis-Test").getContext("2d");

targetCtx.scale(scale, scale);
targetCtx.canvas.width = copyWidth * scale;
targetCtx.canvas.height = copyHeight * scale;

targetCtx.canvas.style.width = `${copyWidth}px`;
targetCtx.canvas.style.height = `${copyHeight}px`;
targetCtx.drawImage(sourceCanvas, 0, 0, copyWidth * scale, copyHeight * scale, 0, 0, copyWidth * scale, copyHeight * scale);

var sourceCtx = sourceCanvas.getContext('2d');

// Normalize coordinate system to use css pixels.

sourceCtx.clearRect(0, 0, copyWidth * scale, copyHeight * scale);
rectangleSet = true;
}
},
onProgress: function () {
if (rectangleSet === true) {
var copyWidth = chartTest.scales['y-axis-0'].width;
var copyHeight = chartTest.scales['y-axis-0'].height + chartTest.scales['y-axis-0'].top + 10;

var sourceCtx = chartTest.chart.canvas.getContext('2d');
sourceCtx.clearRect(0, 0, copyWidth, copyHeight);
}
}
}
}
});

Chart.js making this chart more readable / scrollable

Chart.js doesn't support scrollable axis natively. ChartJs charts are responsive and change width according to parent container. You can do something like this :

<div class="chartWrapper">
<div class="chartAreaWrapper">
<canvas id="chart" height="400" width="15000"></canvas>
</div>
</div>

CSS

.chartWrapper {
position: relative;
}

.chartWrapper > canvas {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
}

.chartAreaWrapper {
width: 15000px;
overflow-x: scroll;
}

Finally, add this options object to your chart

options: {     
scales: {
xAxes: [{
ticks: {
padding: 20
}
}]
}}

Here is one more example on how you can make your chart scrollable



Related Topics



Leave a reply



Submit