In a laravel project, I'm using Highcharts to show a chart of the standard column type simply called column. xAxis has 4 categories representing teams, and yAxis holds each teams score. It looks like this:
<div id="chart" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
<script type="text/javascript">
var chart1 = Highcharts.chart('chart', {
chart: {
type: 'column'
},
title: {
text: 'title'
},
xAxis: {
categories: ["f","j","n","s"]
},
yAxis: {
min: 0,
title: {
text: 'Total score'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
});
</script>
The points are added after the page is loaded by using jquery and a javascript function like so:
$( document ).ready(function() {
#foreach($existingScores as $score)
addScoreToChart({!! $score !!})
#endforeach
});
function addScoreToChart(obj)
{
var scores = obj.params.scores;
var datas = [];
for(var k in scores){
datas.push([k, parseInt(scores[k])]);
}
console.log(datas);
chart1.addSeries({
name: obj.clientName,
data: datas,
});
}
This works fine on the initial load of the scores. Some scores will be added to the chart after the page is loaded (via websockets).
I'm quite unsure how to actually update a given teams score. The websockets part is working, and when a new score is added i can call a javascript function that updates the scoreboard with the new data. How can i do this ? Say for example that a new score of 5 points for team "j" is added. How would i tell Highcharts to update the chart with such data / add 5 points to "j" existing score?
You can use series.update to update a series, this function will merge the input with the existing series. Can be done like this:
function updateTeam(obj) {
let name = obj.params.name;
let scores = obj.params.scores;
let datas = [];
for (let k in scores) {
datas.push([parseInt(k), parseInt(scores[k])]);
}
let tmpSeries = chart.series;
for (var i = 0; i < tmpSeries.length; i++) {
if (tmpSeries[i].name == name ) {
tmpSeries[i].update({
data: datas
}, true);
}
}
}
var chart = Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'title'
},
xAxis: {
categories: ["f", "j", "n", "s"]
},
yAxis: {
min: 0,
title: {
text: 'Total score'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
series: [{
name: 'team1',
data: [29.9, 71.5, 106.4, 129.2]
},
{
name: 'team2',
data: [29.9, 71.5, 106.4, 129.2]
}, {
name: 'team3',
data: [29.9, 71.5, 106.4, 129.2]
}
]
});
function updateTeam(obj) {
let name = obj.params.name;
let scores = obj.params.scores;
let datas = [];
for (let k in scores) {
datas.push([parseInt(k), parseInt(scores[k])]);
}
let tmpSeries = chart.series;
for (var i = 0; i < tmpSeries.length; i++) {
if (tmpSeries[i].name == name ) {
tmpSeries[i].update({
data: datas
}, true);
}
}
}
// the button handler
$('#button').click(function() {
var incomingObj = {
params: {
name: 'team1',
scores: [2.1, 5.6, 150.4, 99.9]
}
};
updateTeam(incomingObj);
});
<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/modules/exporting.js"></script>
<div id="container" style="height: 400px"></div>
<button id="button" class="autocompare">Update Series</button>
Working JSfiddle: http://jsfiddle.net/ewolden/Lrxu5u68/2/
You will need to redraw the chart as far as I can remember highcharts wont watch the data to draw.
Call chart.redraw() when new data comes in from your web socket.
Related
In this chart I want to show all the people's name with it's band color as legends who has different fruits. Here Some people can have many kind of fruits but I don't want to show the name twice.Here it just shows the series name but I want to show all the people's name in the bottom.Can anyone help me with this?
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: ''
},
xAxis: {
categories: ['Apples', 'Oranges','Bananas']
},
yAxis: {
min: 0,
title: {
text: ''
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{point.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
credits: {
enabled: false
},
series : [{
data : [{
x:0,
y:3,
name:'John',
color:'#FF5733'
},
{
x:0,
y:5,
name:'Parker',
color:'#009900'
},{
x:0,
y:1,
name:'Adam',
color:'#95FF33'
},{
x:1,
y:5,
name:'Alex',
color:'#E3FF33'
},{
x:1,
y:3,
name:'Pukal',
color:'#33BDFF'
},{
x:1,
y:4,
name:'Mark',
color:'#FB33FF'
},{
x:2,
y:3,
name:'John',
color:'#FF5733'
},{
x:2,
y:4,
name:'Parker',
color:'#009900'
},{
x:2,
y:2,
name:'Mark',
color:'#FB33FF'
}]
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
I would convert the data to be in the form of multiple series instead of one series, like this:
{
series : [
{ name: "John", color: "#FF5733", data: [3, 0, 3] }
{ name: "Parker", color: "#009900", data: [5, 0 4] }
.. etc ...
]
}
Then Highcharts will automatically use the person's name as the legend.
Here is a Fiddle to show what I mean.
I transformed the data to multiple series using this code:
var data = [];
var seriesLookup = {};
original.forEach(function(item){
var series = seriesLookup[item.name];
if(!series){
series = {
name: item.name,
color: item.color,
data: [0, 0, 0]
};
data.push(series);
seriesLookup[item.name] = series;
}
series.data[item.x] = item.y;
});
Then I changed the tooltip.pointFormat to use series.name instead of point.name
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
I also used the dataLabels.formatter to ignore 0 values.
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
formatter: function(){
return (this.y!=0) ? this.y : "";
}
}
You can also just set legendType: 'point':
series: [{
legendType: 'point',
data: [ ... ]
}]
Live demo: http://jsfiddle.net/BlackLabel/9kqLsfza/
I have a stacked column graph like this fiddle.
If you see there the one column is in grey colour to indicate that it is disabled. I want to hide total from the top of the column where the colour is grey/ or where the category is 'Pears'.
I have tried this approach in this answer but I can't figure out how to disable the stack total based on the category type/ column?
As links to fiddle.net must be accompanied by the code, here it is:
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears', 'Grapes', 'Bananas']
},
yAxis: {
min: 0,
title: {
text: 'Total fruit consumption'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
},
series: {
events: {
afterAnimate: function(e) {
var chart = e.target.chart;
for (var j = 0; j < chart.series.length; j++) {
for (var i = 0; i < chart.series[j].data.length; i++) {
// alert(chart.series[j].data[i].category);
if (chart.series[j].data[i].category == 'Pears') {
chart.series[j].data[i].update({
color: 'grey'
});
}
}
}
}
},
}
},
series: [{
name: 'John',
data: [5, 3, 4, 7, 2],
}, {
name: 'Jane',
data: [2, 2, 3, 2, 1]
}, {
name: 'Joe',
data: [3, 4, 4, 2, 5]
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<div id="container" style="min-width: 210px; height: 200px; margin: 0 auto"></div>
You could use a yAxis.stackLabels.formatter (API) and use the current labels x-value (this.x) to find the desired category name.
For example (JSFiddle):
yAxis: {
stackLabels: {
formatter: function() {
// if this label is for pears, return nothing
if(this.axis.chart.xAxis[0].categories[this.x] == 'Pears')
return;
// if not, return the default
else
return this.total;
}
}
}
Like you think you can do that with the formatter option API Doc :
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
},
formatter:function(){
if (this.x !== 2) {
return this.total;
}
}
}
this.x is an array of each categories.
Fiddle
i need add point to highchart x,y . i cannot add my custom xaxis in the label. label automaticly add index of potit .how can i add my text in new point xaixs label ?
var chartPresure = $('#PresureContainer').highcharts();
var series = chartPresure.series[0];
var newpointPresure = updatedresult.Pressure;
if (lastDate != updatedresult.RegisterDatePersian) {
var x = updatedresult.RegisterDatePersian,
y = updatedresult.Pressure;
series.addPoint([x, y, updatedresult.RegisterDatePersian], true);
series.drawPoints();
lastDate = updatedresult.RegisterDatePersian;
}
You can update the axis labels after point add event
function addPoint() {
chart.series[0].addPoint(
Math.floor(Math.random() * 6) + 1,
true,
false
);
//console.log(chart.xAxis[0].categories)
chart.xAxis[0].categories.push(chart.series[0].data.length + 'th element')
//console.log(chart.xAxis[0].categories)
//update chart with category
chart.update({
xAxis: {
categories: chart.xAxis[0].categories
},
});
}
var chart = new Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
categories: ['Apples', 'Oranges', 'Pears', 'Grapes', 'Bananas']
},
yAxis: {
min: 0,
title: {
text: 'Total fruit consumption'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white'
}
}
},
series: [{
name: 'John',
data: [5, 3, 4, 7, 2]
}]
});
function addPoint() {
chart.series[0].addPoint(
Math.floor(Math.random() * 6) + 1,
true,
false
);
//console.log(chart.xAxis[0].categories)
chart.xAxis[0].categories.push(chart.series[0].data.length + 'th element')
//console.log(chart.xAxis[0].categories)
chart.update({
xAxis: {
categories: chart.xAxis[0].categories
},
});
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
<button onclick="addPoint()" class="autocompare">Add point</button>
Good morning,
I'm working on small dashboard and using WinJS, but I have problem with Highcharts. They can't load inside WinJS.UI.HubSection and only in google chrome. I tried firefox and there is showed. I have second graph where I'm using Highstock and then works fine everywhere. I tried almost everything and don't know why the highchart isn't loaded inside HubSection. Thanks for your answers and help.
RainbowShaggy
You are trying to create a chart in div #vehicles, but jQuery (in your demo) nor Highcharts (I tested) are able to find that container.
It seems that when Highstock chart is created all divs are available, so if you will be creating all charts in createChart function, then they should be created successfully.
Example: https://jsfiddle.net/r6twbj0z/6/
var clientsArray = [];
stationsArray = [];
companiesArray = [];
WinJS.Namespace.define("ListView.Clients", {
data: new WinJS.Binding.List(clientsArray)
});
WinJS.Namespace.define("ListView.Stations", {
data: new WinJS.Binding.List(stationsArray)
});
WinJS.Namespace.define("ListView.Companies", {
data: new WinJS.Binding.List(companiesArray)
});
WinJS.UI.processAll();
$(function() {
var seriesOptions = [],
seriesCounter = 0,
names = ['MSFT', 'AAPL', 'GOOG'];
/**
* Create the chart when all data is loaded
* #returns {undefined}
*/
function createChart() {
$('#companyvalue').highcharts('StockChart', {
/*chart : {
events : {
load : function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, false);
}, 1000);
}
}
},*/
rangeSelector: {
selected: 4
},
yAxis: {
labels: {
formatter: function() {
return (this.value > 0 ? ' + ' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
plotOptions: {
series: {
compare: 'percent'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
series: seriesOptions
});
$('#vehicles').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Použité vozidla'
},
xAxis: {
categories: ['Vlaky', 'Autobusy', 'Nákl. auta', 'Lodě', 'Letadla']
},
yAxis: {
min: 0,
title: {
text: 'Počet vozidel'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -30,
verticalAlign: 'top',
y: 25,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px black'
}
}
}
},
series: [{
name: 'John',
data: [5, 3, 4, 7, 2]
}, {
name: 'Jane',
data: [2, 2, 3, 2, 1]
}, {
name: 'Joe',
data: [3, 4, 4, 2, 5]
}]
});
}
$.each(names, function(i, name) {
$.getJSON('https://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 += 1;
if (seriesCounter === names.length) {
createChart();
}
});
});
});
I got fetched user from database, and all of them have review score.
I use while statement to show each user and the review score (using highchart).
The problem is that I'm getting only one chart, instead of getting one for each single user.
Here is the code
PHP:
if (isset($_COOKIE['rev_idx'])) {
$review_id=preg_replace('#[^0-9]#','',$_COOKIE['rev_idx']);
if ($review_id==$get_rev) {
$sql1="SELECT * FROM `user`.`review` WHERE reviewer_id='$review_id'";
$query1=mysqli_query($connect_dude,$sql1);
if (mysqli_num_rows($query1)>0) {
$show_review="";
while($row1=mysqli_fetch_assoc($query1)){
$rid=$row1['rid'];
$reviewer_id=$row1['reviewer_id'];
$reviewee_id=$row1['reviewee_id'];
$review_tit=$row1['review_tit'];
$review=$row1['review'];
$image=$row1['image'];
$point=$row1['points'];
$rev_date=$row1['rev_date'];
$sql2="SELECT * FROM `user`.`user_det` WHERE id='$reviewee_id'";
$query2=mysqli_query($connect_dude,$sql2);
if(mysqli_num_rows($query2)>0){
$row2=mysqli_fetch_assoc($query2);
$image=$row2['img'];
$busi_title=$row2['busi_title'];
$show_review.="<br><div id='indi_rev'><div style='width:600px;border-bottom:1px solid black;'></div><div id='rev_dat'>".$rev_date."</div>
<div style='width:600px;border-bottom:1px solid black;'></div>
<div style='float:left;'><a href='../".$reviewee_id."/index.php'><img src='../account/".$reviewee_id."/".$image."' width='130' height='150'></a><br><a href='../".$reviewee_id."/index.php'><b>".$busi_title."</b></a></div>
<div><br><b>".$review_tit."</b><br>".$review."</div><div id='Scores' style='min-width: 100px; height: 80px;max-width: 500px;'></div></div>";
}
}
} else {
$show_review="<b>You have not written any review yet.</b><br>Share your thought to others by writing review.";
}
} else {
header("location:reviewer.php?usr=".$review_id."");
}
}
Javascript:
<script src="http://code.jquery.com/jquery-1.9.1.js" type="text/javascript"></script>
<script src="http://code.highcharts.com/highcharts.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
var x="<?php echo $point;?>";
var chart = new Highcharts.Chart({
chart: {
type: 'bar',
renderTo: 'Scores',
marginRight: 50,
events: {
//load: loadRed
}
},
title: {
text: '',
style: {
color: 'black',
fontWeight: '700',
fontFamily: 'Arial',
fontSize: 20
}
},
xAxis: {
categories: ['Review Score'],
title: {
text: null
},
gridLineWidth: 0,
minorGridLineWidth: 0,
labels: {
style: {
color: 'black',
fontWeight: '700',
fontFamily: 'Arial',
fontSize: 11,
width: 90
}
}
},
yAxis: {
min: 0,
max: 100,
gridLineWidth: 0,
minorGridLineWidth: 0,
labels: {
enabled: false
},
title: {
text: null
}
},
tooltip: {
valueSuffix: ' /100'
},
plotOptions: {
series: {
stacking: 'percent'
},
bar: {
grouping: false,
dataLabels: {
enabled: false
}
}
},
legend: {
enabled: false,
align: 'right',
x: -40,
y: 100,
floating: false,
borderWidth: 0,
backgroundColor: '#FFFFFF',
shadow: false
},
credits: {
enabled: false
},
series: [
{
name: 'null',
data: [x],
borderWidth: 0,
color: "rgba(0,0,0,0)"
}, {
name: 'Score',
data: [x],
borderWidth: 0,
stack: 1,
animation: false,
color: "gray"
}, {
name: 'Score',
data: [x],
color: "green",
borderWidth: 0,
borderRadius: 5
}
]
});
});
</script>
Your help would be greatly appreciated
you should make many instance of highcahrt for many users by adding different id and loop your javascript code too.
change your
<div id='Scores' ....
to
<div id='Scores_".$reviewee_id."' ....
and cut your
< script >
block and paste after
$show_review.="<br><div ......
and change
renderTo: 'Scores',
to
renderTo: 'Scores_<?php echo $reviewee_id>',
The problem is that your x variable is string, but should be an array. So consider to print in php JSON (json_encode()) and then loat this in the javascript by the function $.getJSON().