Chart.js - doughnut show active segment tooltip (on click of external button) - javascript

// 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);

Related

How to display Tooltip without hovering pie chart with Chart.JS

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');
}
});
}

Doughnut chart - interaction with specific segment of a chart

I'm trying to create a simple doughnut chart with chartjs. I've been digging through the Documentation and Stack (of course), but I couldn't find it.
Here is my code: https://jsfiddle.net/zyqtyna7/1/
<div class="place-for-chart">
<canvas id="myChart"></canvas>
</div>
<div class="description">
<p class="first hide">I'm description to no. 1 and I was hide</p>
<p class="second hide">I'm description to no. 2 and I was hide</p>
<p class="third hide">I'm description to no. 3 and I was hide</p>
</div>
<script>
var data = {
datasets: [{
data: [20, 20, 20],
backgroundColor: ["#27ae60", "#95a5a6", "#488a99"]
}],
labels: ["first", "second", "third"],
};
$(document).ready(
function() {
var canvas = document.getElementById("myChart");
var ctx = canvas.getContext("2d");
var CompetenceChart = new Chart(ctx, {
type: 'doughnut',
data: data
});
})
I'm not sure, but I think that the biggest question is: how can I target a specific segment of a chart (and then do something with it)? I'm asking this, because my project requires that:
descriptions in paragraphs will be visible after user's click at related part of chart (how can I target this segment???);
tooltips will have only labels' name (no values) (I couldn't decipher the Documentation);
chart animation should be triggered with scroll (segments will appear in sequence after scrolling - is it even possible?)
I'll be very greatfull for any insight - I'm stuck!
I managed to do 2 of 3.. and I found documentation on how to do the third one.. But I was not able to make it work :/.... (i will try again when i have a bit more of time).
So here is the JSfiddle with this modifications:
1:Data is shown on mouse click
2:On top labels are shown, but when you click you wont see any labels but a black mark
JSFIDDLE
So what did I do?
options: {
// This chart will not respond to mousemove, etc
events: ['click'],
tooltips: {
callbacks: {
label: function(tooltipItem)
{
return tooltipItem.yLabel;
}
}
}
}
I added the options part with those codes.
the events:['click'] makes the labels show when you click a part of the chart instead of hovering it.
the tooltips with the callbacks "turn off" showing the labels on mouse click.
And for the other part that you ask, about showing the animation when you scroll to the part where the chart is I found this 2 links that tells you how to do so (I couldn't make it work, but I will try again when I have more time and update).
Link1
Link2
Please let me know if this is what you wanted to know! CHEERS!
OMG! Now I know. It took me so many hours, but was so obvious! Here's my new - working - code: https://jsfiddle.net/m954jto4/ Documentation of Chartjs and same basic js script - that's all, what I needed (shame on me!).
<div class="place-for-chart">
<canvas id="myChart"></canvas>
</div>
<div class="description">
<p class="first hidden" id="hide1">I'm description to no. 1 and I was hide</p>
<p class="first hidden" id="hide2">I'm description to no. 2 and I was hide</p>
<p class="first hidden" id="hide3">I'm description to no. 3 and I was hide</p>
</div>
var data = {
datasets: [{
data: [20, 20, 20],
backgroundColor: ["#27ae60", "#95a5a6", "#488a99"]
}],
labels: ["first", "second", "third"],
};
$(document).ready(
function() {
var canvas = document.getElementById("myChart");
var ctx = canvas.getContext("2d");
var myNewChart = new Chart(ctx, {
type: 'doughnut',
data: data,
options: {
legend: {
display: true,
onClick: (e) => e.stopPropagation(),
position: 'left',
labels: {
fontSize: 20
}
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var label = data.labels[tooltipItem.index];
return label;
}
}
},
cutoutPercentage: 65
}
}
);
canvas.onclick = function(event) {
var activePoints = myNewChart.getElementsAtEvent(event);
var hiddenparagraph1 = document.getElementById("hide1");
var hiddenparagraph2 = document.getElementById("hide2");
var hiddenparagraph3 = document.getElementById("hide3");
if (activePoints.length > 0) {
var clickedSegmentIndex = activePoints[0]._index;
if (clickedSegmentIndex==0) {
hiddenparagraph1.classList.remove("hidden");
}
else if(clickedSegmentIndex==1) {
hiddenparagraph2.classList.remove("hidden");
}
else {
hiddenparagraph3.classList.remove("hidden");
}
}
};
}
);

Chart.js 2.1.2 Bar Chart Animation Issue

I have a bar chart in chart.js 2.1.2 which I just upgraded from 1.something. In 1.something, you could specify when to animate the bar chart. Essentially, I load the chart on page load and then set a timer to update the data and redraw the chart every 5 seconds without requiring the user to reload the page. I would like for the bar chart to only animate on the initial load and not in subsequent refreshes. In version 1.something you just needed to change the animation property of the bar chart when refreshing it. In version 2.1.2, I don't see a way to do that. At this point, I would be happy if I could disable the animation of the bar chart entirely. However, I also have other pie charts on the page which the animation settings are working so I don't want to change the animation settings globally.
HTML (Excerpt)
<div class="text-center">
<div class="row">
<div id="regbyhour-container" class="col-sm-12">
<h4>Registrations by Hour</h4>
<canvas id="regbyhour"></canvas>
</div>
</div>
</div>
Javascript
<script type="text/javascript">
var barData = defineBarDataArray();
$(function () {
// Global Chart Options
Chart.defaults.global.legend.display = false;
Chart.defaults.global.maintainAspectRatio = true;
// Bar Chart Options
Chart.defaults.bar.scaleBeginAtZero = false;
updateBarChart(true)
setInterval(function () {
updateBarChart(false)
}, 5000);
});
function defineBarDataArray() {
return {
labels: [],
datasets: [{
label: "Registrations",
backgroundColor: "rgba(151,187,205,0.5)",
borderColor: "rgba(151,187,205,0.8)",
borderWidth: 3,
data: []
}]
};
};
function drawRegByHourChart(animate) {
$("#regbyhour").remove();
$("#regbyhour-container").append('<canvas id="regbyhour"></canvas>');
var context = $("#regbyhour");
var chart = new Chart(context, {
type: 'bar',
data: barData
// Need to enable or disable animation here based on animate parameter
});
};
function updateBarChart(animate) {
barData = defineBarDataArray();
barData.labels.push("12:00 PM");
barData.labels.push("1:00 PM");
barData.labels.push("2:00 PM");
barData.datasets[0].data.push(1 + Math.floor(Math.random() * 2000));
barData.datasets[0].data.push(1 + Math.floor(Math.random() * 2000));
barData.datasets[0].data.push(1 + Math.floor(Math.random() * 2000));
drawRegByHourChart(animate);
};
</script>
I don't see anything in the documentation here that says you can specify the animation options like you can with a pie chart. What am I missing?
I ended up posting this as a bug on the chart.js GitHub page since I didn't get any responses here. Following the suggestion from etimberg I changed the drawRegByHourChart function from this:
function drawRegByHourChart(animate) {
$("#regbyhour").remove();
$("#regbyhour-container").append('<canvas id="regbyhour"></canvas>');
var context = $("#regbyhour");
var chart = new Chart(context, {
type: 'bar',
data: barData
// Need to enable or disable animation here based on animate parameter
});
};
To this:
function drawRegByHourChart(animate) {
$("#regbyhour").remove();
$("#regbyhour-container").append('<canvas id="regbyhour"></canvas>');
var context = $("#regbyhour");
var chart = new Chart(context, {
type: 'bar',
data: barData
});
if (!animate) {
chart.update(0);
}
};

Bar chart looks bad before change data

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.

Dojo StackedColumn tooltips

When I create a StackedColumns graph in dojo, the default tooltips show the cumulative value. I would like to show the individual value (or possibly both).
In my experience, when I have a series with first value: 2, and another with first value: 5, the tooltip shows 7 when hovering over the second series. I would like it to still show 5 (or possibly "value: 5, cumulative value: 7").
I found the following Q&A very useful. Phillipes jsFiddle example worked for the StackedArea, but I was unable to get it to work on StackedColumns.
Dojo StackedAreas chart doesn't accept objects as values
Appreciate any help.
Here is my code:
require(["dojox/charting/Chart", "dojox/charting/axis2d/Default", "dojox/charting/plot2d/StackedColumns", "dojox/charting/action2d/Tooltip", "dojox/charting/action2d/Highlight", "dojox/charting/action2d/Magnify", "dojox/charting/widget/SelectableLegend", "dojo/ready"],
function(Chart, Default, StackedColumns, Tooltip, Highlight, Magnify, SelectableLegend, ready){
ready(function(){
var chart1 = new dojox.charting.Chart("chart1");
chart1.addPlot("default",{type: "StackedColumns", gap: 2});
chart1.addAxis("x");
chart1.addAxis("y", {vertical: true, includeZero: true});
chart1.addSeries("A", [2,3,5,7,2,4,6], {plot: "default", fill: "blue", stroke: {color: "blue"}});
chart1.addSeries("C", [5,4,2,7,5,3,1], {plot: "default", fill: "green", stroke: {color: "green"}});
var tooltip = new Tooltip( chart1, "default", {
text : function(point) {
console.debug(point);
return "This is " + point.y;
}
});
chart1.render();
var clusteredColumnsLegend = new SelectableLegend({chart: chart1}, "chart1Legend");
});
});
I have created a new jsFiddle # http://jsfiddle.net/Tony_D/CqNhB/5/
This could maybe be considered as a bug, that said it is very easy to workaround just change your tooltip function by:
var tooltip = new Tooltip( chart1, "default", {
text : function(point) {
console.debug(point);
return "This is " + point.run.data[point.index];
}
});

Categories