Based on the Highcharts documentation you can create your own point marker by defining a custom callback for an (SVG-based) symbol path.
However, what if you need to get at the underlying series data from within the symbol prototype function? Is that possible?
For instance:
Highcharts.SVGRenderer.prototype.symbols.cross = function (x, y, w, h) {
// I want to be able to access the series data from here.
// Either the point data or the entire series' data array.
return ['M', x, y, 'L', x + w, y + h, 'M', x + w, y, 'L', x, y + h, 'z'];
};
if (Highcharts.VMLRenderer) {
Highcharts.VMLRenderer.prototype.symbols.cross = Highcharts.SVGRenderer.prototype.symbols.cross;
}
Highcharts.chart('container', {
title: {
text: 'Demo of predefined, image and custom marker symbols'
},
legend: {
y: -40 // make room for subtitle
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
series: [{
name: 'Custom symbol',
data: [54.4, 29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6],
marker: {
symbol: 'cross',
lineColor: null,
lineWidth: 2
}
}],
credits: {
enabled: false
},
subtitle: {
text: '*) Base64 not supported in IE6 and IE7',
verticalAlign: 'bottom',
align: 'right',
y: null,
style: {
fontSize: '10px'
}
}
});
<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; max-width: 800px; margin: 0 auto"></div>
Turns out, you can actually define the marker properties at the individual point level. From there, you can provide the value and make it accessible from within the custom callback.
Like so:
Highcharts.SVGRenderer.prototype.symbols.cross = function(x, y, w, h, d) {
// I want to be able to access the series data from here.
// Either the point data or the entire series' data array.
if (d.v) {
console.debug("Point-specific data: " + d.v);
}
// From here, you can imagine one can use the point-specific data to affect the symbol path.
// A good example would be to in case you want to build a series of custom wind barbs,
// in which the path of the barb will be based on the intensity and direction of each point
// ...
return ['M', x, y, 'L', x + w, y + h, 'M', x + w, y, 'L', x, y + h, 'z'];
};
if (Highcharts.VMLRenderer) {
Highcharts.VMLRenderer.prototype.symbols.cross = Highcharts.SVGRenderer.prototype.symbols.cross;
}
Highcharts.chart('container', {
title: {
text: 'Demo of predefined, image and custom marker symbols'
},
xAxis: {
type: 'datetime'
},
series: [{
name: 'Custom symbol',
data: [{
x: 1525089600000,
y: 54.4,
marker: {
symbol: "cross",
v: 54.4
}
},
{
x: 1525090500000,
y: 71.5,
marker: {
symbol: "cross",
v: 71.5
}
},
{
x: 1525091400000,
y: 29.9,
marker: {
symbol: "cross",
v: 29.9
}
}
],
marker: {
symbol: 'cross',
lineColor: null,
lineWidth: 2
}
}],
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 400px"></div>
Related
I'm trying to populate a HighCharts dataset with results from SQL Server in Classic ASP.
When the number of series is known everything work OK but I can't get it work correctly for unknown number of series.
Here is my code for 4 series - 1 line and 3 columns.
<script type="text/javascript">
$(function () {
var DivName1 = '<%= DivName(1)%>'
var DivName2 = '<%= DivName(2)%>'
var DivName3 = '<%= DivName(3)%>'
var DivName4 = '<%= DivName(4)%>'
var DivN1 = parseInt('<%= DivN(1)%>')
var DivN2 = parseInt('<%= DivN(2)%>')
var DivN3 = parseInt('<%= DivN(3)%>')
var DivN4 = parseInt('<%= DivN(4)%>')
var DivTotal1 = parseFloat('<%= DivTotal(1)%>')
var DivTotal2 = parseFloat('<%= DivTotal(2)%>')
var DivTotal3 = parseFloat('<%= DivTotal(3)%>')
var DivTotal4 = parseFloat('<%= DivTotal(4)%>')
$('#DivCompTotalA').highcharts({
chart: {
type: 'column'
},
title: {
text: ''
},
credits: {
enabled: false
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
itemWidth: 180,
useHTML: true,
x: 0,
y: 40,
borderWidth: 0
},
xAxis: {
categories: ['']
},
yAxis: {
max: 7.01,
labels: {
enabled: false
},
gridLineColor: 'transparent',
plotLines: [{
value: DivTotal1,
color: '#333333',
width: 2,
label: {
text: 'Org.=' + DivTotal1 + '<br>N=' + DivN1,
align: 'right',
y: -5,
x: 0,
style: {
fontSize: '13px'
}
},
zIndex: 2
}],
title: {
text: ''
}
},
plotOptions: {
column: {
pointPadding: 0.2,
groupPadding: 0.10,
borderWidth: 0
},
series: {
dataLabels: {
enabled: true,
y: 5,
style: {
fontSize: '14px'
}
},
enableMouseTracking: false,
events: {
legendItemClick: function () {
return false;
}
}
}
},
series: [{
name: DivName2 + ' [' + DivN2 + ']',
color: '#c9e7ff',
data: [DivTotal2]
}, {
name: DivName3 + ' [' + DivN3 + ']',
color: '#4898a4',
data: [DivTotal3]
}, {
name: DivName4 + ' [' + DivN4 + ']',
color: '#ffd949',
data: [DivTotal4]
}]
});
});
My first question is How to replace these lines:
var DivName1 = '<%= DivName(1)%>'
var DivName2 = '<%= DivName(2)%>'
var DivName3 = '<%= DivName(3)%>'
var DivName4 = '<%= DivName(4)%>'
with a loop I tried this loop but with no success
var N = '<%=N %>'
var DivName = []
for (var i = 0; i <= N; i++) {
DivName[i] = '<%= DivName(i)%>';
}
How to write the "i" inside the '<%= DivName(i)%>' so it will be a variant
Try something like this:
Set series to nothing:
series: []
Fill it by script (where seriesData is array of prepared data. For format check documentation
$.each(Div, function(i){
var chart = $('#container').highcharts();
if (chart.series.length === 1) {
chart.addSeries({
name: Div[i].Name + i + ' [' + Div[i].N + ']',
color: '#c9e7ff',
data: Div[i].Total
});
}
});
Here an example how to add 1 series. You can add as many as you like with each loop.
$(function () {
$('#container').highcharts({
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
});
// the button handler
$('#button').click(function () {
var chart = $('#container').highcharts();
if (chart.series.length === 1) {
chart.addSeries({
data: [194.1, 95.6, 54.4, 29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4]
});
}
});
});
I have a column chart. When clicking one of the vertical bars, the color of the selected bar changes. I want to disable this behaviour by disabling the detection of the 'click' event on the graph so when the user clicks there nothing happens.
Anyone knows how to do that?
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column',
backgroundColor: 'transparent',
container: {
onclick : null
}
},
colors: ['#27A1DE'],
title: {
text: null
},
credits : {
enabled: false
},
exporting : {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
title: {
text: 'h',
align: 'high',
offset: -15
},
tickColor : 'transparent',
labels: {
style: {
fontWeight:'bold'
},
y: 12,
formatter: function() {
var index = this.axis.categories.indexOf(this.value);
var yValue = this.chart.series[0].yData[index];
if (yValue === 0){
return '<span>'+this.value+'</span>';
} else {
return '<span style="color:#009DE0;">'+this.value +'</span>';
}
}
},
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: {
min: 0,
labels: {
enabled: false
},
gridLineWidth: 0,
lineWidth: 1,
title: {
align: 'high',
rotation: 0,
text: 'kWh',
offset: 0,
y: -2
}
},
plotOptions: {
column: {
pointPadding: 0.05,
groupPadding: 0,
dataLabels : {
enabled: true,
crop :false,
overflow: 'none',
rotation: 270,
x:2,
y:-14,
style: {
color: '#009DE0',
fontSize: 'xx-small',
},
formatter: function() {
if (this.y != 0){
return '<span>'+this.y +'</span>';
} else {
return '<span style="display:none;">'+this.y +'</span>';
}
}
},
borderWidth: 0,
events: {
click: function(e){
//this.update({ color: '#27a1de' }, true, false);
e.preventDefault();
return false;
}
}
},
series: {
cursor: 'pointer',
point: {
events: {
click: function() {
}
}
}
}
},
series: [{
name: '',
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}],
tooltip: {
enabled: false
}
});
Fiddle : here
Thanks
the way I understood your problem, you want to remove the style change on mouse hover (as there is no color change on click in your fiddle unlike you described).
http://jsfiddle.net/6pur4o1w/
states: { hover: 'none' }
in the series should do what you want.
I have a bar chart. I want the dataLabels to not stick onto the bars, but move it to the most right border of the plot area and have it text-aligned right.
This is what I have come to so far: (jsfiddle)
$(function () {
var cat = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug']; //, 'Sep', 'Oct', 'Nov', 'Dec', 'foo', 'bar', 'bla'];
var barWidth = 16;
chart = new Highcharts.Chart({
chart: {
type: "bar",
renderTo: 'container',
events: {
load: function() {
var plotHeight = this.plotHeight;
console.log('plotHeight = ' + plotHeight);
var catWidth = (barWidth-2) / (2*plotHeight/cat.length);
var plot = [];
for(var i=0; i<(cat.length); i+=1) {
var newPlot = {
color: 'grey',
width: 1,
value: i+catWidth //+(cat.length/($('#container').height()/10))
};
plot.push(newPlot);
this.xAxis[0].addPlotLine(newPlot);
}
//this.xAxis[0].addPlotLine(plot);
}
}
},
title: {
text: null
},
credits: {
text: null,
enabled: false
},
xAxis: {
categories: cat,
title: {
text: null,
enabled: false
}
},
yAxis: {
title: {
text: null,
enabled: false
},
labels: {
enabled: false
},
gridLineWidth: 0,
gridLineColor: 'none'
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
color: '#000',
formatter: function() {
return Math.abs(this.y).toFixed(1) + '%';
},
crop: false, // DIRTY!!! :(
overflow: 'justify', // DIRTY!!! :(
x: -360 // DIRTY!!! :(
}
}
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5], //, 216.4, 194.1, 95.6, 54.4, 9.9, 9.9, 9.9],
pointWidth: barWidth
}]
});
});
I have to stick at mostly native Highcharts as I need to export the chart as svg to reuse in a pdf file. So using CSS and useHtml: true are out of question as well as dirty hacks like crop: false, overflow: 'justify', dataLabels.x: -360 (just to show you what I want to do - although it is not right aligned).
How am I able to accomplish that?
You can use workaround with the translating datalables like here:
var width = chart.plotWidth;
$.each(chart.series[0].data, function(i,d){
var bbox = d.dataLabel.getBBox().width;
d.dataLabel.attr({
x: width - bbox
});
});
http://jsfiddle.net/9YyVJ/2/
I have a chart that displays [x,y] using highcharts .I want to use more than [x,y] when I specify in an array say minimum value, maximum value.
I have an array like this: array1[['apples',no of apples,11,12],['oranges',no of oranges,1,2]
How do I employ this array in my following chart? I understand I have to specify this array1 in the series option. But which chart should I use? How do I represent the point in the chart when it has more than [x,y] option in the array defined as above.
$(document).ready(function fruits() {
$('#container').highcharts({
title: {
text: 'fruits'
},
xAxis: {
categories: ['Apple', 'Orange']
},
yAxis: {
title: {
text: 'No of fruits'
},
tickInterval: 10
},
series: [{
name: 'Fruits',
data: [
['apple', 29.9],
['orange', 71.5]
]
}]
});
});
For example,if i use column range chart I have min and max values under the same point.
But I need no of fruits, mean and median also to be included in the same chart.I don want to draw a separate line for mean and median instead use a single line for each point that shows no of fruits,min,max,median inthe tool tip.I want data to be [apple,5,4,12.5,10]
$(function () {
$('#container').highcharts({
chart: {
type: 'columnrange',
inverted: false
},
title: {
text: 'Temperature variation by month'
},
subtitle: {
text: 'Observed in Vik i Sogn, Norway, 2009'
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: {
title: {
text: 'Temperature ( °C )'
}
},
tooltip: {
valueSuffix: '°C'
},
plotOptions: {
columnrange: {
dataLabels: {
enabled: true,
formatter: function () {
return this.y + '°C';
}
}
}
},
legend: {
enabled: false
},
series: [{
name: 'Min and Max',
data: [
[-9.7, 9.4],
[-8.7, 6.5],
[-3.5, 9.4],
[-1.4, 19.9],
[0.0, 22.6],
[2.9, 29.5],
[9.2, 30.7],
[7.3, 26.5],
[4.4, 18.0],
[-3.1, 11.4],
[-5.2, 10.4],
[-13.5, 9.8]
]
}
]
]
});
});
You need two categories and then two series, like this:
xAxis: {
categories: ['Apples', 'Oranges'],
title: {
text: null
}
},
series: [{
name: 'Min',
data: [11, 12]
}, {
name: 'Max',
data: [20, 24]
}]
Here's an example fiddle: http://jsfiddle.net/UZj2K/
I think what you are looking for is called a columnrange chart.
I don't think it's a good idea to put all the data in a single point. But Error Bar or Box plot might fit your need. Here is an example of box plot chart. It's not exactly what you want but it's close. http://jsfiddle.net/7kFh4/
If you want to use only one line on a chart, and just display all detailed info only in tooltip, you can simple pass point as object, and then format tooltip, see: http://jsfiddle.net/3bQne/566/
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
xAxis: {
categories: ['apple', 'banana']
},
tooltip: {
formatter: function() {
var o = this.point.options;
return this.x + '<br>' +
this.series.name + '<br>' +
'Count: ' + this.y + '<br>' +
'Min: ' + o.min + '<br>' +
'Max: ' + o.max + '<br>' +
'Mean: ' + o.mean + '<br>' +
'Median: ' + o.median + '<br>';
}
},
series: [{
data: [{
x: 0,
y: 5,
min: 10,
max: 15,
median: 13.4,
mean: 12.1
},{
x: 1,
y: 6,
min: 13,
max: 16,
median: 13.4,
mean: 15.2
}]
}]
});
I want to create dynamic data for high charts,
i need to generate dynamic values in the x-axis
xAxis: {
categories:['project1','project2']
},
This is my for loop,
var project = [];
for(var i=0;i<project.name;i++){
//new array
}
How do i create dynamic values in the x-axis.
You can pass an array variabile as parameter to the categories option of the chart.
Example:
// Original array
var categories1=['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
// Copy and/or modifify the second array content and do some stuff
var categories2=[];
for(var i=0;i<categories1.length;i++){
categories2.push(categories1[i]);
}
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
xAxis: {
categories: categories2 // reference categories to an array variabile
},
series: [{
data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
}]
});
Working fiddle: http://jsfiddle.net/IrvinDominin/6c8Af/
Another approach:
var Series2 = [1,1,1,2,2,2];
var names=['O','A'];
var data1=Series2,seriesArray; //seriesArray is formed dynamically - array of int values
options.series = [{name: names, data: data1}]
This works properly
I'm using a JSON data and after a long time able to resolve it. My requirement was to get JSON data and then I create a Map Object based on my data requirement. And dynamically create series for chart. I was able to create Series but nothing was coming in chart.
This was because the numeric digits has to be converted to Int . When I used parseInt, it worked for me.
Step 1: I get the JSON data and after manipulation it looks like this: seriesData = {"O":series1}, {"A":Series2}, {"S":Series3}]
var options = {
chart: {
renderTo: 'demoGraph',
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
categories: [1, 2, 3, 4, 5,6],
title: {
text: 'Severity'
},
},
yAxis: {
min: 0,
title: {
text: 'Total Defects with Severity - 1,2,3,4,5,6'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
legend: {
align: 'right',
x: -70,
verticalAlign: 'top',
y: 20,
floating: true,
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false
},
tooltip: {
formatter: function () {
return '<b>' + this.x + '</b><br/>' +
this.series.name + ': ' + this.y + '<br/>' +
'Total: ' + this.point.stackTotal;
}
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px black, 0 0 3px black'
}
}
}
},
series: [{},{},{},{},{},{}],
};
for(var i in seriesData ){
for(var j in seriesData [i]){
options.series[i].name = j;
options.series[i].data = seriesData [i][j];
break;
}
}
var chart = new Highcharts.Chart(options);