I'm playing around with a backbone marionette app trying to dynamically populate highcharts data but I'm running into some trouble.
I created a basic survey app and I wanted to create a chart that shows the results of each question. However I don't know how many questions the survey might have or how many answers each question might have.
So what I do is populate an array that looks like this answerArray[answerId] = numberOfTimesSelected like this:
questions: (survey) =>
questions = survey.get('questions')
questions.each (question) =>
length = question.get('answers').length
answers = question.get('answers')
answerArray = []
if length < 7
question.get('answers').each (answer) ->
answerArray[answer.id] = 0
survey.get('responses').each (response) =>
date = Math.floor(new Date(response.get('created_date')) / 86400000)
if date > (#minDate - 1) && date < (#maxDate + 1)
if response.get('completed')
choices = response.get('choices')
choices.each (choice) ->
if choice.get('question_id') == question.get('id')
answerArray[choice.get('answer_id')] = answerArray[choice.get('answer_id')] + 1
Now a highcharts chart is populated like this:
$('#' + question.get('id')).highcharts({
chart: {
marginRight: 50,
marginTop: 0,
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false
},
title: {
text: '',
style: {
fontSize: 10
}
},
tooltip: {
pointFormat: '<b>{point.percentage:.1f}%</b>'
},
credits: {
enabled: false
},
exporting: {
enabled: true
},
plotOptions: {
pie: {
size: 300,
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true
}
},
series: [{
type: 'pie',
name: question.get('title'),
states: {
hover: {
brightness: 0
}
},
data: [
{
name: "14-17",
y: 22,
color: "#E8DF66"
},
{
name: "18-24",
y: 42,
color: "#8C8C8B"
},
{
name: "25-34",
y: 11,
color: "#687D68"
},
{
name: "35-44",
y: 55,
color: "#217C7E"
},
{
name: "45-54",
y: 231,
color: "#BEE7E8"
},
{
name: "55+",
y: 224,
color: "#634357"
}
]
}]
})
So I'm able to populate a graph for each question with that static data. But I need some way to dynamically change the data. Something like
data: [ question.get('answers').each (answer) ->
{
name: answer.get('title'),
y: answerArray[answer.get('id')],
color: "#E8DF66"
}
]
But that doesn't actually work. Any ideas how I could do something like that?
So I just ended up dynamically creating an object for each and then creating an array of those and using that array as the data.
Create the array/object:
graphData = []
question.get('answers').each (answer) ->
graphPiece = {}
graphPiece["name"] = answer.get('title')
graphPiece["y"] = answerArray[answer.get('id')]
graphPiece["color"] = "#E8DF66"
graphData.push(graphPiece)
Use the data in the highcharts graph:
series: [{
type: 'pie',
name: question.get('title'),
states: {
hover: {
brightness: 0
}
},
data: graphData
}]
Related
highchart doesn't show in IE and SAFARI. I try the solution from the official highchart forum, but nothing help (remove "," at the end of json, or resize page on load etc... )
I have multiple different highcharts, but here is only one for explanation. I call config function depends on chart data. My app have many different parts, and it's very hard to make working plunker. Thnx
Here is my code
function getBaseChartConfig(graphName) {
Highcharts.setOptions({
global: {
useUTC: false
}
});
var config =
{
xAxis: {
ordinal: false
},
yAxis: {
},
options: {
chart: {
zoomType: 'x',
backgroundColor: 'rgba(255, 255, 255, 1)',
polar: true,
type: 'line',
borderRadius: 5
},
legend: {
enabled: true
},
rangeSelector: {
//za postavit rucni upis date range-a
enabled: false,
inputStyle: {
color: 'black'
}
},
navigator: {
enabled: true
}
},
series: [],
title: {
text: graphName
},
useHighStocks: true
};
return config;
};
$scope.data.push(solar_voltage);
$scope.data.push(battery_voltage);
$scope.data.push(solar_current);
$scope.data.push(hybridCurrent);
$scope.chartConfig1 = getChartConfigWithYaxisPlotLines('Production');
$scope.chartConfig1.series.push({
id: 1,
name: "Solar voltage",
data: $scope.data[0],
tooltip: {
valueDecimals: 2
}
}, {
id: 2,
name: "Battery voltage",
data: $scope.data[1],
tooltip: {
valueDecimals: 2
}
}, {
id: 3,
name: "Solar current",
data: $scope.data[2],
tooltip: {
valueDecimals: 2
}
}, {
id: 4,
name: "Hybrid current",
data: $scope.data[3],
tooltip: {
valueDecimals: 2
}
}
);
function getChartConfigWithYaxisPlotLines(graphName) {
var baseChartConfig = getBaseChartConfig(graphName);
baseChartConfig.yAxis.plotLines = [{
color: '#FF0000',
width: 1,
value: 11.50,
label: {text: '11.50'}
}];
return baseChartConfig;
}
Here is image how this look in safari or IE
And here is in CHROME and FIREFOX
This is my json from api
I have built this electoral map but I have not succeeded drawing a pie chart of the two parties on the pop-up dialog when a map region is clicked. The dialog title is being passed but not the actual values that should build the chat.
The returned json data is here and I just want to push a pie-chart to the dialog when someone clicks on a county on the map. Here's my code and "pointClick" function that should render the pie to a div.
$(function() {
$.getJSON("<?= base_url('index.php/presidential/getByCounty'); ?>", function(json) {
function pointClick(json) {
var row = this.options.row,
$div = $('<div></div>')
.dialog({
title: ([this.name]),
width: 400,
height: 300
});
//THIS IS ACTUALLY WHAT'S NOT WORKING
window.chart = new Highcharts.Chart({
chart: {
renderTo: $div[0],
type: 'pie',
width: 370,
height: 240
},
title: {
text: null
},
series: [{
name: 'Votes',
data: [{
name: 'nasa',
color: '#0200D0',
y: this.nasa //returned json data for candidate 1 and I problem must be somewhere here
}, {
name: 'jubilee',
color: '#C40401',
y: this.jubilee //returned json data for candidate 2
}],
dataLabels: {
// format: '<b>{point.name}</b> {point.value:.1f}%'
}
}]
});
}
//AM BUILDING THE ELECTORAL MAP FROM THIS POINT WHICH WORKS OUT NICELY
$('#presidential').highcharts('Map', {
title: {
text: 'Presidential Electoral Map <em>(Kenya - Test)</em>'
},
legend: {
title: {
text: 'Plotical Parties'
}
},
credits: {
enabled: false
},
tooltip: {
valueSuffix: ' Incumbent Margin'
},
mapNavigation: {
enabled: true,
enableButtons: false
},
colorAxis: {
dataClasses: [{
from: 0.0000001,
to: 100,
color: '#C40401',
name: 'Jubilee'
}, {
from: -100,
to: -0.00000001,
color: '#0200D0',
name: 'Nasa'
}, {
from: 0,
to: 0,
color: '#C0C0C0',
name: 'Battle Ground(s)'
}]
},
series: [{
name: 'By County Difference',
point: {
events: {
click: pointClick
}
},
"type": "map",
"joinBy": ['name', 'name'],
"data": $.each(json, function() {}),
"mapData": [{
"name": "Mandera",
"path": "M572,-818,574,-789,578,-783,598,-775,619,-750,646,-738,645,-727,652,-703,662,-689,678,-679,689,-666,693,-672,696,-734,733,-774,783,-848,774,-845,765,-850,761,-846,711,-843,677,-873,663,-874,583,-838z"
}, //and a couple more mapdata
]
}, {
"type": "mapline",
"data": [{
"name": "path5072",
"path": "M443,-449Z"
}]
}]
});
});
});
Your JSON data contains number in string format so convert it into Number
like this
Fiddle link
series: [{
name: 'Votes',
data: [{
name: 'nasa',
color: '#0200D0',
y: Number(this.nasa) //transform to number
}, {
name: 'jubilee',
color: '#C40401',
y: Number(this.jubilee) //transform to number
}],
dataLabels: {
format: '<b>{point.name}</b> {point.value:.1f}%'
}
}]
I wanted to display two labels on bars. I am able to display one label right now. I want something like this.
Instead I am getting like this
The code snippet which I am using to show the labels is
plotOptions: {
column: {
dataLabels: {
enabled: true,
color: "black",
style: {
textOutline: false
}
}
}
}
how Can I show these percentage value on the bars? Thanks in Advance.
For placing label with percentage inside the particular column you should give dataLabels inside that series, for rest of the column use common dataLabels as defined by you in plotOptions. Below code is for idea only Fiddle link
var data = [7, 12, 16, 32];
var dataSum = 0;
for (var i = 0; i < data.length; i++) {
dataSum += data[i]
}
var data2 = [5, 19, 14, 13];
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: ''
},
xAxis: {
type: 'category',
},
yAxis: {
min: 0,
},
legend: {
enabled: false
},
plotOptions: {
column: {
dataLabels: {
enabled: true,
color: "black",
style: {
textOutline: false
}
}
}
},
series: [{
name: 'first',
data: data,
dataLabels: {
y: 20, /*for placeing lables values inside column*/
enabled: true,
formatter: function() {
var pcnt = (this.y / dataSum) * 100;
return Highcharts.numberFormat(this.y , 0) +'<br>'+Highcharts.numberFormat(pcnt) + '%';
}
}
}, {
name: 'Second',
data: data2,
}]
});
Hi I'm trying to update my piechart LIVE without redrawing the piechart, any advice?
this is the function that is being called
var i = 0;
setInterval(function(){
piecharts(i, 1, 2, 3, 4, 5);
i++;
},5000);
function piecharts(sector0Data, sector1Data, sector2Data, sector3Data, sector4Data, sector5Data)
{
$('#container').highcharts({
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie',
options3d: {
enabled: false,
alpha: 45,
beta: 0
}
},
title: {
text: 'Number of person in each sector'
},
tooltip: {
pointFormat: '{series.name}: <b>{point.y}</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
depth: 35,
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.y} ', //change percentage to y for decimal value
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
}
}
},
series: [{
name: 'Avg number of person in this sector over the total of ',
colorByPoint: true,
data: [{
name: 'Sector0',
y: sector0Data
},{
name: 'Sector1',
y: sector1Data
},{
name: 'Sector2',
y: sector2Data
},{
name: 'Sector3',
y: sector3Data
},{
name: 'Sector4',
y: sector4Data
}, {
name: 'Sector5',
y: sector5Data
}]
}]
});
}
For every 5 second, my i will increase by 1 and my pie-chart will be drawn, this works fine but it kept redrawing my chart. any advice? thanks. also, i'm using v4.1.8 of highchart
You should use the update() method for this. Init your chart on the DOM ready event and just call a function in order to update data :
Demo
function updatePiechart(sector0Data, sector1Data, sector2Data, sector3Data, sector4Data, sector5Data)
{
var chart = $('#container').highcharts();
chart.series[0].update({
data: [{
name: 'Sector0',
y: sector0Data
},{
name: 'Sector1',
y: sector1Data
},{
name: 'Sector2',
y: sector2Data
},{
name: 'Sector3',
y: sector3Data
},{
name: 'Sector4',
y: sector4Data
}, {
name: 'Sector5',
y: sector5Data
}]
})
}
The reason for the re-render is that you create a new chart every five seconds instead of updating its data.
You need to call the update method for your y point on your chart series data:
chart.series[0].data[0].update(y);
Here is a simple example on how to update the data: Update pie data jsfiddle
Or have a look at the documentation for live data
I have a scatter chart from Highcharts, in the y axis i put 'Intensity' values,and in the x axis i have datetimes (month,day,year).
chart: {
type: 'scatter',
zoomType: 'xy',
renderTo: 'chartContainer'
},
rangeSelector: {
enabled: true
},
xAxis: {
title: {
enabled: true
},
type: 'datetime',
dateTimeLabelFormats:{
month: '%e. %b %Y',
year: '%b'
},
startOnTick: true,
endOnTick: true,
showLastLabel: true
},
yAxis: {
title: {
text: 'Intensity'
},
min: 0,
max: 100
},
plotOptions: {
scatter: {
marker: {
radius: 5,
states: {
hover: {
enabled: true,
lineColor: 'rgb(100,100,100)'
}
}
},
states: {
hover: {
marker: {
enabled: false
}
}
},
events: {
click: function(event) {
showMoreData();
}
}
}
},
series: [{
name: 'Male',
color: 'rgba(144,36,58, .8)',
data: getDataParsed()
}]
These data are loaded from another function getDataParsed(), where I do a ajax GET and get multiple data . The question is how i pass more data (also Intensity and Datetimes) so i can used later in the scatter chart.
function getDataParsed() {
var serie = [];
var i=0;
dolorCollect.forEach(function (dato) {
var arr = dato.FECHA_INICIO.split("/");
var hour = dato.HORA_INICIO.split(":");
serie[i]= [Date.UTC(arr[2],arr[1]-1,arr[0],hour[0],hour[1]),dato.INTENSIDAD_DOLOR];
i++;
});
return serie;
}
To have more data in each data point in series' data you can:
do as Rahul Sharma suggested in his comment - set data point as object with named properties. More info in API - see 3rd way of data format:
An array of objects with named values. The objects are point configuration objects as seen below. If the total number of data points exceeds the series' turboThreshold, this option is not available.
data: [{
x: 1,
y: 2,
name: "Point2",
color: "#00FF00"
}, {
x: 1,
y: 4,
name: "Point1",
color: "#FF00FF"
}]
or set data as array of arrays - as you do now, but with more data in point array. To allow Highcharts proper way to decode your new format set keys.
So same data can be set using code like:
series:[{
data: [
[1, 2, "Point2", "#00FF00"],
[1, 4, "Point1", "#FF00FF"]
],
keys: ['x','y','name','color'],
...