I have Highcharts Gauge chart with multiple needles and the datalabels of the needles are overlapped each other like http://jsfiddle.net/edLHB/3/
plotOptions I have used as following
plotOptions: {
guage: {
dataLabels: {
enabled: true,
crop: false,
overflow: 'none'
}
}
},
Please help me to get datalabels without overlapping.
Thanks
Give them individual x or y values in the series
series: [{
name: 'Speed',
data: [80],
dataLabels: {
y:50
}
}, {
name: 'Speed',
data: [100],
dataLabels: {
y:30
}
}, {
name: 'Speed',
data: [150],
dataLabels: {
y:10
}
}]
Demo: http://jsfiddle.net/robschmuecker/edLHB/7/
In general this solution is not supported (I mean collision detection), but you adapt this solution http://jsfiddle.net/menXU/6/.
function StaggerDataLabels(series) {
sc = series.length;
if (sc < 2) return;
for (s = 1; s < sc; s++) {
var s1 = series[s - 1].points,
s2 = series[s].points,
l = s1.length,
diff, h;
for (i = 0; i < l; i++) {
if (s1[i].dataLabel && s2[i].dataLabel) {
diff = s1[i].dataLabel.y - s2[i].dataLabel.y;
h = s1[i].dataLabel.height + 2;
if (isLabelOnLabel(s1[i].dataLabel, s2[i].dataLabel)) {
if (diff < 0) s1[i].dataLabel.translate(s1[i].dataLabel.translateX, s1[i].dataLabel.translateY - (h + diff));
else s2[i].dataLabel.translate(s2[i].dataLabel.translateX, s2[i].dataLabel.translateY - (h - diff));
}
}
}
}
}
Related
I am trying to make the regression to start from the origin , x=y=0. Is this possible to do. some say it is not good to do so but for some purposes I need to make the line through the origin. I am using highcharts.
How about adding a point to the regression series with x = y = 0 and setting the marker to disabled in order to hide it?
let discipline = [
{
name: "Football",
data: "football"
}
];
Highcharts.getJSON(
"https://raw.githubusercontent.com/mekhatria/demo_highcharts/master/olympic2012.json?callback=?",
function (data) {
function regression(arrWeight, arrHeight) {
let r, sy, sx, b, a, meanX, meanY;
r = jStat.corrcoeff(arrHeight, arrWeight);
sy = jStat.stdev(arrWeight);
sx = jStat.stdev(arrHeight);
meanY = jStat(arrWeight).mean();
meanX = jStat(arrHeight).mean();
b = r * (sy / sx);
a = meanY - meanX * b;
//Set up a line
let y1, y2, x1, x2;
x1 = jStat.min(arrHeight);
x2 = jStat.max(arrHeight);
y1 = a + b * x1;
y2 = a + b * x2;
return {
line: [
//Add x = 0, y = 0 to your regression logic?
{x: 0, y: 0, marker: {enabled: false}},
{x: x1, y: y1, marker: {enabled: true}},
{x: x2, y: y2, marker: {enabled: true}},
],
r
};
}
const getData = (continentName) => {
let temp = [],
tempWeight = [],
tempHeight = [];
data.forEach((elm) => {
if (
elm.continent == continentName &&
elm.weight > 0 &&
elm.height > 0
) {
temp.push([elm.height, elm.weight]);
tempWeight.push(elm.weight);
tempHeight.push(elm.height);
}
});
let { line, r } = regression(tempWeight, tempHeight);
return [temp, line, r];
};
const getDataSport = (sportName) => {
let temp = [],
tempWeight = [],
tempHeight = [];
data.forEach((elm) => {
if (elm.sport == sportName && elm.weight > 0 && elm.height > 0) {
temp.push([elm.height, elm.weight]);
tempWeight.push(elm.weight);
tempHeight.push(elm.height);
}
});
let { line, r } = regression(tempWeight, tempHeight);
return [temp, line, r];
};
let series = [],
visible = false,
index = 0,
activate = ["Football"];
discipline.forEach((e) => {
if (activate.indexOf(e.name) > -1) {
visible = true;
} else {
visible = false;
}
let [scatterData, line, r] = getDataSport(e.data);
series.push(
{
type: "scatter",
visible: visible,
name: e.name,
data: scatterData
},
{
name: e.name,
visible: visible,
r: r,
data: line
}
);
});
Highcharts.chart("container", {
chart: {
type: "line",
zoomType: "y",
},
title: {
text: "2012 Olympic football athletes' weight and height relationship"
},
xAxis: {
title: {
text: "Height"
},
labels: {
format: "{value} m"
},
},
yAxis: {
title: {
text: "Weight"
},
labels: {
format: "{value} kg"
}
},
legend: {
enabled: true
},
plotOptions: {
scatter: {
marker: {
radius: 2.5,
symbol: "circle",
states: {
hover: {
enabled: true,
lineColor: "rgb(100,100,100)"
}
}
},
states: {
hover: {
marker: {
enabled: false
}
}
}
},
line: {
lineWidth: 2.5
}
},
tooltip: {
formatter: function () {
if (this.series.data.length > 2) {
return (
this.series.name +
"<br/>Height: " +
this.x +
" m<br/>Weight: " +
this.y +
" kg"
);
} else {
return (
this.series.name +
"<br/>r: " +
this.series.userOptions.r.toFixed(2)
);
}
}
},
series: series
});
}
);
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/data.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jstat#latest/dist/jstat.min.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container"></div>
I have create a HighCharts Pie as follows :
This a parts of my source:
series: [{
name: 'Temps d\'arrêt',
type: 'pie',
data: getTempsDArretSeries(data2),
center: [35, 0],
size: 100,
showInLegend: false,
dataLabels: {
enabled: false
}
,tooltip: {
valueSuffix: ' min '+'<br><b>{point.percentage:.1f}%</b>',
}
,title: {
text: 'Temps d\'arrêt'
},
}]
My function getTempsDArretSeries(data2) is :
function getTempsDArretSeries(data){
var array = new Array();
var duree = 0;
var memProduit = 0;
$(data).each(function(){
if(memProduit!=0){
if(memProduit != parseInt(this.efcode)){
array.push(duree);
memProduit = parseInt(this.efcode);
duree = parseInt(this.efdur);
}else{
duree += parseInt(this.efdur);
}
}else{
duree += parseInt(this.efdur);
memProduit = parseInt(this.efcode);
}
})
array.push(duree);
return array;
}
I have the result as follows on my chart :
chart
It is possible to put something like :
name: memProduit,
y: duree,
sliced: true,
selected: true
for all lines.
Thanks,
Regards,
I've implemented a polar chart in which each series has 4 values corresponding to 4 categories. When I export the chart csv, the category column contains polar coordinates. I would like to replace these with the corresponding category name. How do I do this?
Adding the categories to each series, had no effect. I also tried adding a categories property to the xAxis, but it had not effect. An xAxis.label formatter successfully returns the category name for each data polar coordinate.
const options = {
chart: {
polar: true,
},
title: {
text: '',
},
tooltip: {
valueDecimals: 2,
headerFormat: '<br/>',
},
legend: {},
pane: {
startAngle: 0,
endAngle: 360,
},
xAxis: {
tickInterval: 45,
min: 0,
max: 360,
labels: {
// eslint-disable-next-line
formatter: function() {
switch (this.value) {
case 45:
return '<b>Experience</b>'
case 135:
return '<b>Frictionless</b>'
case 225:
return '<b>Low Price</b>'
case 315:
return '<b>Brand</b>'
default:
return ''
}
},
},
},
yAxis: {
min: 0,
max: 10,
labels: {
format: '{}',
},
},
plotOptions: {
series: {
pointStart: 45,
pointInterval: 90,
},
column: {
pointPadding: 0,
groupPadding: 0,
},
},
series: kahnSeries,
}
You need to use categories property, but without options like: pointInterval, pointStart, min and max:
xAxis: {
categories: ['Experience', 'Frictionless', 'Low Price', 'Brand']
},
Live demo: http://jsfiddle.net/BlackLabel/z8cm1p39/
API Reference: https://api.highcharts.com/highcharts/xAxis.categories
To avoid changing the chart's current display, I wrapped the getCSV function and replaced the CSV category values. If there was a simpler way, please share it.
{
(function (H) {
H.wrap(H.Chart.prototype, 'getCSV', function (
proceed,
useLocalDecimalPoint
) {
// Run the original proceed method
const result = proceed.apply(
this,
Array.prototype.slice.call(arguments, 1)
)
const itemDelimiter = ','
const lineDelimiter = '\n'
const rows = result.split(lineDelimiter)
let newResult = ''
let rowCategories = false
rows.forEach((row, rowIndex) => {
const columns = row.split(itemDelimiter)
if (rowIndex === 0 && columns[0] === '"Category"') {
rowCategories = true
}
if (rowIndex > 0 && rowCategories) {
let newRow = formatter(columns[0])
columns.forEach((column, columnIndex) => {
if (columnIndex > 0) {
newRow += itemDelimiter
newRow += column
}
})
newResult += newRow
} else {
newResult += row
}
if (rowIndex < rows.length - 1) {
newResult += lineDelimiter
}
}
)
return newResult
})
}(Highcharts))
}
my problem is that the primary and secondary yAxis zero is not on the same level. The screenshot can describe my problem better. Is there any possibility to fix this?
Here is the JSFiddle
Highcharts.chart('container', {
title: {
text: 'Stückzahl'
},
xAxis: {
categories: ['5007.205.1.1.1', '5007.225.1.1.1', '5007.285.1.1.1'],
labels:{
enabled: false
}
},
credits: {
enabled: false
},
legend:{
enabled: false
},
yAxis: [{
title: {
text: 'Stückzahl',
},
opposite: false
},{
title: {
text: 'FOR[%]',
},
opposite: true,
max:100,
min:0
}],
series: [
{
type: 'column',
name: 'Sollwert',
pointWidth:30,
grouping: false,
color: 'rgba(0,0,0,0.1)',
data: [2000, 1500, 1600],
yAxis: 0
},{
dataLabels:{
enabled:true
},
type: 'column',
grouping: false,
pointWidth:20,
name: 'John',
data: [1941, 975, 1936],
yAxis: 0
},{
dataLabels:{
enabled:true
},
color:'#ef703e',
grouping: false,
pointWidth:20,
type: 'column',
data: [-27, -15, -350],
yAxis: 0
},{
color:'black',
data: [80,60,99],
yAxis: 1,
type: 'line'
}]
});
To post this question, I need to describe my problem better. So ignore these last lines :/
There is an experimental wrap on Highcharts User Voice - multiple axis alignment control. It was written some time ago but it still works.
The wrap:
/**
* Experimental Highcharts plugin to implement chart.alignThreshold option. This primary axis
* will be computed first, then all following axes will be aligned to the threshold.
* Author: Torstein Hønsi
* Last revision: 2016-11-02
*/
(function (H) {
var Axis = H.Axis,
inArray = H.inArray,
wrap = H.wrap;
wrap(Axis.prototype, 'adjustTickAmount', function (proceed) {
var chart = this.chart,
primaryAxis = chart[this.coll][0],
primaryThreshold,
primaryIndex,
index,
newTickPos,
threshold;
// Find the index and return boolean result
function isAligned(axis) {
index = inArray(threshold, axis.tickPositions); // used in while-loop
return axis.tickPositions.length === axis.tickAmount && index === primaryIndex;
}
if (chart.options.chart.alignThresholds && this !== primaryAxis) {
primaryThreshold = (primaryAxis.series[0] && primaryAxis.series[0].options.threshold) || 0;
threshold = (this.series[0] && this.series[0].options.threshold) || 0;
primaryIndex = primaryAxis.tickPositions && inArray(primaryThreshold, primaryAxis.tickPositions);
if (this.tickPositions && this.tickPositions.length &&
primaryIndex > 0 &&
primaryIndex < primaryAxis.tickPositions.length - 1 &&
this.tickAmount) {
// Add tick positions to the top or bottom in order to align the threshold
// to the primary axis threshold
while (!isAligned(this)) {
if (index < primaryIndex) {
newTickPos = this.tickPositions[0] - this.tickInterval;
this.tickPositions.unshift(newTickPos);
this.min = newTickPos;
} else {
newTickPos = this.tickPositions[this.tickPositions.length - 1] + this.tickInterval;
this.tickPositions.push(newTickPos);
this.max = newTickPos;
}
proceed.call(this);
}
}
} else {
proceed.call(this);
}
});
}(Highcharts));
All you need to do is set alignThresholds in chart options.
Highcharts.chart('container', {
chart: {
alignThresholds: true
},
live example: http://jsfiddle.net/f3urehs0/
Hi everyone I am new using highcharts, I have my data structure and when I try to show, I don't see anything
function nueva (current_data){
var seriesOptions = [],
seriesCounter = 0,
type = ['jobs_running', 'jobs_pending'];
function createChart() {
$('#containerChart').highcharts('StockChart', {
rangeSelector: {
selected: 4
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
series: seriesOptions
});
}
for (var j = 0; j < current_data['names'].length; j++){
var all_element = []
name_project = current_data['names'][j];
for (var i = 0; i < type.length; i++){
seriesCounter = 0;
for (var i = 0; i < type.length; i++){
seriesOptions[j] = {
name: type[i],
data: current_data[name_project][type[i]],
};
}
}
createChart();
}
}
I pass current_data to my function that is like this
I want to show 'jobs_running' and 'jobs_pendding' I set the value to seriesOptions
and my array of data has this
Any idea why I don't see anything in the chart! I am missing something.
Thanks in advance
Hopefully you can find your answer in this:
https://jsfiddle.net/ekekp8rh/1/
Not sure what you were hoping to get but at least this displays a chart.
var data = {
projects: [{
name: 'Project X',
jobs_running: [
[1459814400000, 121],
[1459900800000, 205],
[1459987200000, 155],
[1460073600000, 458]
],
jobs_pending: [
[1459814400000, 146],
[1459900800000, 149],
[1459987200000, 158],
[1460073600000, 184]
]
}, {
name: 'Project Y',
jobs_running: [
[1459814400000, 221],
[1459900800000, 295],
[1459987200000, 255],
[1460073600000, 258]
],
jobs_pending: [
[1459814400000, 246],
[1459900800000, 249],
[1459987200000, 258],
[1460073600000, 284]
]
}]
};
nueva(data);
function nueva(current_data) {
var seriesOptions = [],
type = ['jobs_running', 'jobs_pending'];
for (var j = 0; j < current_data['projects'].length; j++) {
var project = current_data['projects'][j];
for (var i = 0; i < type.length; i++) {
seriesOptions.push({
name: project.name + ' ' + type[i],
data: project[type[i]]
});
}
}
$('#containerChart').highcharts('StockChart', {
series: seriesOptions
});
}