I have a simple gauge chart, but I wish to alter it dynamically, for instance, I would like to have the scale limits set based on data extracted from a database. how would I achieve this?
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<div id="chart-A" class="chart"></div>
var axismin = 10;
$(function(axismin,axismax) {
$('#chart-A').highcharts({
chart: {
type: 'gauge',
},
title: {
text: 'Gauge'
},
pane: {
startAngle: -150,
endAngle: 150,
},
// the value axis
yAxis: {
min: axismin,
max: 100,
},
series: [{
data: [1]
}]
},
// Add some life
function(chart) {
if (!chart.renderer.forExport) {
setInterval(function() {
var point = chart.series[0].points[0],
newVal,
inc = Math.round((Math.random() - 0.5) * 20);
newVal = point.y + inc;
if (newVal < 0 || newVal > 100) {
newVal = point.y - inc;
}
point.update(newVal);
}, 500);
}
});
});
jsfiddle
Suppose from database you call min and max values.
$(function() {
//suppose using php
var axismin = <?php echo $axismin ?>;
var axismax = <?php echo $axismax ?>;
function init(axismin, axismax) {
......
}
init(axismin, axismax); //call chart function with arguments
});
Fiddle demo
Highcharts provide some functions for altering already rendered chart. For updating yAxis.min and yAxis.max values you can use setExtremes or update.
API references:
https://api.highcharts.com/class-reference/Highcharts.Axis#setExtremes
https://api.highcharts.com/class-reference/Highcharts.Axis#update
Related
In my chart I have these time stamp that are displayed on the x-axis
How do I make them display in the tooltip when I hover over to certain point in the chart?
Highcharts.chart('container', {
...
xAxis: {
labels: {
formatter: function() {
let seconds = this.value * 5;
let t = new Date(1900, 1, 1, 9, 30, 0);
t.setSeconds(t.getSeconds() + this.value * 5);
return `${t.getHours()}:${t.getMinutes()}:${t.getSeconds()}`
}
},
tickInterval: 2
},
});
Can someone please help as I am not able to figure this out?
You can use the same approach in pointFormatter as in the labels formatter function.
tooltip: {
pointFormatter: function(){
let t = new Date(1900, 1, 1, 9, 30, 0);
t.setSeconds(t.getSeconds() + this.x * 5);
return `
Time: ${t.getHours()}:${t.getMinutes()}:${t.getSeconds()}
Y: ${this.y}
Value: ${this.value}
`
}
}
Live demo: https://jsfiddle.net/BlackLabel/jf9x8y3q/
API Reference: https://api.highcharts.com/highcharts/tooltip.pointFormatter
The Highcharts API has a pointFormat property for tooltips, where you can specify the HTML (e.g. <p>Tooltip data: {variable}</p>). You can find the API reference here: https://api.highcharts.com/highcharts/tooltip.pointFormat
Or you could use pointFormatter to specify a callback function instead (https://api.highcharts.com/highcharts/tooltip.pointFormatter).
i have data comprised of both positive and negative values which are to be displayed in a chart. i
am trying to display data in such a way that data point of positive values is greater than that of negative values.
the following is my code
<html>
<head>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<div id="demochart"></div>
<button id="update"> Update</button>
<script>
Highcharts.chart('demochart', {
chart: {
type: 'scatter'
},
xAxis: {
categories: [0, 10, 20, 30, 40, 50, 60, 70, 80]
},
series: [{
name: 'Temperature',
data: [15, 50, -56.5, -46.5, -22.1, -2.5, -27.7, -55.7, 76.5]
}]
},function(chart){
$('#update').click(function(){
var data = chart.series[0].data;
var new_array = [];
new_array = data;
console.log(new_array);
for(var i = 0; i < new_array.length; i++){
console.log("For: "+ new_array[i].y);
if(new_array[i].y > 0){
new_array[i].y = "{y:"+ new_array[i] +",marker: {radius: 10}}"
console.log("If: "+ new_array[i].y);
}else{
new_array[i].y = "{y:"+ new_array[i] +",marker: {radius: 4}}"
console.log("Else: "+ new_array[i].y);
}
}
chart.series[0].setData(new_array);
})
});
</script>
</body>
</html>
When i click the update button, the size of data point value radius has to be changed.
Can this scenario will work ?
You can simply use the update method for points that meet your condition and change marker options. For performance reasons, it is better to set redraw parameter to false and redraw the chart after loop to avoid redrawing on every iteration.
Highcharts.chart('container', {
...
}, function(chart) {
$('#update').click(function() {
var points = chart.series[0].points;
points.forEach(function(point) {
if (point.y > 0) {
point.update({
marker: {
radius: 10
}
}, false);
}
});
chart.redraw();
})
});
Live demo: http://jsfiddle.net/BlackLabel/jznums3L/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.Point#update
https://api.highcharts.com/class-reference/Highcharts.Chart#redraw
I have an line/area chart, I want to set a minimum range on the y-axis.
Let's say my points are [0,300],[1,270],[2,230],[3,260] (those are retrieved through ajax, so they're not static).
I want the y-axis range to be at least 100, but by default google will set maximum as maximum value (300 in this case), and minimum at minimum value (230 in this case), so range in this case would be (and it is actually) 70, I want it to be at least 100, so the chart maximum should be (300+230)/2+50 and minimum (300+230)/2-50, so that I have a 100 range and the chart i vertically center aligned.
I want the range to have a minimum but not a maximum, if my points are [0,100],[1,240],[5,160] then range should match the data range (140 in this case) also if the optimum is smaller (100).
Basically I don't want the chart to show a big difference when the actual difference in data is small. I know how to set fixed maximum and minimum on axis, but that doesn't solve my problem.
This is my actual code:
$.fn.createChart = function(url,options){
var obj = $(this);
console.log('CREATING CHART: '+url);
// Load the Visualization API and the linechart package.
if(!$.canAccessGoogleVisualization()){
google.charts.load('current', {packages: ['corechart', 'line']});
}
// Set a callback to run when the Google Visualization API is loaded.
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var jsonData = $.ajax({
url: url ,
dataType: "json",
async: false
}).responseText;
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(jsonData);
//Default options
var def = {
width: obj.width(),
height: obj.height(),
curveType: 'function',
legend: { position: 'bottom' },
hAxis: {
format: 'dd/MM'
},
animation:{
"startup": true,
duration: 1000,
easing: 'out',
}
};
//Overwrite default options with passed options
var options = typeof options !== 'undefined' ? $.mergeObjects(def,options) : def;
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.AreaChart(obj.get(0));
chart.draw(data, options);
}
}
$.mergeObjects = function(obj1,obj2){
for (var attrname in obj2) { obj1[attrname] = obj2[attrname]; }
return obj1;
}
$.canAccessGoogleVisualization = function()
{
if ((typeof google === 'undefined') || (typeof google.visualization === 'undefined')) {
return false;
}
else{
return true;
}
}
you can use the getColumnRange method on the DataTable to find the min and max
then apply you're logic to set the viewWindow on the vAxis
see following working snippet...
google.charts.load('current', {
callback: function () {
var data = google.visualization.arrayToDataTable([
['X', 'Y'],
[0, 300],
[1, 270],
[2, 230],
[3, 260]
]);
var yMin;
var yMax;
var columnRange = data.getColumnRange(1);
if ((columnRange.max - columnRange.min) < 100) {
yMin = ((columnRange.max + columnRange.min) / 2) - 50;
yMax = ((columnRange.max + columnRange.min) / 2) + 50;
} else {
yMin = columnRange.min;
yMax = columnRange.max;
}
var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
chart.draw(data, {
vAxis: {
viewWindow: {
min: yMin,
max: yMax
}
}
});
},
packages: ['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
I'm wondering if there is a way to apply dynamic settings to individual marker of an highstock chart? I've searched for half a day and I have the feeling that there is a problem with the API. It seems that there is no ways to adjust marker setting on a specific datum. ex:
$('#container').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, true);
}, 1000);
}
}
},
series : [{
data : (function () {
var data = [], time = (new Date()).getTime(), i;
for (i = -999; i <= 0; i += 1) {
data.push([
{ x: time + i * 1000,
y: Math.round(Math.random() * 100),
marker:{
fillColor:'red'
}
}
]);
}
return data;
}())
}]
}
I've fork a basic Highstock demo to illustrate my point. See the jsfiddle that demonstrate the problem: http://jsfiddle.net/9xj0nz72/1/
Maybe I have an error in my fiddle... or may I have to create an issue on Github?
Thanks a lot!!
I had to assign the style in the addPoint method, you can't just push to the data array. And you have to use it on the chart = new Highcharts.StockChart() variable.
I'm pretty sure I got what you were hoping for using the following. And to demonstrate I assigned a random color and radius to each new point.
$(function () {
var chart = new Highcharts.StockChart({
chart: {
renderTo: 'container'
},
plotOptions: {
series: {
marker: {
enabled: true
}
}
},
series: [{
name: 'Random data',
data: [],
time: (new Date()).getTime()
}]
});
/* add new random point every 1 second */
var i = 0;
setInterval(function () {
i++;
chart.series[0].addPoint({
marker: {
/* assign a random hex color and radius */
fillColor: '#' + (Math.random() * 0xFFFFFF << 0).toString(16),
radius: Math.floor(Math.random() * 10) + 1
},
y: Math.random() * 100,
x: i * 1000,
}, true, false);
}, 1000);
});
Your updated JSFiddle
First time ever working with JS and HighCharts... But I'll try to formulate a question so it'll make sense!
At the moment I'm working with only 4 sources of data, which is incredibly easy to throw right in to highcharts.
The problem is, the 4 aggregated numbers is... well, not very consistent.
The numbers I have atm is: 349531093, 156777100, 572480, 7 and 0.
The first number and the second covers the whole funnel, which makes the plot very unattractive and hard to visually see the values.
(Yeah, yeah - the labels are brilliant, but I want to be able to visually see each section).
I've been reading through the documentation of the funnel plot, but I cannot find a way to limit the section size in any way.
So I tried to play around a bit with the different kind of limits, like:
minSize - The minimum size for a pie in response to auto margins. The pie will try to shrink to make room for data labels in side the
plot area, but only to this size. (which does exactly what it says,
so I'm not sure why I even tried it...)
size - that ofc just changed the size of the whole chart....
series: {
dataLabels: {
enabled: true,
format: '<b>{point.name}</b> ({point.y:,.0f})',
minSize: '10%',
color: 'black',
softConnector: true
},
neckWidth: '50%',
neckHeight: '50%',
minSize: '20%',
//-- Other available options
height: '200'
// width: pixels or percent
}
You can see my horrible attempt here at it here: JSFiddle thingy
So to the actual question: Is it possible to set an minimum limit for the section in the funnel?
Any suggestions or just a simple: "dude, not possible" is appreciated!
Cheers!
Unfortunately this is not supported (good idea to post this on userVoice!)
However I have created simple example that you can preprocess data and still display proper values: https://jsfiddle.net/69eey/2/
$(function () {
var dataEx = [
['Raw Events', 349531093],
['Filtered/Aggregated Events', 156777100],
['Correlated Events', 2792294],
['Use Case Events', 572480],
['Finalized', 0]
],
len = dataEx.length,
sum = 0,
minHeight = 0.05,
data = [],
i;
for(i = 0; i < len; i++){
sum += dataEx[i][1];
}
for(i = 0; i < len; i++){
var t = dataEx[i],
r = t[1] / sum;
data[i] = {
name: t[0],
y: ( r > minHeight ? t[1] : sum * minHeight ),
label: t[1]
}
}
It is only workaround of course. You also need to use formatter for a tooltip to make sure you will display proper values (like for dataLabels).
I took Paweł Fus's great example and extended it to include the tooltip correction. Just add the snippet below:
tooltip: {
formatter: function() {
return '<b>'+ this.key +
'</b> = <b>'+ Highcharts.numberFormat(this.point.label, 0) +'</b>';
}
},
JSFiddle with a working example:
HTML
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/funnel.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="width: 600px; height: 400px; margin: 0 auto"></div>
JavaScript
$(function () {
var dataEx = [
['Raw Events', 349531093],
['Filtered/Aggregated Events', 156777100],
['Correlated Events', 2792294],
['Use Case Events', 572480],
['Finalized', 0]
],
len = dataEx.length,
sum = 0,
minHeight = 0.05,
data = [];
for(var i = 0; i < len; i++){
sum += dataEx[i][1];
}
for(var i = 0; i < len; i++){
var t = dataEx[i],
r = t[1] / sum;
data[i] = {
name: t[0],
y: ( r > minHeight ? t[1] : sum * minHeight ),
label: t[1]
}
}
$('#container').highcharts({
chart: {
type: 'funnel',
marginRight: 100
},
title: {
text: 'SEIM Metrics',
x: -50
},
tooltip: {
//enabled: false
formatter: function() {
return '<b>'+ this.key +
'</b> = <b>'+ Highcharts.numberFormat(this.point.label, 0) +'</b>';
}
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
formatter: function(){
var point = this.point;
console.log(point);
return '<b>' + point.name + '</b> (' + Highcharts.numberFormat(point.label, 0) + ')';
},
minSize: '10%',
color: 'black',
softConnector: true
},
neckWidth: '50%',
neckHeight: '50%',
//-- Other available options
height: '200'
// width: pixels or percent
}
},
legend: {
enabled: false
},
series: [{
name: 'Unique users',
data: data
}]
});
});
You can try normalizing the values first by taking log.
log(349531093)=8.5
log(572480)=5.75