Update text dynamic via tooltip in Highcharts Piechart [duplicate] - javascript

This question already has an answer here:
Highcharts Donut Chart text in center change on hover
(1 answer)
Closed 8 years ago.
I am trying to dynamic update the text in the centre of my piechart when my tooltip mouses over the series.
By using the formatter inside the tooltip field of the chart I am able to call a separate function but it seems like the text is not updating.
Here is my fiddle Pie Chart
$(function () {
var chartTitle = "Text in the Pie";
var colors = Highcharts.getOptions().colors;
var chart1 = new Highcharts.Chart({
chart: {
renderTo: 'container1',
type: 'pie'
},
title: {
text: 'Pie Pie Pie',
y: 20,
verticalAlign: 'top'
},
tooltip: {
//pointFormat: '{series.name}: <b>{point.percentage}%</b>'
formatter: function () {
chartTitle = this.series.name + '/n' + this.point.percentage.toFixed(2) + '%';
refreshText(this);
return '<b>' + this.series.name + '</b>: ' + this.point.percentage;
}
},
plotOptions: {
pie: {
borderColor: 'white',
innerSize: '60%',
dataLabels: {
enabled: false
}
}
},
series: [{
data: [{
y: 59,
color: '#005C7F',
name: 'Chrome'
}, {
y: 41,
color: '#4CCDFF'
}, {
y: 61,
color: '#00B8FF'
}, {
y: 52,
color: '#26677F'
}],
size: '80%',
innerSize: '60%'
}]
},
function (chart1) { // on complete
var xpos = '50%';
var ypos = '50%';
var circleradius = 130;
// Render the circle
chart1.renderer.circle(xpos, ypos, circleradius).attr({
fill: '#0093CC'
}).add();
// Render the text
//chart1.renderer.text(chart1.series[0].data[0].percentage.toFixed(2) + '%', 270, 200).css({
chart1.renderer.text(chartTitle + '%', 230, 200).css({
width: circleradius * 2,
color: '#FFFFFF',
fontSize: '16px',
textAlign: 'center'
}).attr({
// why doesn't zIndex get the text in front of the chart?
zIndex: 999
}).add();
}
);
function refreshText(chart1) {
alert("inside refreshText() function");
var xpos = '50%';
var ypos = '50%';
var circleradius = 130;
// Render the circle
chart1.renderer.circle(xpos, ypos, circleradius).attr({
fill: '#0093CC'
}).add();
chart1.renderer.text(chartTitle + '%', 270, 200).css({
width: circleradius * 2,
color: '#FFFFFF',
fontSize: '16px',
textAlign: 'center'
}).attr({
// why doesn't zIndex get the text in front of the chart?
zIndex: 999
}).add();
}
});

FYI, you were calling refreshChart(this) in your tooltip. You just needed to call refreshChart(chart1) to get the refresh to work, although you weren't clearing out the renderer.
tooltip: {
//pointFormat: '{series.name}: <b>{point.percentage}%</b>'
formatter: function () {
chartTitle = this.series.name + '/n' + this.point.percentage.toFixed(2) + '%';
refreshText(chart1);
return '<b>' + this.series.name + '</b>: ' + this.point.percentage;
}
},
http://jsfiddle.net/2qV9K/

Related

How can I contain a label on a Highcharts area chart to the series' area

For some reason no matter what we try the labels on our area chart series seem to have a mind of their own. Even though a short label looks like it could fit inside the area of the data, it puts it right on the end line, bleeding out of the area.
We suspect it might be due to having min and max dates that are beyond the series min and max, but these buffer zones are a requirement.
Is there an option to make labels be contained to their own series and not bleed off into whitespace?
Below is the example chart configuration and here is the JSFiddle: http://jsfiddle.net/sLqu34cn/
Highcharts.chart('container', {
chart: {
type: "area",
height: 200
},
legend: {
enabled: false
},
plotOptions: {
area: {
stacking: "percent",
pointPlacement: "on"
},
series: {
lineWidth: 0,
fillOpacity: 1,
marker: {
enabled: false
},
label: {
style: {
color: "white",
textOutline: "1px black"
}
}
}
},
series: [
{
name: "Two",
data: [[1532217600000, 1], [1532822400000, 0]],
color: "#41B6E6"
},
{
name: "Three",
data: [[1532217600000, 0], [1532822400000, 2]],
color: "#0072CE"
}
],
xAxis: {
tickWidth: 1,
title: {
enabled: false
},
labels: {
format: "{value: %b %e}"
},
max: 1533243166375,
min: 1530478366375,
type: "datetime"
},
yAxis: {
tickInterval: 20,
title: {
text: null
},
labels: {
format: "{value}%"
},
max: 100,
min: 0
},
tooltip: {}
});
Probably not the perfect solution, but you can create some customization to position the series labels. This is an example how to manually calculate the center of area in triangle shape:
Highcharts.wrap(Highcharts.Chart.prototype, 'drawSeriesLabels', function(proceed) {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
var chart = this,
plotTop = chart.plotTop,
plotLeft = chart.plotLeft,
series = chart.series,
height = chart.yAxis[0].height,
x1,
x2,
y1,
y2;
x1 = ((series[0].graphPath[1] + plotLeft) * 2 + series[0].graphPath[4] + plotLeft) / 3;
y1 = (height + plotTop + series[0].graphPath[2] + plotTop + series[0].graphPath[5] + plotTop) / 3;
x2 = (series[1].graphPath[1] + plotLeft + (series[1].graphPath[4] + plotLeft) * 2) / 3;
y2 = ((series[1].graphPath[2] + plotTop) * 2 + series[1].graphPath[5] + plotTop) / 3;
series[0].labelBySeries.attr({
x: x1,
y: y1,
align: 'center'
});
series[1].labelBySeries.attr({
x: x2,
y: y2,
align: 'center'
});
});
Live demo: http://jsfiddle.net/BlackLabel/34z8od5f/
Docs: https://www.highcharts.com/docs/extending-highcharts/extending-highcharts

Highcharts.js: scrollable innterText?

Based on the code of this Highchart example, I would like to display some text in the center of the donut circle, when a certain tile is clicked. Is it now possible, to make the displayed text scrollable when it doesn't fit nicely into the circle's inner area?
What I have so far
$(function () {
var colors = ['#8d62a0', '#ceb3d8', '#d5dddd'];
var chart = new Highcharts.Chart({
chart: {
renderTo: 'vacation-time-chart',
type: 'pie',
height: 300,
width: 300,
borderRadius: 0
},
credits: {
enabled: false
},
title: false,
tooltip: {
formatter: function() {
return '<b>'+this.y+'</b>';
}
},
plotOptions: {
pie: {
borderWidth: 6,
startAngle: 90,
innerSize: '75%',
size: '100%',
shadow: true,
// {
// color: '#000000',
// offsetX: 0,
// offsetY: 2,
// opacity: 0.7,
// width: 3
// },
dataLabels: false,
stickyTracking: false,
states: {
hover: {
enabled: false
}
},
point: {
events: {
click: function(){
this.series.chart.innerText.attr({text: this.txt});
}
}
}
}
},
series: [{
data: [
{y:40, color: colors[0], txt: 'yoyo'},
{y:10, color: colors[1], txt: 'dada'},
{y:60, color: colors[2], txt: 'this is a longer text that I would like to be scrollable. this is a longer text that I would like to be scrollable. this is a longer text that I would like to be scrollable. this is a longer text that I would like to be scrollable. this is a longer text that I would like to be scrollable.this is a longer text that I would like to be scrollable. this is a longer text that I would like to be scrollable.'}
]
// data: [
// ['Firefox', 44.2],
// ['IE7', 26.6],
// ['IE6', 20],
// ['Chrome', 3.1],
// ['Other', 5.4]
// ]
}]
},
function(chart) { // on complete
var xpos = '50%';
var ypos = '53%';
var circleradius = 102;
var boundingBox;
var series = chart.series[0];
var zones;
// Render the text
chart.innerText = chart.renderer.label('Articles mentioning XY', 135, 125).add();
boundingBox = chart.innerText.getBBox();
chart.innerText.css({
display:"inline-block",
position:"absolute",
top:"1px",
width: "150px",
height:"30px",
color: '#4572A7',
fontSize: '12px',
overflow: 'auto',
textAlign: 'block'
}).attr({
// why doesn't zIndex get the text in front of the chart?
x: series.center[0] - boundingBox.width / 2 + chart.plotLeft / 2,
y: series.center[1] + boundingBox.height / 2 + chart.plotTop,
zIndex: 999
}).add();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<script src="http://code.highcharts.com/highcharts.js"></script>
</head>
<body>
<div id="vacation-time-chart" style="min-width: 300px; height: 300px; margin: 0 auto"></div>
<script src="testfile.js"></script>
</body>
</html>
Could anyone please help me with this? Adding overflow: auto (or scroll) to the innterText.css properties doesn't seem to be the solution here.
You can do this,
function defineInnerData(name, y, obj) { // on complete
var chart=$("#container").highcharts();
$( "#pieChartInfoText" ).remove();
var textX = chart.plotLeft + (chart.plotWidth * 0.5);
var textY = chart.plotTop + (chart.plotHeight * 0.5);
var span = '<span id="pieChartInfoText" style="position:absolute; text-align:center;left: 235px;top:210px;width: 130px;">';
span += '<span style="font-size: 15px">'+ y +'</span><br>';
span += '<span style="font-size: 12px">'+ name +'</span>';
span += '</span>';
$("#addText").append(span);
span = $('#pieChartInfoText');
span.css('left', textX + (span.width() * -0.5));
span.css('top', textY + (span.height() * -0.5));
}
defineInnerData("", "Tap the slices of this chart to see more");
And call it inside,
series: {
cursor: 'pointer',
point: {
events: {
mouseOver: function() {
console.log(this)
defineInnerData(this.name, this.y, this);
}
}
},
DEMO

How to display time on x axis in flot line graph?

I am trying to show time intervals between Min and Max of a certain time range. Eg: 2015-04-30 10:20:00 and 2015-04-30 10:30:00 on x axis
I will be fetching all the values from database(which has datetime stored in 2015-04-30 10:27:58 format and passing it through webmethod.
If I create var data1 as
var data1 = [
['2015-04-30 10:27:58', 1690.25], ...
];
It won't work. So I am guessing I would need to convert '2015-04-30 10:27:58'milisecond ticks when creating var data1.
But I do not want to display time in a proper time format such as 10:27:58 instead of 1430369878000 on xaxis. (I want exclude date part).
How can I achieve this?
//RED
var data1 = [
[1430369878000, 1690.25], [1430369879000, 1696.3], [1430369880000, 1659.65]
];
//BLUE
var data2 = [
[1430369878000, 1682.1], [1430369879000, 1680.65], [1430369880000, 1685.1]
];
var dataset = [
{
label: "Sell out",
data: data1,
color: "#FF0000",
points: { fillColor: "#FF0000", show: true },
lines: { show: true }
},
{
label: "Buy in",
data: data2,
color: "#0062E3",
points: { fillColor: "#0062E3", show: true },
lines: { show: true }
}
];
var options = {
series: {
shadowSize: 5
},
xaxes: { mode: "time",
min: parseInt((new Date("2015-04-30 10:27:58")).getTime()),
max: parseInt((new Date("2015-04-30 10:43:39")).getTime()),
timeformat: "%H/%M/%S"
},
yaxis: {
color: "black",
tickDecimals: 2,
axisLabel: "Gold Price in USD/oz",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 6
},
legend: {
noColumns: 0,
labelFormatter: function (label, series) {
return "<font color=\"white\">" + label + "</font>";
},
backgroundColor: "#000",
backgroundOpacity: 0.9,
labelBoxBorderColor: "#000000",
position: "nw"
},
grid: {
hoverable: true,
borderWidth: 3,
mouseActiveRadius: 50,
backgroundColor: { colors: ["#ffffff", "#EDF5FF"] },
axisMargin: 20
}
};
$(document).ready(function () {
setInterval(function () {
$.plot($("#flot-placeholder"), dataset, options);
$("#flot-placeholder").UseTooltip();
}, 1000)
});
var previousPoint = null, previousLabel = null;
$.fn.UseTooltip = function () {
$(this).bind("plothover", function (event, pos, item) {
if (item) {
if ((previousLabel != item.series.label) || (previousPoint != item.dataIndex)) {
previousPoint = item.dataIndex;
previousLabel = item.series.label;
$("#tooltip").remove();
var x = item.datapoint[0];
var y = item.datapoint[1];
var date = new Date(x);
var color = item.series.color;
showTooltip(item.pageX, item.pageY, color,
"<strong>" + item.series.label + "</strong><br>" +
x +
" : <strong>" + y + "</strong> (USD/oz)");
}
} else {
$("#tooltip").remove();
previousPoint = null;
}
});
};
function showTooltip(x, y, color, contents) {
$('<div id="tooltip">' + contents + '</div>').css({
position: 'absolute',
display: 'none',
top: y,
left: x,
border: '2px solid ' + color,
padding: '3px',
'font-size': '9px',
'border-radius': '5px',
'background-color': '#fff',
'font-family': 'Verdana, Arial, Helvetica, Tahoma, sans-serif',
opacity: 0.9
}).appendTo("body").fadeIn(200);
}
The options for the x-axis are under the name xaxes not xaxis therefore they are not used. (Also your min and max values are outside of the data range.)
// not xaxes:
xaxis: {
mode: "time",
//min: parseInt((new Date("2015-04-30 10:27:58")).getTime()),
//max: parseInt((new Date("2015-04-30 10:43:39")).getTime()),
timeformat: "%H/%M/%S"
},
See this fiddle for a working example.
PS: You use the $.plot() function with setInterval which is okay but you should only call UseTooltip() once.

highcharts heatmap items opacity turns to 0

I m using Heat Map of Highcharts library in my app and i have begin to face a weird scenario. The map does not show some rows data, plz look at the following screen shot:
I see data in the column when I Inspect Element a cell. I noticed that all the row cell's opacity is set to 0. Changing it to 1 in chrome shows the item.
My JS code is as follows:
$highchart1.highcharts({
exporting: false,
credits: false,
chart: {
type: 'heatmap',
marginTop: 40,
marginBottom: 120
},
title: {
align: 'left',
text: 'Some chart title',
style: { color: 'red' }
},
xAxis: {
categories: pillarOrClusters,
labels: {
style: { color: '#000' }
}
},
yAxis: {
categories: locations,
title: summary.locationType,
labels: {
style: { color: '#000' }
}
},
colorAxis: {
min: 0,
minColor: '#FFFFFF',
maxColor: Highcharts.getOptions().colors[0]
},
legend: {
enabled: false
},
tooltip: {
formatter: function () {
return '<b>' + this.series.xAxis.categories[this.point.x] + '</b> has <br><b>' +
this.point.value + '</b> items in <br><b>' + this.series.yAxis.categories[this.point.y] + '</b>';
}
},
series: [{
name: 'Pillars per' + summary.locationType, // Loaded from Service
borderWidth: 1,
data: data,
dataLabels: {
enabled: true,
color: '#000000'
}
}]
});
Why would the map set opacity to 0 for entire row elements?
This issue was being raised only in Chrome and sometimes in IE because of insufficient height of the chart. I am calculating chart height as per items on yAxis as follows:
//locations is an array of strings to be shown on yAxis
var chartHieght = locations.length * 35;
if (chartHieght < 350) chartHieght = 350;
And then set it as follows:
chart: {
type: 'heatmap',
marginTop: 40,
height: chartHieght,
marginBottom: 130,
backgroundColor: '#F0F0F0',
borderColor: '#E5E5E5',
borderWidth: 2,
borderRadius: 4,
events: {
load: function () {
//THIS WAS A DIRTY WORKAROUND I WAS USING TO MAKE IT RENDER PROPERLY
/* $(".highcharts-data-labels g").attr("opacity", 1); */
}
}
}
Turning the height calculation as locations.length * 30 begins to render the same issue in Chrome. locations.length * 25 will cause the issue in IE as well.
Hope it helps someone.

display on hover and rotate ticks 90 degrees at the same time in flot bar graph

I am using flot and rendering a bar graph. I am having very big labels on my x-axis so I rotated them to 90 degrees using https://github.com/markrcote/flot-tickrotor.
But In my graph I am also using tooltip to show user the data on hover. When I am using both of them simultaneously I am getting the flowing error:
"Uncaught TypeError: Cannot read property 'label' of undefined".
My code:
<script>
var dataset = [{ data: data, color: "#5482FF" }];
var options = {
series: {
bars: {
show: true
}
},
bars: {
align: "center",
barWidth: 0.5
},
xaxis: {
axisLabel: "EquipmentMainCatagory",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 10,
ticks: ticks,
rotateTicks:90
},
yaxis: {
axisLabel: "# Assets",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 3,
},
grid: {
hoverable: true,
borderWidth: 0,
backgroundColor: { colors: ["#ffffff", "#EDF5FF"] }
}
};
$(document).ready(function () {
$.plot($("#placeholder"), dataset, options);
$("#placeholder").UseTooltip();
});
var previousPoint = null, previousLabel = null;
$.fn.UseTooltip = function () {
$(this).bind("plothover", function (event, pos, item) {
if (item) {
if ((previousLabel != item.series.label) || (previousPoint != item.dataIndex)) {
previousPoint = item.dataIndex;
previousLabel = item.series.label;
$("#tooltip").remove();
var x = item.datapoint[0];
var y = item.datapoint[1];
var color = item.series.color;
//console.log(item.series.xaxis.ticks[x].label);
showTooltip(item.pageX,
item.pageY,
color,
item.series.xaxis.ticks[x].label + " : <strong>" + y + "</strong>");
}
} else {
$("#tooltip").remove();
previousPoint = null;
}
});
};
function showTooltip(x, y, color, contents) {
$('<div id="tooltip">' + contents + '</div>').css({
position: 'absolute',
display: 'none',
top: y - 40,
left: x - 120,
border: '2px solid ' + color,
padding: '3px',
'font-size': '9px',
'border-radius': '5px',
'background-color': '#fff',
'font-family': 'Verdana, Arial, Helvetica, Tahoma, sans-serif',
opacity: 0.9
}).appendTo("body").fadeIn(200);
}
</script>
It looks like the jquery.flot.tickrotor.js plugin clears the .ticks array property and creates it's own .rotatedTicks array property.
So switch to:
item.series.xaxis.rotatedTicks[x].label
And all should be well.
Fiddle example here.
In your bind("plothover"...) function, you use
item.series.xaxis.ticks[x].label + " : <strong>" + y + "</strong>");
but your ticks array consists of arrays and not objects with a label property.
You can try replacing the above line with
item.series.xaxis.ticks[x][1] + " : <strong>" + y + "</strong>");

Categories