I'm using AdminLTE and chart.js for pie charts. The question is, can i make the text visible for each arc in the pie chart without hovering mouse?
I don't use legends because some chart have a lot of labels in it.
If you have any other ways to show the all text labels i would appreciate it.
This is my current script for all my pie charts
<script>
$(function () {
//-------------
//- PIE CHART -
//-------------
// Get context with jQuery - using jQuery's .get() method.
var pieChartCanvas = $('#pieChart').get(0).getContext('2d')
var pieChart = new Chart(pieChartCanvas)
var PieData = [<?php echo $isiData; ?>]
var pieOptions = {
//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 : 2,
//Number - The percentage of the chart that we cut out of the middle
percentageInnerCutout: 0, // This is 0 for Pie charts
//Number - Amount of animation steps
animationSteps : 150,
//String - Animation easing effect
animationEasing : 'easeOutBack',
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true,
//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false,
//Boolean - whether to make the chart responsive to window resizing
responsive : true,
// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
maintainAspectRatio : true,
//String - A legend template
legendTemplate : '<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'
}
//Create pie or douhnut chart
// You can switch between pie and douhnut using the method below.
pieChart.Doughnut(PieData, pieOptions)
})
</script>
<canvas id="pieChart" style="height:400px;"></canvas>
I've had a great time on google with this problem..
Basically the way other developers solve your problem was creating a plugin which makes all the tooltips show up after the render
I found a fiddle that fixes this problem..
The fiddle is not mine..
Credits goes to Suhaib Janjua
// Show tooltips always even the stats are zero
Chart.pluginService.register({
beforeRender: function(chart) {
if (chart.config.options.showAllTooltips) {
// create an array of tooltips
// we can't use the chart tooltip because there is only one tooltip per chart
chart.pluginTooltips = [];
chart.config.data.datasets.forEach(function(dataset, i) {
chart.getDatasetMeta(i).data.forEach(function(sector, j) {
chart.pluginTooltips.push(new Chart.Tooltip({
_chart: chart.chart,
_chartInstance: chart,
_data: chart.data,
_options: chart.options.tooltips,
_active: [sector]
}, chart));
});
});
// turn off normal tooltips
chart.options.tooltips.enabled = false;
}
},
afterDraw: function(chart, easing) {
if (chart.config.options.showAllTooltips) {
// we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
if (!chart.allTooltipsOnce) {
if (easing !== 1)
return;
chart.allTooltipsOnce = true;
}
// turn on tooltips
chart.options.tooltips.enabled = true;
Chart.helpers.each(chart.pluginTooltips, function(tooltip) {
tooltip.initialize();
tooltip.update();
// we don't actually need this since we are not animating tooltips
tooltip.pivot();
tooltip.transition(easing).draw();
});
chart.options.tooltips.enabled = false;
}
}
});
// Show tooltips always even the stats are zero
var canvas = $('#myCanvas2').get(0).getContext('2d');
var doughnutChart = new Chart(canvas, {
type: 'doughnut',
data: {
labels: [
"Success",
"Failure"
],
datasets: [{
data: [45, 9],
backgroundColor: [
"#1ABC9C",
"#566573"
],
hoverBackgroundColor: [
"#148F77",
"#273746"
]
}]
},
options: {
// In options, just use the following line to show all the tooltips
showAllTooltips: true
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<canvas id="myCanvas2" width="350" height="296"></canvas>
</div>
I use onclick event and bootstrap modal for this issue and disabled Tooltip.
,onClick: function(c,i) {
e = i[0];
var x_value = this.data.labels[e._index];
var ID = x_value;
var Type =1;
$.ajax({
url: 'getsearchresults.asmx/ChartDetayGetir',
data: "{ 'ID': '" + ID + "',type:'"+Type+"'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
document.getElementById("modalheader").innerHTML = x_value;
document.getElementById("modalbody").innerHTML = data.d;
$('#myModal').modal();
},
error: function (response) {
alert(response.responseText);
},
failure: function (response) {
alert('Failure');
}
});
}
Related
Here is the jsfiddle Code reproduction,
I am using Highcharts to plot an area graph, how do I do the below ?
I need to move the y-axis labels to the right
Plot Area chart of 3 colors ['#762232', '#EFCA32', '#007788'] with their respective values.
Expected Output
Set yAxis.opposite to true.
Add two more series and use tickPositioner to show thier last values as labels.
yAxis: {
opposite: true,
showFirstLabel: false,
showLastLabel: false,
tickPositioner: function() {
var prevTickPos = this.tickPositions,
tickPositions = [prevTickPos[0], prevTickPos[prevTickPos.length - 1]],
series = this.chart.series;
series.forEach(function(s) {
tickPositions.push(s.processedYData[s.processedYData.length - 1]);
});
tickPositions.sort(function(a, b) {
return a - b;
});
return tickPositions;
},
...
}
Live demo: https://jsfiddle.net/BlackLabel/gk1t6cp2/
API Refernce: https://api.highcharts.com/highcharts/yAxis.opposite
// ignore this comment - required to post the following jsfiddle.net link!
Please see https://jsfiddle.net/68bf25vh/
If you click a doughnut segment, the corresponding tooltip displays, which is the correct functionality.
The problem is triggering this desired functionality when a user clicks one of the buttons below the doughnut. E.g. when a user clicks the 'Trigger Segment 1 Click' button. The tooltip should display above segment 1 (just as if the user had clicked segment 1).
A bonus would be having the tooltip displaying above segment 1 initially too, but not essential.
Any help much appreciated :)
Please note
Using Chart.js v 2.5.0. I've read a few articles suggesting to use a showTooltip() method, e.g. chart.showTooltip([chart.segments[0]], true); Unfortunately this method does not exist in this version.
Found this https://stackoverflow.com/a/37989832, but this displays all tooltips. Just want the tooltip of the active (current) segment to display.
You can use the following function to display corresponding tooltip, when clicked on an external button :
function showTooltip(chart, index) {
var segment = chart.getDatasetMeta(0).data[index];
chart.tooltip._active = [segment];
chart.tooltip.update();
chart.draw();
}
When calling the function, pass chart-instance and button-index as the first and second argument respectively.
BONUS :
To initially show the tooltip of segment-1, add the following config in your chart options :
animation: {
onComplete: function() {
if (!isChartRendered) {
showTooltip(myChart, 0);
isChartRendered = true;
}
}
}
* declare a variable named isChartRendered in global-scope and set it to false
ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ ⧩
var isChartRendered = false;
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Segment 1', 'Segment 2', 'Segment 3'],
datasets: [{
data: [10, 10, 10]
}]
},
options: {
events: ['click'],
cutoutPercentage: 70,
legend: {
display: false
},
tooltips: {
displayColors: false
},
onClick: function(evt, elements) {},
// BONUS: show segment 1 tooltip initially
animation: {
onComplete: function() {
if (!isChartRendered) {
showTooltip(myChart, 0);
isChartRendered = true;
}
}
}
}
});
$(document).on('click', 'button', function() {
var $this = $(this),
index = $this.index();
showTooltip(myChart, index);
});
function showTooltip(chart, index) {
var segment = chart.getDatasetMeta(0).data[index];
chart.tooltip._active = [segment];
chart.tooltip.update();
chart.draw();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="width:400px;height:400px;">
<canvas id="myChart"></canvas>
</div>
<div style="margin-top:50px;">
<button>Trigger Segment 1 Click</button>
<button>Trigger Segment 2 Click</button>
<button>Trigger Segment 3 Click</button>
</div>
For Chart.js 3 the GRUNT`s solution needs some modifications:
chart.tooltip.setActiveElements([{datasetIndex: 0, index: index}]);
chart.tooltip.update();
chart.render();
If you want to change also the segment style:
const activeSegment = chart.getDatasetMeta(0).data[index];
chart.updateHoverStyle([{element: activeSegment, datasetIndex: 0}], null, true);
I am having a problem with chartjs. I just
want to print what is inside div#browser with a pie chart. The chart
was fine and animated but the problem is during I print it the pie
chart disappears but when I refresh again it it was just fine. The
other charts works fine in printing except the pie chart. I believe
its reason is in the animation or something
The chartjs script
<script>
var pieChartCanvas = $("#pieChart").get(0).getContext("2d");
var pieChart = new Chart(pieChartCanvas);
var PieData = [
{
value: 700,
color: "#f56954",
highlight: "
#f56954",
label: "Chrome"
},
{
value: 500,
color: "#00a65a",
highlight: "#00a65a",
label: "IE"
},
{
value: 400,
color: "#f39c12",
highlight: "#f39c12",
label: "FireFox"
},
{
value: 600,
color: "#00c0ef",
highlight: "#00c0ef",
label: "Safari"
},
{
value: 300,
color: "#3c8dbc",
highlight: "#3c8dbc",
label: "Opera"
},
{
value: 100,
color: "#d2d6de",
highlight: "#d2d6de",
label: "Navigator"
}
];
var pieOptions = {
//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: 1,
//Number - The percentage of the chart that we cut out of the middle
percentageInnerCutout: 50, // 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,
//Boolean - whether to make the chart responsive to window resizing
responsive: true,
// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
maintainAspectRatio: false,
//String - A legend template
legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>",
//String - A tooltip template
tooltipTemplate: "<%=value %> <%=label%> users"
};
//Create pie or douhnut chart
// You can switch between pie and douhnut using the method below.
pieChart.Doughnut(PieData, pieOptions);
</script>
The html
<div id="browser">
<h3 class="box-title">Browser Usage</h3>
<a onclick="printContent('browser')">Print</a>
<div class="chart-responsive">
<canvas id="pieChart" height="150"></canvas>
</div>
</div>
Print script
<script>
function printContent(el){
var restorepage = document.body.innerHTML;
var printcontent = document.getElementById(el).innerHTML;
document.body.innerHTML = printcontent;
window.print();
document.body.innerHTML = restorepage;
}
</script>
Try using the .toDataURL() method on your canvas. This method returns a URL containing your chart as an image.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
Grab your pie chart's canvas and convert it to an image: document.getElementbyId('pieChart').toDataURL;
Assign the generated chart image URL to a variable, let's keep using printContents in this case: let **printContents** = document.getElementbyId('pieChart').toDataURL;
Initiate an html document on the fly and append the previously created image URL as an <img> element's source, using template literals to embed the printContents variable: let html = <html><head><title></title></head><body><img src=${printContent}></body></html>
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
-Execute the print job (Chrome) by writing the previously constructed html doc to the print window on the fly:
let **printWindow** = window.open('', 'Print-Preview', 'height=900,width=200');
printWindow.document.open();
printwindow.document.write(html);
printWindow.document.close();
Yes, it has to do with the animation. You need to check for the animation being complete. Under options add:
animation: {
onComplete: done
}
and then create a function "done" where you handle the printing.
function done() {
}
Hi here I set the data to the bar chart:
setDatosBarra: function(data){ //
var self = this;
var horaEstim = 0;
var horaReal = 0;
var horaTotal = 0;
if(data[0].horas_estim != '-'){
horaEstim = data[0].horas_estim;
}
if(data[0].horas_real != '-'){
horaReal = data[0].horas_real;
}
if(data[0].total_horas != '-'){
horaTotal = data[0].total_horas;
}
var datosBarra =[{data: [[0,horaEstim]], color: "#691717"}, {data: [[1,horaReal]], color: "#173D69"},{data: [[2,horaTotal]], color: "#176469"}];
self.flotLinea(datosBarra);
},
When all is ready I send the data to self.flotBar;
This is the flotBar function:
flotBar: function(datos){
var self = this;
if(datos == 0){
var data = [["SIN REGISTROS",0]];
}else{
var data = datos;
}
function getTooltip(label, x, y) {
return "<strong style='font-size:18px;'> " + y + " </strong> horas";
}
var plot = $.plot("#placeholder",data, {
series: {
bars: {
show: true,
barWidth: 0.3,
align: "center",
lineWidth: 0,
fill:.75
}
},
xaxis: {
ticks: [[0,"Horas estimadas"],[1,"Horas reales"],[2,"Total horas"]],
mode: "categories",
tickLength: 0
},
grid: {
hoverable: true,
clickable: true
},
tooltip: true,
tooltipOpts : {
content : getTooltip,
defaultTheme : false
},
});
},
Ok , and this is my problem, example:
I select a option in an dropDown:
And the bar chart looks like this:
If I select other option in the dropDown:
The bar chart looks like this:
And if I select again the first option "Correcion de errores", the bar chart looks like this:
So.. always the first time that I show the bar chart looks like in the first image , with the numbers in the line, but If I select other option looks good.
I need see good the bar chart always and no just when I select other option.
I'm using flot javascript library.
How can I fix this? sorry by my english
The main issue with the question as stated is that we do not have all the code. In essence, you should either provide all the code, or shrink down the problem to something that shows the issue and then, well, provide all the code. As far as I can guess, you have some other code somewhere else that is drawing the initial chart. The second and subsequent times? Drawn properly. To support my assertion, notice that in your initial image the captions for the x-axis tick markers (ditto the bars themselves) are right aligned not centered.
For fun, I wrote a quick jsFiddle that showed how to switch datasets using a button (much as you want to do with the drop-down) and redraw the chart:
drawChart = function(index) {
var chartData = getDataForChart(rawData[index]);
if (chart) {
chart.setData(chartData);
chart.draw();
}
else {
chart = $.plot("#barchart", chartData, chartOptions);
}
},
switchDataset = function() {
datasetIndex = (datasetIndex + 1) % datasetCount;
drawChart(datasetIndex);
};
$("#switchButton").on("click", switchDataset);
Because I decided to load new data into the chart rather than redraw it all from scratch (to be honest I saw no real difference either way), it meant that I had to pre-calculate the maximum value for the y-axis:
calcValueMax = function() {
var max = 0;
rawData.forEach(function(values) {
values.forEach(function(value) {
if (value > max) {
max = value;
}
});
});
return max;
},
// other code
chartOptions.yaxis.max = calcValueMax();
Hope that helps.
I am trying to use chartsjs to make a pie chart. I have followed the steps in the chartjs documentation and I have included chart.js and the canvas element. i added the script that should create the chart as the example provided in the chartjs documentation. I am getting the following error:
Uncaught TypeError: Cannot read property 'canvas' of undefined
Does anywhone know how to fix this? What am I doing wrong?
Thanx in advance!
HERE IS THE CODE:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="<?php echo base_url(); ?>media/js/chart.js"></script>
<script type="text/javascript" src="<?php echo base_url(); ?>media/js/jquery.js"></script>
</head>
<canvas id="myChart" width="400" height="400"></canvas>
<script type="text/javascript">
$(function() {
options = {
//Boolean - Show a backdrop to the scale label
scaleShowLabelBackdrop: true,
//String - The colour of the label backdrop
scaleBackdropColor: "rgba(255,255,255,0.75)",
// Boolean - Whether the scale should begin at zero
scaleBeginAtZero: true,
//Number - The backdrop padding above & below the label in pixels
scaleBackdropPaddingY: 2,
//Number - The backdrop padding to the side of the label in pixels
scaleBackdropPaddingX: 2,
//Boolean - Show line for each value in the scale
scaleShowLine: true,
//Boolean - Stroke a line around each segment in the chart
segmentShowStroke: true,
//String - The colour of the stroke on each segement.
segmentStrokeColor: "#fff",
//Number - The width of the stroke value in pixels
segmentStrokeWidth: 2,
//Number - Amount of animation steps
animationSteps: 100,
//String - Animation easing effect.
animationEasing: "easeOutBounce",
//Boolean - Whether to animate the rotation of the chart
animateRotate: true,
//Boolean - Whether to animate scaling the chart from the centre
animateScale: false,
//String - A legend template
legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
};
data = [
{
value: 300,
color: "#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green"
},
{
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow"
}
];
ctx = $("#myChart").get(0).getContext("2d");
myNewChart = new Chart(ctx[0]).Pie(data, options);
});
</script>
</html>
The problem lies on this line here:
myNewChart = new Chart(ctx[0]).Pie(data, options);
And in specifically ctx[0]. When you defined ctx here:
ctx = $("#myChart").get(0).getContext("2d");
ctx is an object called CanvasRenderingContext2D, which haves properties. You are trying to treat it as an Array when it's not. ctx[0] is therefore undefined. So the solution is actually simple, as you have found out.
Change ctx[0] to ctx, and you have your nice animated pie chart.
ctx = $("#myChart").get(0).getContext("2d");
myNewChart = new Chart(ctx).Pie(data, options);
Fiddle Here
My solution is a little different, as I wanted to have the chart change dynamically (in my application, it's moving with a slider) but avoid the awful flickering.
After standard instantiation, I update on slider drag like so:
var chartData = getChartData();
for(var i=0; i<chartData.length; i++)
{
barChart.datasets[0].bars[i].value = chartData[i];
}
barChart.update();
This animates teh change nicely, but after the animation is finished, in order to keep the weird flickering from happening when the user hovers the mouse over (the tooltip is also essential for me), I destroy and recreate the chart on mouse up as follows:
if(barChart) {
barChart.clear();
barChart.destroy();
}
chartDataObject = getChartData();
var chartData = {
labels: getChartLabels(),
datasets: [
{
label: "label",
fillColor: "rgba(151,187,205,0.5)",
strokeColor: "rgba(151,187,205,0.8)",
highlightFill: "rgba(151,187,205,0.75)",
highlightStroke: "rgba(151,187,205,1)",
data: chartDataObject
}
]
};
var chartContext = $("#visualizeEfficacyBar").get(0).getContext("2d");
barChart = new Chart(chartContext).Bar(chartData, { tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>", responsive : true , animate : false, animationSteps : 1 });
The important thing here is not to animate the recreation cause it leads to a very awkward visual effect, setting animate : false did not do the trick, but animationSteps : 1 did. Now no flickering, the chart is recreated and the user is none the wiser.