How do I hide line outside the min/max (scale area) in chartjs 2.0? - chart.js

How can i hide the line (in chartjs 2.x) as soon it goes outside the scale boundries?
i came across this question/answer:
How do I hide values past the x-axis in chartjs 2.0?
There they will filter all points outside the scale boundries. But that will only work if you have a point on the min/max, and the curve of the line (if any) will not be correct.
In my situation there isn't always a point for the min and/or max and line is also curved.
I have a situation like this jsfiddle:
https://jsfiddle.net/gyotsv07/1/
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="robots" content="noindex, nofollow">
<meta name="googlebot" content="noindex, nofollow">
<script type="text/javascript" src="/js/lib/dummy.js"></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.2/Chart.min.js"></script>
</head>
<body><iframe class="chartjs-hidden-iframe" tabindex="-1" style="width: 100%; display: block; border: 0px; height: 0px; margin: 0px; position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px;"></iframe>
<canvas id="canvas" height="566" style="display: block; width: 849px; height: 566px;" width="849"></canvas>
<script>
var ctx = document.getElementById("canvas").getContext("2d");
/*
var cleanOutPlugin = {
beforeInit: function(chart) {
// Replace `ticks.min` by `time.min` if time-type chart
var min = chart.config.options.scales.xAxes[0].ticks.min;
// Same here with `ticks.max`
var max = chart.config.options.scales.xAxes[0].ticks.max;
var ticks = chart.config.data.labels;
var idxMin = ticks.indexOf(min);
var idxMax = ticks.indexOf(max);
if (idxMin == -1 || idxMax == -1)
return;
var data = chart.config.data.datasets[0].data;
data.splice(idxMax + 1, ticks.length - idxMax);
data.splice(0, idxMin);
ticks.splice(idxMax + 1, ticks.length - idxMax);
ticks.splice(0, idxMin);
}
};
Chart.pluginService.register(cleanOutPlugin);*/
var scatterChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Scatter Dataset',
data: [{
x: -10,
y: 0
}, {
x: 0,
y: 6
}, {
x: 10,
y: 5
}]
}]
},
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'bottom',
ticks: {
min: -5,
max: 5
}
}]
}
}
});
</script>
</body></html>
is there a solution to prevent drawing outside the scale boundries?

A quick fix to your issue is to remove everything drawn outside of the chart surface.
The following plugin can help you doing it :
Chart.plugins.register({
beforeDatasetsDraw: function(chartInstance) {
var ctx = chartInstance.chart.ctx;
var chartArea = chartInstance.chartArea;
ctx.save();
ctx.beginPath();
ctx.rect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
ctx.clip();
},
afterDatasetsDraw: function(chartInstance) {
chartInstance.chart.ctx.restore();
},
});
Check your updated fiddle here and its result :

Related

Chartjs and (more compact) title placement

I am using Chartjs for some simple gauges (using pie chart) but when adding the title it is quite far apart and padding doesn't seem to help me :-( Does anyone know a way of placing the title closer to the gauge/pie chart ?
image of title in pie/gauge chart here
var ctx103 = document.getElementById('chart103').getContext('2d');
new Chart(ctx103, {
type: 'doughnut',
data: {
datasets: [{
//label: '# of Votes',
data: [80, 20],
backgroundColor: ["green", "grey"]
}]
},
options: {
rotation: 270, // start angle in degrees
circumference: 180, // sweep angle in degrees
plugins: {
title: {
display: true,
position: 'top',
text: 'TITLE !!!!!',
padding: {
top: 0,
bottom: 0
}
}
}
}
});
I have been trying different padding options but that just moves the title further away ...
While this may not work for your specific application, in some cases this can be achieved using HTML/CSS.
This is the styling I used:
<style>
#titleAndChart {
margin: 0;
position: absolute;
height: 600px;
width: 600px;
box-sizing: border-box;
}
#titleDiv {
position: absolute;
top: 0px;
left: 0px;
width: 600px;
}
#chartDiv {
position: absolute;
top: 60px;
left: 0px;
width: 600px;
}
</style>
The HTML layout then becomes:
<div id="titleAndChart">
<div id="titleDiv">
Chart title goes here
</div>
<div id='chartDiv'>
<canvas id="myChart"></canvas>
</div>
</div>
And the chart itself looks like this:
Chart.defaults.doughnut.circumference = Math.PI;
Chart.defaults.doughnut.rotation = -1 * Math.PI;
new Chart(document.getElementById('myChart'), {
type: 'doughnut',
options: {
legend: {
display: false,
}
},
data: {
labels: ['Red','Green'],
datasets: [{
data: [25,75],
backgroundColor: ['red','green']
}]
}
});
Here's a fiddle using ChartJS v2.9.4:
https://jsfiddle.net/hdahle/4x670et8/
And here's a fiddle using ChartJS v4.0.1
https://jsfiddle.net/hdahle/k8zxvjyq/

chartjs datalabels not showing anything with django template

I tried so many time to ask this question but no one was able to help me so I decided to deleted the previous question and reask with taking into considerations the answers that I received.
I have this chart created with chartjs, as you can see you can hover over points to see their coordinated or data, I would like to have an option to show them without having to hover. The reason why I want to do this is because I am going to add export to pdf, and it exports whatever it can see on the HTML , and exporting a chart without its values would be unreadable to the end user.
Note (I don't know if this matters but I am using django and I did not do any npm installation of datalabels)
Another Note : I was told that I have to register the plugin before using it, with
Chart.register(ChartDataLabels); but adding it the chart script just causes the chart to disappear.
.cann {
border: 3px solid darkgrey;
padding: 10px;
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
transition: all 0.3s cubic-bezier(.25,.8,.25,1);
width: 650px;
height: 250px;
margin-left: 3em;
}
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- semantic UI -->
<link rel="stylesheet" type='text/css' href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.14/semantic.min.css">
<!--Chart js-->
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.0.0-alpha"> </script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0-rc"></script>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function (){
Chart.register(ChartDataLabels);
var ctx = document.getElementById('myChart');
window.myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
data: [12, 19, 3, 5, 2, 3],
label: 'Advisor Closed MTD',
backgroundColor: 'rgb(192,111,94)',
barThickness: 25,
datalabels: {
color: '#FFCE56'
}
}],
},
options: {
responsive: false,
plugins: {
datalabels: {
anchor: 'end',
align: 'end',
labels: {
value: {
color: 'blue'
}
}
}
}
}
}
);
});
</script>
<canvas id="myChart" class="cann"></canvas>
How about instead of reposting and deleting you post each time so people dont know whats wrong you actually keep your post so people can actually help you because with what you provide its working fine, chart shows, with register the plugin shows so unless you point out where its going bad and people can see it you wont get any better answers
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.2.1">
</script>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0-rc"></script>
<canvas id="turn_over_line" class="cann"></canvas>
<script>
// Turn over line chart
$(document).ready(function() {
Chart.register(ChartDataLabels);
var ctx = document.getElementById('turn_over_line');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [0, 1, 2, 3, 2, 3, 0.5, 8, 4, 2],
datasets: [{
backgroundColor: '#ccddee',
borderColor: '#5566aa',
data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}]
},
options: {
legend: false,
tooltip: false,
plugins: {
datalabels: {
align: function(context) {
var index = context.dataIndex;
var value = context.dataset.data[index];
var invert = Math.abs(value) <= 1;
return value < 1 ? 'end' : 'start'
},
anchor: 'end',
backgroundColor: null,
borderColor: null,
borderRadius: 4,
borderWidth: 1,
color: '#223388',
font: {
size: 11,
weight: 600
},
offset: 4,
padding: 0,
formatter: function(value) {
return Math.round(value * 10) / 10
}
}
}
}
});
})
</script>
Actually my code was perfectly fine, I appreciate the effort of the guy who kept posting the same answer that did not help, I finally figured out that the issue is in my chartjs version , so if you are facing the same issue with chartjs 3.0.0-alpha , 3.2.1 seemed to fix it for me.

Google pie chart vs old flot chart

I have an old pie chart with jquery flot.
And if my series values are:
Apples: 1070
Bananas: 2127
And pie chart looks like
2127 / 1070
Currently, I have google pie chart. And, as i understand, counting happens other way:
(1070 + 2127) / 1070
and
(1070 + 2127) / 2127.
Thus chart looks different.
Is there any way to display values like in an old flot pie?
not sure how the data is being loaded,
but the following two examples look the same to me...
flot
$(document).ready(function() {
var data = [
{label: 'Apples', data: 1070, color: '#e1ab0b'},
{label: 'Bananas', data: 2127, color: '#fe0000'}
];
$.plot($("#chart-flot"), data, {
series: {
pie: {
show: true
}
}
});
});
body, html, .chart {
height: 100%;
margin: 0px;
padding: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/flot/0.8.3/jquery.flot.pie.min.js"></script>
<div id="chart-flot" class="chart"></div>
google
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Apples', 1070],
['Bananas', 2127]
]);
var options = {
chartArea: {
height: '100%',
width: '100%',
top: 16,
left: 16,
right: 16,
bottom: 16
},
colors: ['#e1ab0b', '#fe0000'],
height: '100%',
legend: {
position: 'top',
alignment: 'end'
},
width: '100%'
};
var chart = new google.visualization.PieChart(document.getElementById('chart-google'));
chart.draw(data, options);
});
body, html, .chart {
height: 100%;
margin: 0px;
padding: 0px;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart-google" class="chart"></div>

display total in center of donut pie chart using google charts?

I am new to angularjs and google charts i made a pie chart now i want following:
1- display total components inside the centre of the pie charts.
2- display pieSliceText outer side of the pie slice
you can see the
this is what i want:
how can this be done
my sample code:
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.1','packages':['corechart']}]}"> </script>
<div id="piechart" style="width: 900px; height: 500px;"></div>
javascript:
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 11],
['Eat', 2],
['Commute', 2],
['Watch TV', 2],
['Sleep', 7]
]);
var options = {
height: 360,
width: 360,
pieHole: 0.5,
showLables: 'true',
pieSliceText: 'value',
pieSliceTextStyle: {
color: 'white',
fontSize:18
},
legend: {
position: 'right',
alignment: 'center'
},
chartArea: {
left: 10,
top: 10,
width: '130%',
height: '65%'
},
tooltip: {
trigger:'none'
}
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
OK, try this http://jsfiddle.net/L1tct3Lv/3/ ... its a fast hack but you could certainly vastly improve it by calculating the positions based on sizes and such.
google.setOnLoadCallback(drawChart);
<!-- This generates the google chart -->
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Task', 'Hours per Day'],
['Work', 11],
['Eat', 2],
['Commute', 2],
['Watch TV', 2],
['Sleep', 7]
]);
var options = {
height: 360,
width: 360,
pieHole: 0.8,
showLables: 'true',
pieSliceText: 'value',
pieSliceTextStyle: {
color: 'white',
fontSize:18
},
legend: {
position: 'right',
alignment: 'center'
},
chartArea: {
left: 10,
top: 10,
width: '130%',
height: '65%'
},
tooltip: {
trigger:'none'
}
};
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
jQuery('#cnt').text(data.Gf.length);
chart.draw(data, options);
}
Setting up a few overlays like this:
<div id="JSFiddle">
<div id="chart_div"></div>
<div id="cnt" class="overlay"></div>
<div class="overlay-label">total components</div>
</div>
With this css:
#JSFiddle {
position: relative;
}
.overlay {
display:block;
width:240px;
height:240px;
text-align:center;
vertical-align: middle;
position: absolute;
top: 0px; /* chartArea top */
left: 0px; /* chartArea left */
font-size: 80px;
margin-top: 60px;
}
.overlay-label{
display:block;
width:240px;
height:240px;
text-align:center;
vertical-align: middle;
position: absolute;
top: 0px; /* chartArea top */
left: 0px; /* chartArea left */
margin-top: 140px;
font-size: 20px;
}
Result is this:
Researching about this I found this link: https://codepen.io/cireriddler/pen/yyeLpE
This code isn't my, but I think that he answers the problem splitting the chart from the info inside chart.
Example:
<div id="donutchart" class="col-xs-12 col-sm-6 col-md-4">
<div id="chart"></div>
<div id="labelOverlay">
<p class="used-size">90<span>%</span></p>
<p class="total-size">de economia mensal</p>
</div>
</div>

Merge Jquery Knob Functionality in Chart Js

I am using Doughnut Chart of ChartJS, and here is my code
<!doctype html>
<html>
<head>
<title>Doughnut Chart</title>
<script src="jquery-1.11.3.min.js"></script>
<script src="jquery.knob.js"></script>
<script src="../Chart.js"></script>
<style>
body{
padding: 0;
margin: 0;
}
#canvas-holder{
width:30%;
}
</style>
</head>
<body>
<div id="canvas-holder">
<canvas id="chart-area" width="250" class="knob" height="250"/>
</div>
<script>
var doughnutData = [
{
value: 200,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 200,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green"
},
{
value: 200,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#4D5360",
highlight: "#616774",
label: "Dark Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 200,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
}
];
var options = {
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke : true,
//String - The colour of each segment stroke
segmentStrokeColor : "#fff",
//Number - The width of each segment stroke
segmentStrokeWidth : 0,
//Number - The percentage of the chart that we cut out of the middle
percentageInnerCutout : 80, // This is 0 for Pie charts
//Number - Amount of animation steps
animationSteps : 100,
//String - Animation easing effect
animationEasing : "easeOutBounce",
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true,
//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false,
showTooltips: false
}
window.onload = function(){
var ctx = document.getElementById("chart-area").getContext("2d");
var myDoughnut = new Chart(ctx).Doughnut(doughnutData, options);
$("#chart-area").click( function(evt){
var activePoints = myDoughnut.getSegmentsAtEvent(evt);
/* do something */
}
);
};
</script>
</body>
</html>
There is a requirement to update the value while clicking on the canvas, in the middle of doughnut chart (Just like in Jquery Knob http://anthonyterrien.com/knob/) i.e the value updates on sliding as well as clicking on the canvas. Is there any way to merge the functionality of these two libraries
It would be better to use that control. That said, you could do it Chart.js too. Here is a fair approximation (note that I've used jQuery for some parts, but you could do the same using plain javascript).
CSS
<style>
.myChartWrapper {
position: relative;
display: inline-block;
}
.myChartValue {
border: none;
font-family: 'Helvetica';
font-size: 20px;
overflow: visible;
width: 2em;
white-space: nowrap;
text-align: center;
position: absolute;
background-color: transparent;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.myChartValue::-ms-clear {
display: none;
}
</style>
HTML
<div class="myChartWrapper">
<canvas id="myChart"></canvas>
<input id="myChartValue" class="myChartValue" />
</div>
Javascript
var value = 20;
var MAX = 200;
var STEP = 1;
var HALFSETCOLOR = "rgba(154, 225, 254, 1)";
var SETCOLOR = "rgba(134, 205, 234, 1)";
var UNSETCOLOR = "rgba(237, 237, 237, 1)";
var data = [];
for (var i = 0; i < MAX; i = i + STEP) {
data.push({
value: STEP,
color: (i < value) ? SETCOLOR : UNSETCOLOR,
label: i
})
}
var canvas = document.getElementById("myChart");
var ctx = canvas.getContext("2d");
var myDoughnutChart = new Chart(ctx).Doughnut(data, {
animation: false,
segmentShowStroke: false,
showTooltips: false
});
$("#myChartValue").val(value);
// half set the sectors
canvas.onmousedown = function (evt) {
var activeSegments = myDoughnutChart.getSegmentsAtEvent(evt);
if (activeSegments.length) {
var value = Number(activeSegments[0].label);
var crossed = false;
myDoughnutChart.segments.forEach(function (segment) {
if (Number(segment.label) >= value)
crossed = true;
if (!crossed && segment.fillColor !== SETCOLOR)
segment.fillColor = HALFSETCOLOR;
else if (crossed && segment.fillColor !== UNSETCOLOR)
segment.fillColor = HALFSETCOLOR;
})
myDoughnutChart.update()
myDoughnutChart.value = value;
$("#myChartValue").val(value);
}
};
canvas.onmousemove = function (evt) {
if (myDoughnutChart.value !== undefined) {
canvas.onmousedown(evt)
}
}
// set / unset sectors
canvas.onmouseup = function () {
var value = myDoughnutChart.value;
if (value !== undefined) {
var crossed = false;
myDoughnutChart.segments.forEach(function (segment, i) {
if (Number(segment.label) >= value)
crossed = true;
if (!crossed)
segment.fillColor = SETCOLOR;
else if (crossed)
segment.fillColor = UNSETCOLOR;
})
myDoughnutChart.value = undefined;
myDoughnutChart.update()
}
};
$("#myChartValue").on("change", function () {
myDoughnutChart.value = Number($("#myChartValue").val());
canvas.onmouseup();
})
It could do with a bit of cleanup (like handling change in direction without lifting the mouse), but comes pretty close to the knob functionality without too much effort.
Fiddle - http://jsfiddle.net/rxrxLo33/