How to rolloverSlice every 5 seconds in amCharts? - javascript

Is it possible to rolloverSlice a pie chart based on seconds without an event?
Is clicking or hovering the part of the chart is the only way to rollover a slice or is there anyway to forloop this by index to show the parts every seconds
Here is my code
<script src="http://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="http://www.amcharts.com/lib/3/pie.js"></script>
<script src="http://www.amcharts.com/lib/3/themes/light.js"></script>
<div id="asset--chart"></div>
<style>
#asset--chart {
width : 100%;
height : 500px;
font-size : 11px;
}
</style>
var pieChartData = [
{
asset: 'Funiture',
marketValue: 50000.00
}, {
asset: 'Cash',
marketValue: 6250.00
}, {
asset: 'Car',
marketValue: 10000.00
}, {
asset: 'Other',
marketValue: 11250.00
}
];
chartAsset = AmCharts.makeChart(
'asset--chart', {
type: 'pie',
dataProvider: pieChartData,
valueField: 'marketValue',
titleField: 'asset',
startEffect: 'easeOutSine',
pulledField: 'pullOut',
//pullOutOnlyOne: true,
// pullOutEffect: 'easeInSine',
responsive: {
enabled: true
},
labelsEnabled: false,
balloon: {
fillAlpha: 0.95,
borderThickness: 1,
borderColor: '#000000',
shadowAlpha: 0,
}
}
);
chartAsset.addListener('rollOverSlice', function(e) {
chartAsset.clickSlice(e.dataItem.index);
});
Here is the fiddle: http://jsfiddle.net/Lrktmwa5/

AmCharts provides manual rollOverSlice and rollOutSlice methods that take the index of the slice where you want to simulate hover and mouseout actions. You can call them in a setInterval or setTimeOut loop depending on your use case:
var counter = 0;
setInterval(function() {
//check if the previous slice is pulled out in order
//to simulate a mouseout action to pull it back in for this chart
if (chartAsset.chartData[(counter + (chartAsset.dataProvider.length - 1)) % chartAsset.dataProvider.length].pulled) {
chartAsset.rollOutSlice((counter + (chartAsset.dataProvider.length - 1)) % chartAsset.dataProvider.length);
}
chartAsset.rollOverSlice(counter);
counter = (counter + 1) % chartAsset.dataProvider.length;
}, 5000);
Demo below:
var pieChartData = [{
asset: 'Funiture',
marketValue: 50000.00
}, {
asset: 'Cash',
marketValue: 6250.00
}, {
asset: 'Car',
marketValue: 10000.00
}, {
asset: 'Other',
marketValue: 11250.00
}];
chartAsset = AmCharts.makeChart(
'asset--chart', {
type: 'pie',
dataProvider: pieChartData,
valueField: 'marketValue',
titleField: 'asset',
startEffect: 'easeOutSine',
pulledField: 'pullOut',
//pullOutOnlyOne: true,
// pullOutEffect: 'easeInSine',
responsive: {
enabled: true
},
labelsEnabled: false,
balloon: {
fillAlpha: 0.95,
borderThickness: 1,
borderColor: '#000000',
shadowAlpha: 0,
}
}
);
chartAsset.addListener('rollOverSlice', function(e) {
chartAsset.clickSlice(e.dataItem.index);
});
chartAsset.addListener('rollOutSlice', function(e) {
chartAsset.clickSlice(e.dataItem.index);
});
var counter = 0;
setInterval(function() {
//check if the previous slice is pulled out in order
//to simulate a mouseout action to pull it back in for this chart
if (chartAsset.chartData[(counter + (chartAsset.dataProvider.length - 1)) % chartAsset.dataProvider.length].pulled) {
chartAsset.rollOutSlice((counter + (chartAsset.dataProvider.length - 1)) % chartAsset.dataProvider.length);
}
chartAsset.rollOverSlice(counter);
counter = (counter + 1) % chartAsset.dataProvider.length;
}, 5000);
body, html {
width: 100%;
height: 100%;
margin: 0;
}
#asset--chart {
width: 100%;
height: 100%;
font-size: 11px;
}
<script src="http://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="http://www.amcharts.com/lib/3/pie.js"></script>
<script src="http://www.amcharts.com/lib/3/themes/light.js"></script>
<div id="asset--chart"></div>

Related

Chartjs-gauge create circumference until certain value from data

I am creating 5 sections of gauge using chartjs-gauge. I am using the following data.
[150,200,250,300,400]
From this data, I want to display the circumference until 300. But the angle should calculated by including the last section value too. I had custom the text showing in section by setting it to empty string if more than 300. For section colour, I set 4 colours["green", "yellow", "orange", "red"]. Now, last section showing as silver colour which is default background of gauge. I have add rgba(0,0,0,0) to colour array ["green", "yellow", "orange", "red","rgba(0,0,0,0)"] which will show transparent colour for last section. But, when hover on section, it is responsive showing border. I would like to know if have other way to show the circumference until certain value from our data ,but calculating section area in chart using all value from data.
var data = [150, 200, 250, 300, 400];
var config = {
type: "gauge",
data: {
labels: ['Success', 'Warning', 'Warning', 'Error'],
datasets: [{
data: data,
value: 300,
backgroundColor: ["green", "yellow", "orange", "red"],
borderWidth: 2
}]
},
options: {
responsive: true,
title: {
display: true,
text: "Gauge chart with datalabels plugin"
},
layout: {
padding: {
bottom: 30
}
},
needle: {
// Needle circle radius as the percentage of the chart area width
radiusPercentage: 2,
// Needle width as the percentage of the chart area width
widthPercentage: 3.2,
// Needle length as the percentage of the interval between inner radius (0%) and outer radius (100%) of the arc
lengthPercentage: 80,
// The color of the needle
color: "rgba(0, 0, 0, 1)"
},
valueLabel: {
formatter: Math.round
},
plugins: {
datalabels: {
display: true,
formatter: function(value, context) {
//return '>'+value;
if (value <= 300) {
return value;
} else {
return '';
}
},
color: function(context) {
//return context.dataset.backgroundColor;
return 'black';
},
//color: 'rgba(255, 255, 255, 1.0)',
/*backgroundColor: "rgba(0, 0, 0, 1.0)",*/
borderWidth: 0,
borderRadius: 5,
font: {
weight: "bold"
}
}
}
}
};
window.onload = function() {
var ctx = document.getElementById("chart").getContext("2d");
window.myGauge = new Chart(ctx, config);
};
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en-US">
<head>
<script src="jQuery/jquery-3.4.1.min.js"></script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Gauge Chart with datalabels plugin</title>
<script src="https://unpkg.com/chart.js#2.8.0/dist/Chart.bundle.js"></script>
<script src="https://unpkg.com/chartjs-gauge#0.3.0/dist/chartjs-gauge.js"></script>
<script src="https://unpkg.com/chartjs-plugin-datalabels#0.7.0/dist/chartjs-plugin-datalabels.js"></script>
</head>
<body>
<div id="canvas-holder" style="width:100%">
<canvas id="chart"></canvas>
</div>
</body>
</html>
var data = [150, 200, 250, 300, 400];
colour_array = ["#11d8ee", "#3cc457", "#f12b0e", "#dda522", "#808080"];
let sum = data.reduce(function(a, b) {
return a + b;
}, 0);
var perc = 0;
perc_array = [];
for (i = 0; i < data.length; i++) {
perc = (data[i] / sum * 100).toFixed(2);
perc_array.push(perc);
}
Chart.plugins.register({ //increase distance between legend and chart
id: 'paddingBelowLegends',
beforeInit: function(chart, options) {
chart.legend.afterFit = function() {
this.height = this.height + 50; //custom 50 to value you wish
};
}
});
//when want to disable this plugin in other chart, paddingBelowLegends: false in plugin{}
var config = {
type: "doughnut",
data: {
labels: ['A', 'B', 'C', 'D', 'Others'],
datasets: [{
data: data,
value: data[(colour_array.length - 1)], //300
backgroundColor: colour_array,
borderWidth: 2
}]
},
options: {
responsive: true,
cutoutPercentage: 60,//thickness of chart
title: {
display: true,
text: "Gauge chart with datalabels plugin"
},
layout: {
padding: {
bottom: 30
}
},
valueLabel: {
formatter: Math.round,
display: false // hide the label in center of gauge
},
plugins: {
beforeInit: function(chart, options) {
chart.legend.afterFit = function() {
this.height = this.height + 50;
};
},
outlabels: {
display: true,
//text: '%l %v %p',//(label value percentage)the percentage automatically roundoff
//hide chart text label for last section-https://github.com/Neckster/chartjs-plugin-piechart-outlabels/issues/10#issuecomment-716606369
text: function(label) {
console.log(label);
highest_index = label['labels'].length - 1; //get highest index from the labels array
current_index = label['dataIndex']; //current index
value = label['dataset']['data'][label['dataIndex']]; //value of current index
const v = parseFloat(label['percent']) * 100;
if (current_index != highest_index) //to hide last section text label on chart.
{
//return value + ' , ' + `${v.toFixed(2)}%`;
return value+',\n'+`${v.toFixed(2)}%`;
} else {
return false;
}
},
color: 'white',
stretch: 12, //length of stretching
font: {
resizable: true,
minSize: 10,
maxSize: 14
},
padding: {
/*left:25,
right: 0
top:0,
bottom:0*/
}
},
//inner label:
datalabels: { //label on arc section
display: false,
formatter: function(value, context) {
if (value <= data[(colour_array.length - 2)]) //hide datalabel for last section
{
id = data.indexOf(value);
perc = perc_array[id];
return value + ' , ' + perc + '%';
} else {
return '';
}
},
color: function(context) {
return 'black';
},
borderWidth: 0,
borderRadius: 10,
font: {
weight: "bold",
},
anchor: "end" //'center' (default): element center, 'start': lowest element boundary, 'end': highest element boundary
}
},
legend: { //filter last section from legend chart labels
display: true,
//position: 'right',
labels: {
filter: function(legendItem, data) {
//ori-return legendItem !=1;
return !legendItem.text.includes('Others');
},
boxWidth: 20
}
},
rotation: 1 * Math.PI,
circumference: 1 * Math.PI,
tooltips: {
enabled: true,
mode: 'single',
filter: function(tooltipItem, data) { //disable display tooltip in last section
var label = data.labels[tooltipItem.index];
if (label == "Others") {
return false;
} else {
return true;
}
},
callbacks: { //custom tooltip text to show percentage amount (by default,showing real amount)
label: function(tooltipItem, data) {
var dataset = data.datasets[tooltipItem.datasetIndex];
hovered_index = tooltipItem.index;
data_length = data.datasets[0].data.length;
var total = dataset.data.reduce(function(previousValue, currentValue, currentIndex, array) {
return previousValue + currentValue;
});
var currentValue = dataset.data[tooltipItem.index];
var percentage = (currentValue / total * 100).toFixed(2);
return currentValue + ' , ' + percentage + "%";
}
}
}
}
};
window.onload = function() {
var ctx = document.getElementById("chartJSContainer").getContext("2d");
window.myGauge = new Chart(ctx, config);
};
<html>
<head>
<script src="https://unpkg.com/chart.js#2.8.0/dist/Chart.bundle.js"></script>
<script src="https://unpkg.com/chartjs-gauge#0.3.0/dist/chartjs-gauge.js"></script>
<script src="https://unpkg.com/chartjs-plugin-datalabels#0.7.0/dist/chartjs-plugin-datalabels.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-piechart-outlabels"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div id="canvas-holder" style="width:50% align:center">
<canvas id="chartJSContainer"></canvas>
</div>
</body>
</html>

Highmaps with rich information in separate container

I use highmaps with "Rich information on click" in a json format. For this I used a previously existing example. However, there are a few parts that I would like to add.
Separate container in which the extra information (countryChart) is
displayed instead of a single container in which both the map and
the extra information are shown Solution given by ppotaczek
Is it possible to display the total per category if no country is selected. In the example below, this means that in (Countrychart)
graph, cat1: 14, cat2: 3 and cat3: 15 (Canada, US and India added
together) are shown. Solution given by ppotaczek
The flags are not displayed, I cannot figure out why this is. Solution given by Emad
In this example I have made a start on the graph hopefully this is a good basis for the extra functionality.
$.ajax({
url: 'https://cdn.rawgit.com/highcharts/highcharts/v6.0.4/samples/data/world-population-history.csv',
success: function() {
var jsondata = {
"data": [{
"value": "8",
"code": "in",
"name": "india",
"testdata": [{
"vcount": "3"
}, {
"vcount": null
}, {
"vcount": "5"
}]
}, {
"value": "15",
"code": "us",
"name": "united states",
"testdata": [{
"vcount": "9"
}, {
"vcount": "2"
}, {
"vcount": "4"
}]
}, {
"value": "9",
"code": "ca",
"name": "canada",
"testdata": [{
"vcount": "2"
}, {
"vcount": "1"
}, {
"vcount": "6"
}]
}]
}
var mapChart;
var countryChart;
var graphdata = [];
var graphdataf = [];
var valuecount;
var countries = {};
$.each(jsondata.data, function(i, item) {
var graphval = [];
var value = item.value;
var code = item.code;
var name = item.name;
graphval.push(code);
graphval.push(value);
graphdata.push(graphval);
$.each(item.testdata, function(j, itemval) {});
countries[item.code] = {
name: item.name,
code3: item.code,
data: item.testdata
};
});
var data = [];
for (var code3 in countries) {
if (countries.hasOwnProperty(code3)) {
$.each(countries[code3].data, function(j, itemval) {
//var graphvaldata = [];
var value = itemval.vcount;
data.push({
name: countries[code3].name,
code3: code3,
value: value,
});
});
}
}
// Wrap point.select to get to the total selected points
Highcharts.wrap(Highcharts.Point.prototype, 'select', function(proceed) {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
var points = mapChart.getSelectedPoints();
if (points.length) {
if (points.length === 1) {
$('#info #flag').attr('class', 'flag ' + points[0].flag);
$('#info h2').html(points[0].name);
} else {
$('#info #flag').attr('class', 'flag');
$('#info h2').html('Comparing countries');
}
$('#info .subheader').html('<h4>Historical population</h4><small><em>Shift + Click on map to compare countries</em></small>');
if (!countryChart) {
countryChart = Highcharts.chart('country-chart', {
chart: {
height: 250,
spacingLeft: 0
},
credits: {
enabled: false
},
title: {
text: null
},
subtitle: {
text: null
},
xAxis: {
tickPixelInterval: 50,
crosshair: true,
categories: ['cat1', 'cat2', 'cat3']
},
yAxis: {
title: null,
opposite: true
},
tooltip: {
split: true
},
plotOptions: {
series: {
animation: {
duration: 500
},
marker: {
enabled: false
}
}
}
});
}
$.each(points, function(i, point) {
var data,
dataRaw = countries[point['hc-key']].data;
if (dataRaw) {
data = dataRaw.map((p) => parseInt(p.vcount));
}
// Update
if (countryChart.series[i]) {
countryChart.series[i].update({
name: this.name,
data: data,
type: points.length > 1 ? 'column' : 'column'
}, false);
} else {
countryChart.addSeries({
name: this.name,
data: data,
type: points.length > 1 ? 'column' : 'column'
}, false);
}
});
while (countryChart.series.length > points.length) {
countryChart.series[countryChart.series.length - 1].remove(false);
}
countryChart.redraw();
} else {
$('#info #flag').attr('class', '');
$('#info h2').html('');
$('#info .subheader').html('');
if (countryChart) {
countryChart = countryChart.destroy();
}
}
});
// Initiate the map chart
mapChart = Highcharts.mapChart('container', {
title: {
text: 'Population history by country'
},
subtitle: {
text: 'Source: The World Bank'
},
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
colorAxis: {
type: 'logarithmic',
endOnTick: false,
startOnTick: false,
minColor: '#fff',
maxColor: '#3D1C5C',
min: 5,
max: 15,
},
tooltip: {
footerFormat: '<span style="font-size: 10px">(Click for details)</span>'
},
credits: {
enabled: false
},
series: [{
data: graphdata,
mapData: Highcharts.maps['custom/world'],
joinBy: 'hc-key',
name: 'Total Play',
allowPointSelect: true,
cursor: 'pointer',
states: {
select: {
color: '#a4edba',
borderColor: 'black',
dashStyle: 'shortdot'
}
}
}]
});
}
});
* {
font-family: sans-serif;
}
#wrapper {
height: 500px;
width: 1000px;
margin: 0 auto;
padding: 0;
overflow: visible;
}
#container {
float: left;
height: 500px;
width: 700px;
margin: 0;
}
#info {
float: left;
width: 270px;
padding-left: 20px;
margin: 100px 0 0 0;
border-left: 1px solid silver;
}
#info h2 {
display: inline;
font-size: 13pt;
}
#info .f32 .flag {
vertical-align: bottom !important;
}
#info h4 {
margin: 1em 0 0 0;
}
#media screen and (max-width: 920px) {
#wrapper,
#container,
#info {
float: none;
width: 100%;
height: auto;
margin: 0.5em 0;
padding: 0;
border: none;
}
}
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/maps/modules/map.js"></script>
<script src="https://code.highcharts.com/mapdata/custom/world.js"></script>
<!-- Flag sprites service provided by Martijn Lafeber, https://github.com/lafeber/world-flags-sprite/blob/master/LICENSE -->
<link rel="stylesheet" type="text/css" href="//github.com/downloads/lafeber/world-flags-sprite/flags32.css" />
<div id="wrapper">
<div id="container"></div>
<div id="info">
<span class="f32"><span id="flag"></span></span>
<h2></h2>
<div class="subheader">Click countries to view history</div>
<div id="country-chart"></div>
</div>
</div>
Thanks in advance for your help!
I can aswer to your third question : The flags are not displayed, I cannot figure out why this is.
The problem is with this line :
$('#info #flag').attr('class', 'flag ' + points[0].flag);
There is no flag property in points object, you can change it to this :
$('#info #flag').attr('class', 'flag ' + points[0]["hc-key"]);
And you will have the flag now.
https://jsfiddle.net/vq26m8nb/7/
As to your questions:
Both charts are already in separate containers. You can remove the div with 'wrapper' id to split them so that they do not appear side by side. Check this example: https://jsfiddle.net/BlackLabel/8jo7vzty/
Yes, for example you can call select on some point with an additional argument and sum the data in the wrapped select method (depending on that additional argument).
if (points.length) {
...
if (arguments[3]) {
totalData = [];
Highcharts.objectEach(countries, function(el){
el.data.forEach(function(val, i){
if (totalData[i]) {
totalData[i] += parseInt(val.vcount)
} else {
totalData[i] = parseInt(val.vcount);
}
});
});
$('#info h2').html('Total data');
countryChart.series[0].setData(totalData);
mapChart.series[0].points[0].select(false, false, true);
}
} else if (!arguments[3]) {
$('#info #flag').attr('class', '');
$('#info h2').html('');
$('#info .subheader').html('');
if (countryChart) {
countryChart = countryChart.destroy();
}
}
...
mapChart = Highcharts.mapChart('container', ...);
mapChart.series[0].points[0].select(true, false, true);
Live demo: https://jsfiddle.net/BlackLabel/mg7x3kje/
The flags are not displayed because your points do not have flag property. You can add them in the way as #Emad Dehnavi suggested.

Highcharts - Change value of text box when drilling down through chart

Tricky one to explain this so please bear with me.
I have this Large Tree Map created with Highcharts:
http://jsfiddle.net/mb3hu1px/2/
var data = {
"ARS": {
"01To03Years": {
"N": {
"ARGENTINA": 951433
}
},
"Above05Years": {
"N": {
"ARGENTINA": 3719665
}
}
},
"CNY": {
"03To05Years": {
"N": {
"CHINA": 162950484
}
}
},
"COP": {
"Above05Years": {
"N": {
"COLOMBIA": 323390000
}
}
},
"EUR": {
"01To03Years": {
"Y": {
"BELGIUM": 393292575
}
}
}
},
points = [],
currencyPoints,
currencyVal,
currencyI = 0,
periodPoints,
periodI,
yesOrNoPoints,
yesOrNoI,
currency,
period,
yesOrNo,
mil,
causeMil,
causeMilI,
causeName = {
'N': 'Country Name',
'Y': 'Country Name'
};
for (currency in data) {
if (data.hasOwnProperty(currency)) {
currencyVal = 0;
currencyPoints = {
id: 'id_' + currencyI,
name: currency,
color: Highcharts.getOptions().colors[currencyI]
};
periodI = 0;
for (period in data[currency]) {
if (data[currency].hasOwnProperty(period)) {
periodPoints = {
id: currencyPoints.id + '_' + periodI,
name: period,
parent: currencyPoints.id
};
points.push(periodPoints);
yesOrNoI = 0;
for (yesOrNo in data[currency][period]) {
if (data[currency][period].hasOwnProperty(yesOrNo)) {
yesOrNoPoints = {
id: periodPoints.id + '_' + yesOrNoI,
name: yesOrNo,
parent: periodPoints.id,
};
causeMilI = 0;
for (mil in data[currency][period][yesOrNo]) {
if (data[currency][period][yesOrNo].hasOwnProperty(mil)) {
causeMil = {
id: yesOrNoPoints.id + '_' + causeMilI,
name: mil,
parent: yesOrNoPoints.id,
value: Math.round(+data[currency][period][yesOrNo][mil])
};
currencyVal += causeMil.value;
points.push(causeMil);
causeMilI = causeMilI + 1;
}
}
points.push(yesOrNoPoints);
yesOrNoI = yesOrNoI + 1;
}
}
periodI = periodI + 1;
}
}
currencyPoints.value = Math.round(currencyVal / periodI);
points.push(currencyPoints);
currencyI = currencyI + 1;
}
}
Highcharts.chart('container', {
series: [{
type: 'treemap',
layoutAlgorithm: 'squarified',
allowDrillToNode: true,
animationLimit: 1000,
dataLabels: {
enabled: false
},
levelIsConstant: false,
levels: [{
level: 1,
dataLabels: {
enabled: true
},
borderWidth: 3
}],
data: points
}],
title: {
text: ''
}
});
#container {
min-width: 300px;
max-width: 600px;
margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/heatmap.js"></script>
<script src="https://code.highcharts.com/modules/treemap.js"></script>
<div id="container"></div>
<textarea name="text" id="text" cols="30" rows="10"></textarea>
And as you can see there is also a text area underneath.
What I want is for every level that is clicked through on the chart, the text area updates with some random text.
So for example on the first drill down, the text area could literally just print out level 1, the second drill down print level 2 etc. etc.
If anyone needs anything else from my end please let me know.
Many thanks:)
You can do this several ways. Here is how to do it with plotOptions.series.point.events.click. What you need to do is capture the point click and render some text. As you do not describe what text to show this will just update the textarea with the clicked point's properties name and value.
Highcharts.chart('container', {
series: [{
point: {
events: {
click: function() {
var thePointName = this.name,
thePointValue = this.value;
$('#text').val(function(_, val) {
return 'Category: ' + thePointName + ', value: ' + thePointValue;
});
}
}
},
type: 'treemap',
layoutAlgorithm: 'squarified',
allowDrillToNode: true,
animationLimit: 1000,
dataLabels: {
enabled: false
},
levelIsConstant: false,
levels: [{
level: 1,
dataLabels: {
enabled: true
},
borderWidth: 3
}],
data: points
}],
title: {
text: ''
}
});
Live example.

How to get total of highcharts multiple series

With the Highcharts value-in-legend plugin http://www.highcharts.com/plugin-registry/single/10/Value-In-Legend, I have been able to kind of implement a sort of multiple series total, but I do not understand how to get a total for a clicked y-axis point.
For example when I click, one day I will get the 3 separate series numbers, but I would like to get a total somehow as well, but I only know the y points on load and the visible y-points on redraw. I think the difficulty is getting the total of the 3 series points versus getting the individual point's value.
$(function() {
// Start the standard Highcharts setup
var seriesOptions = [],
yAxisOptions = [],
seriesCounter = 0,
names = ['MSFT', 'AAPL', 'GOOG'],
colors = Highcharts.getOptions().colors;
$.each(names, function(i, name) {
$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=' + name.toLowerCase() + '-c.json&callback=?', function(data) {
seriesOptions[i] = {
name: name,
data: data
};
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter++;
if(seriesCounter == names.length) {
createChart();
}
});
});
// create the chart when all data is loaded
function createChart() {
$('#container').highcharts('StockChart', {
chart: {
events: {
load: function(event) {
console.log('load');
var total = 0;
for(var i = 0, len = this.series[0].yData.length; i < len; i++) {
total += this.series[0].yData[i];
}
totalText_posts = this.renderer.text('Total: ' + total, this.plotLeft, this.plotTop - 35).attr({
zIndex: 5
}).add()
},
redraw: function(chart) {
console.log('redraw');
console.log(totalText_posts);
var total = 0;
for(var i = 0, len = this.series[0].yData.length; i < len; i++) {
if(this.series[0].points[i] && this.series[0].points[i].visible) total += this.series[0].yData[i];
}
totalText_posts.element.innerHTML = 'Total: ' + total;
}
}
},
rangeSelector: {
selected: 4
},
yAxis: {
labels: {
formatter: function() {
return(this.value > 0 ? '+' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
legend: {
enabled: true,
floating: true,
align: 'left',
verticalAlign: 'top',
y: 35,
labelFormat: '<span style="color:{color}">{name}</span>: <b>{point.y:.2f} USD</b> ({point.change:.2f}%)<br/>',
borderWidth: 0
},
plotOptions: {
series: {
compare: 'percent',
cursor: 'pointer',
point: {
events: {
click: function () {
alert('Category: ' + this.category + ', value: ' + this.y);
}
}
}
}
},
series: seriesOptions
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/stock/highstock.src.js"></script>
<script src="http://code.highcharts.com/stock/modules/exporting.js"></script>
<script src="https://rawgithub.com/highslide-software/value-in-legend/master/value-in-legend.js"></script>
<div id="container" style="height: 400px; min-width: 500px"></div>
I was able to find out a way to put the total result as a title in a multi series by reading the source code for the Highcharts value-in-legend plugin https://rawgithub.com/highslide-software/value-in-legend/master/value-in-legend.js.
$(function () {
var seriesOptions_likes = [],
seriesCounter_likes = 0,
names_likes = ['MSFT', 'AAPL', 'GOOG'],
totalText_likes = 0;
/**
* Create the chart when all data is loaded
* #returns {undefined}
*/
function createLikesChart() {
Highcharts.stockChart('container_likes', {
chart: {
},
rangeSelector: {
selected: 4
},
title: {
text: 'Total Results: '
},
yAxis: {
labels: {
formatter: function () {
return (this.value > 0 ? ' + ' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
plotOptions: {
series: {
compare: 'percent',
showInNavigator: true
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2,
split: true
},
series: seriesOptions_likes,
legend: {
enabled: true,
floating: true,
align: 'left',
verticalAlign: 'top',
y: 65,
borderWidth: 0
},
});
}
$.each(names_likes, function (i, name) {
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=' + name.toLowerCase() + '-c.json&callback=?', function (data) {
seriesOptions_likes[i] = {
name: name,
data: data
};
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter_likes += 1;
if (seriesCounter_likes === names_likes.length) {
createLikesChart();
}
});
});
});
(function (H) {
H.Series.prototype.point = {}; // The active point
H.Chart.prototype.callbacks.push(function (chart) {
$(chart.container).bind('mousemove', function () {
var legendOptions = chart.legend.options,
hoverPoints = chart.hoverPoints,
total = 0;
if (!hoverPoints && chart.hoverPoint) {
hoverPoints = [chart.hoverPoint];
}
if (hoverPoints) {
var total = 0,
ctr = 0;
H.each(hoverPoints, function (point) {
point.series.point = point;
total += point.y;
});
H.each(chart.legend.allItems, function (item) {
item.legendItem.attr({
text: legendOptions.labelFormat ?
H.format(legendOptions.labelFormat, item) :
legendOptions.labelFormatter.call(item)
});
});
chart.legend.render();
chart.title.update({ text: 'Total Results: ' + total.toFixed(2) });
}
});
});
// Hide the tooltip but allow the crosshair
H.Tooltip.prototype.defaultFormatter = function () { return false; };
}(Highcharts));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<div id="container_likes" style="height: 400px; min-width: 600px"></div>

Click on the chart to zoom chart

I know highstock not support click to zoom graph
http://www.highcharts.com/docs/chart-concepts/zooming
But I want to click on the graph, the graph will display all screens, including the form "Time updates". How can i do?
For example: http://jsfiddle.net/DuyThoLe/58bzo3vg/17/enter code here
Starting from this Hgihcharts demo - http://jsfiddle.net/gh/get/jquery/1.7.2/highslide-software/highcharts.com/tree/master/samples/highcharts/chart/events-container/
... it is possible to get it to work with your chart: http://jsfiddle.net/6jLg8fg5/1/
Later you wanted to include "Time update" in pop up window, so it is added to div that will change its class (and because of CSS will be displayed on top, like a pop up): http://jsfiddle.net/6jLg8fg5/4/
Next you wanted to be able to prin, export, click legend without popping up or back down the chart. You could postpone (e.g. using setTimeout) pop up effect and check if click is not triggering legend or exporting menu.
Series have legendItemClick event - so first we shuold check that. While printing chart will have afterPrinting and beforePrinting events triggered. For exporting - it is possible to rewrite getChartHTML from exporting module using wrapping (extending Highcharts) - http://jsfiddle.net/6jLg8fg5/5/
JS:
$(function () {
(function (H) {
H.wrap(H.Chart.prototype, 'getChartHTML', function (proceed) {
printing = true;
// Run original proceed method
return this.container.innerHTML;
});
}(Highcharts));
Highcharts.setOptions({
global: {
useUTC: false
}
});
var legendClicked = false,
printing = false; //or exporting
// Create the chart
$('#chart1').highcharts('StockChart', {
chart: {
borderWidth: 0,
height: 283,
width: 660,
events: {
beforePrint: function() {
printing = true;
},
afterPrint: function(){
printing = false;
}
}
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 0
},
title: {
text: 'Live random data'
},
legend: {
enabled: true
},
exporting: {
enabled: true
},
navigator: {
enabled: true
},
series: [{
events: {
legendItemClick: function () {
legendClicked = true;
}
},
name: 'Random data',
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -999; i <= 0; i += 1) {
data.push([
time + i * 1000,
Math.round(Math.random() * 100)]);
}
return data;
}())
}]
});
//the form action
var updateInterval = 10000;
$("#updateInterval").val(updateInterval).change(function () {
var v = $(this).val();
if (v && !isNaN(+v)) {
updateInterval = +v;
if (updateInterval < 1) {
updateInterval = 1;
} else if (updateInterval > 50000) {
updateInterval = 10000;
}
$(this).val("" + updateInterval);
}
});
function update() {
var series = $('#chart1').highcharts().series[0];
x = (new Date()).getTime(); // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
setTimeout(update, updateInterval);
}
update();
$('.chart-container').bind('mousedown', function () {
var source = this;
if(!printing) {
setTimeout(function () {
//check if legend was clicked
if (legendClicked) {
legendClicked = false;
} else if ($('.highcharts-contextmenu').css('display') === 'block' || printing) {
//check if context menu is visible
printing = false;
} else {
//else do popup or back to default
$('#chart-with-time-update').toggleClass('modal');
$('.chart', source).highcharts().reflow();
}
}, 150);
}
});
});
CSS:
.main {
width: 400px;
margin: 0 auto;
}
.chart {
min-width: 300px;
max-width: 800px;
height: 300px;
margin: 1em auto;
}
.modal {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.7);
}
.modal .chart {
height: 90%;
width: 90%;
max-width: none;
}
Finally you needed to make it work with multiple charts - http://jsfiddle.net/6jLg8fg5/13/
(This problem was also discussed on Highcharts forum: http://forum.highcharts.com/highstock-usage/click-on-the-chart-to-zoom-chart-t33714/)

Categories