I have been working on the highchart for a while, I have the chart like this
and i have placed the legend at the botton of the page and what i need to do is make the legend text align center like in the following image
I found few question of text alignment in highchart but does not suite my request. So I am unable to move further.
Fiddle http://jsfiddle.net/AbNpB/12/
Thanks in Advance!
It's possible to align each line using a custom code that will translate each legend item.
It's easier to resize output window in JSFiddle: http://jsfiddle.net/BlackLabel/a02czac2/
$(function() {
(function(H) {
H.wrap(H.Legend.prototype, 'render', function(proceed) {
// proceed
proceed.apply(this, [].slice.call(arguments, 1));
// custom
var legend = this,
centerRow = function(tab, w, x) {
var offset = (legend.legendWidth - (x + w)) / 2;
H.each(tab, function(elem) {
elem.legendGroup.attr({
translateX: elem.legendGroup.translateX + offset
});
});
}
if (legend.options.centerItemLines) {
var items = legend.allItems || [],
lastY = items[0] && items[0]._legendItemPos[1],
rowItems = [],
pos, prevX, prevW;
H.each(items, function(item) {
pos = item._legendItemPos;
if (pos[1] > lastY) {
lastY = pos[1];
centerRow(rowItems, prevW, prevX);
rowItems = [];
}
rowItems.push(item);
prevX = pos[0];
prevW = item.legendGroup.getBBox(true).width;
});
centerRow(rowItems, prevW, prevX); // last line
}
});
}(Highcharts))
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
legend: {
itemStyle: {
width: 350
},
centerItemLines: true
},
series: [{
data: [6, 4, 2],
name: 'First'
}, {
data: [7, 3, 2],
name: 'Second a longer legend text and longer and longer and longer'
}, {
data: [9, 4, 8],
name: 'Third'
}, {
data: [1, 2, 6],
name: 'Fourth'
}, {
data: [4, 6, 4],
name: 'Fifth'
}]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 400px;"></div>
Try to add this one:
legend: {
align: 'center',
verticalAlign: 'bottom',
x: 0,
y: 0
},
Hope this helps.
Related
I have a problem with marking area: i need to be able to select a bar area based on xAxis, for example from 0 to 1, from 1 to 2, etc. But when i try to provide options for bar like
[{xAxis: 0, itemStyle: {color: red}},{xAxis: 1}]
it marks an area from a middle of xAxis area with an index of 0 to a middle of xAxis area with an index of 1. Is there a way to make it mark from start of an area to an end. Currently i managed to do so only with x option in pixels:
https://codesandbox.io/s/react-echart-markarea-ksj31?file=/src/index.js:714-726
Is there a better way to do it?
I can't imagine a method that would cover your requirements. It seems there is no such but nothing prevents to do it ourselves, see below.
When call function with join = true markedArea will calc as range from first to last.
calcMarkAreaByBarIndex(myChart, join = true, [4, 9])
When call function with join = false markedArea will calc for each bar.
calcMarkAreaByBarIndex(myChart, join = true, [4, 5, 6, 9])
var myChart = echarts.init(document.getElementById('main'));
var option = {
tooltip: {},
xAxis: {
data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
},
yAxis: {},
series: [
{
id: 'myBar',
name: 'Series',
type: 'bar',
data: [11, 11, 11, 11, 12, 13, 110, 123, 113, 134, 93, 109],
markArea: {
data: [
[{x: 184},{x: 216}],
[{x: 224},{x: 256}],
]
},
},
]
};
myChart.setOption(option);
function calcMarkAreaByBarIndex(chartInstance, join = false, barIdx){
var series = chartInstance.getModel().getSeriesByType('bar');
var seriesData = series.map((s, idx) => s.getData())[0];
var barNum = seriesData.count();
var barCoors = [];
var layout = idx => seriesData.getItemLayout(idx);
for(var i = 0; i < barNum; i++){
if(!barIdx.includes(i)) continue;
barCoors.push([
{ x: layout(i).x },
{ x: layout(i).x + layout(i).width },
])
}
if(join){
return [
[
{ x: barCoors[0][0].x },
{ x: barCoors[barCoors.length - 1][1].x }
]
]
} else {
return barCoors
}
}
var markedAreas = {
series: {
id: 'myBar',
markArea: {
data: calcMarkAreaByBarIndex(myChart, join = true, [4,9])
}
}
};
myChart.setOption(markedAreas);
<script src="https://cdn.jsdelivr.net/npm/echarts#4.7.0/dist/echarts.min.js"></script>
<div id="main" style="width: 600px;height:400px;"></div>
I found a solution, that worked for me:
Basically, you need to manually set yAxis's max props, add another xAxis, make it invisible, create a custom series with type 'bar' and set xAxisIndex to 1:
data: [maxYaxisValue,maxYaxisValue...], //length === xAxis.data.length
type: 'bar',
barWidth: '100%',
color: transparent,
xAxisIndex: 1,
And style a bar by index with background color and borderWidth
You can check the working example here
https://codesandbox.io/s/react-echart-markarea-m0mgq?file=/src/index.js
I'm having trouble aligning tooltip position on bar chart. Tooltip positioning works fine if all charts are line chart but not with bar/column charts. Could the Highcharts experts please help me with this issue?
http://jsfiddle.net/yhenwtsb/1/
var charts = [],
options1, options2;
function syncTooltip(container, p) {
var i = 0;
for (; i < charts.length; i++) {
if (container.id != charts[i].container.id) {
if (charts[i].tooltip.shared) {
charts[i].tooltip.refresh([charts[i].series[0].data[p]]);
} else {
charts[i].tooltip.refresh(charts[i].series[0].data[p]);
}
}
}
}
options1 = {
chart: {
type: "column",
inverted: true
},
plotOptions: {
series: {
point: {
events: {
mouseOver: function() {
syncTooltip(this.series.chart.container, this.x - 1);
}
}
}
}
},
xAxis: {
type: 'datetime'
}
};
options2 = {
plotOptions: {
series: {
point: {
events: {
mouseOver: function() {
syncTooltip(this.series.chart.container, this.x - 1);
}
}
}
}
},
xAxis: {
type: 'datetime'
}
};
charts[0] = new Highcharts.Chart($.extend(true, {}, options1, {
chart: {
renderTo: 'container1',
marginLeft: 40, // Keep all charts left aligned
},
tooltip: {
shared: true,
crosshairs: true,
valueDecimals: 2
},
series: [{
data: [
[1, 29.9],
[2, 71.5],
[3, 106.4]
]
}, {
data: [
[1, 59.9],
[2, 91.5],
[3, 136.4]
]
}]
}));
charts[1] = new Highcharts.Chart($.extend(true, {}, options2, {
chart: {
renderTo: 'container2',
marginLeft: 40, // Keep all charts left aligned
},
tooltip: {
shared: false
},
series: [{
data: [
[1, 29.9],
[2, 71.5],
[3, 106.4]
]
}]
}));
You can set tooltip.followPointer to true and add a small plugin to synchronize the second chart:
(function(H) {
H.wrap(H.Pointer.prototype, 'runPointActions', function(proceed, e, p) {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
var tooltipPos = this.chart.tooltip.now;
Highcharts.charts.forEach(function(chart) {
if (chart !== this.chart) {
chart.tooltip.updatePosition({
plotX: tooltipPos.x - chart.plotLeft,
plotY: tooltipPos.y - chart.plotTop
});
}
}, this);
});
}(Highcharts));
Live demo: http://jsfiddle.net/BlackLabel/2w9683gb/
API Reference: https://api.highcharts.com/highcharts/tooltip.followPointer
Docs: https://www.highcharts.com/docs/extending-highcharts
Currently, I'm showing a max point in the line chart. But I want to change dataMax to top 5 max value points in chart.How can I achieve this in Highcharts?
var defaultData = 'urlto.csv';
var urlInput = document.getElementById('fetchURL');
var pollingCheckbox = document.getElementById('enablePolling');
var pollingInput = document.getElementById('pollingTime');
function createChart() {
Highcharts.chart('closed5', {
chart: {
type: 'area',
zoomType: 'x'
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
style: {},
formatter: function() {
if (this.y === this.series.dataMax) {
return this.y;
}
}
}
}
},
title: {
text: 'Chart for charting'
},
data: {
csvURL: urlInput.value,
enablePolling: pollingCheckbox.checked === true,
dataRefreshRate: parseInt(pollingInput.value, 10)
}
});
if (pollingInput.value < 1 || !pollingInput.value) {
pollingInput.value = 1;
}
}
urlInput.value = defaultData;
// We recreate instead of using chart update to make sure the loaded CSV
// and such is completely gone.
pollingCheckbox.onchange = urlInput.onchange = pollingInput.onchange = createChart;
// Create the chart
createChart();
As #ewolden rightly noticed, you can sort your data and show only the five highest values:
var data = [11, 22, 33, 44, 55, 66, 15, 25, 35, 45, 55, 65],
sortedData = data.slice().sort(function(a, b){
return b - a
});
Highcharts.chart('container', {
series: [{
data: data,
dataLabels: {
enabled: true,
formatter: function() {
if (sortedData.indexOf(this.y) < 5) {
return this.y;
}
}
}
}]
});
Live demo: http://jsfiddle.net/BlackLabel/xkf2w5tb/
API: https://api.highcharts.com/highmaps/series.mapbubble.dataLabels.formatter
As far as I know formatter callback is the way to format the data labels. If you want to show the top N points you should sort the data in a new array and pull the top 5 values. This is an example of how to clone and sort the array and extract the top 5 elements in the formatter call.
let data = [32, 10, 20, 99, 30, 54, 85, 56, 11, 26, 15, 45, 55, 65];
//Copy the array
let temp = data.slice();
// Sort the temp array in descending order
temp.sort((a, b) => b - a);
Highcharts.chart('closed5', {
chart: {
type: 'area',
zoomType: 'x'
},
title: {
text: 'Chart for charting'
},
series: [{
data: data,
dataLabels: {
enabled: true,
formatter: function() {
if (temp.indexOf(this.y) < 5) {
return this.y;
}
},
},
}]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="closed5"></div>
I am trying to do a d3 horizontal funnel chart.
Everything is working properly but tooltip position is not working properly it appears at a different location.
Here is my code:
const data = [
["L0", 10],
["L1", 0],
["L2", 5],
["L3", 10],
["L4", 3],
["L5", 10]
];
newdata = data.map(function (d,i){
var new_d = d
if (new_d[1] == 0){
new_d[1] = 0.50
}
return new_d
})
const options = {
chart: {
width: 200,
height: 450,
bottomWidth: 1 / 2,
bottomPinch: 1,
},
block: {
dynamicSlope: true,
dynamicHeight: true,
minHeight:50
},
label: {
enabled: true,
fontSize: '18px',
fill: '#fff',
/* format: '{l}: {f}' */
format: function(label, value) {
console.log('value', value);
if(value ==0.50){
var a=0;
return label+ ":" + a;
}else{
return label+ ":" + value;
}
}
},
tooltip: {
enabled: true,
format: '{l}: {f}'
}
};
const chart = new D3Funnel('#funnel');
chart.draw(newdata, options);
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://rawgit.com/jakezatecky/d3-funnel/master/dist/d3-funnel.min.js"></script>
<div id="funnel" style="transform: rotate(270deg);height: 539px;width:1px;margin-left:267px;"></div>
(from http://jsfiddle.net/3x265bLj/79/)
I was under the assumption the "Play with this data!" link was supposed the show up by default. Any ideas on why it may not appear? I am just working with a basic scatter plot.
Note that this code below is not standalone as is, it is just the excerpt that does the plotly work.
var xData = [];
var yData = [];
var h = results;
for(var k in h) {
var localdate = k;
var plotdate = moment(localdate).format('YYYY-MM-DD HH:mm:ss');
xData.push(plotdate);
if (currentPort === "t") {
yData.push(CtoF(h[k]));
} else {
yData.push(h[k]);
};
}
var plotdata = [
{
x: xData,
y: yData,
type: 'scatter',
mode: 'markers+lines',
line: {
'color': HELIUM_BLUE
},
marker: {
'symbol': 'circle',
'color': HELIUM_PINK,
'maxdisplayed': 50
}
}
];
var layout = {
title: currentData,
xaxis: {
'title': 'Date / Time'
},
yaxis: {
'title': title
}
};
Plotly.newPlot(plotHolder, plotdata, layout);
You would need to add {showLink: true} as the fourth argument (after layout). I guess the default value changed from true to false.
If you want to change the caption of the button, use {showLink: true, "linkText": "Play with this data"}
var xData = [1, 2, 3, 4, 5];
var yData = [10, 1, 25, 12, 9];
var plotdata = [
{
x: xData,
y: yData,
type: 'scatter',
mode: 'markers+lines',
}
];
var layout = {
title: 'Edit me',
xaxis: {
'title': 'x'
},
yaxis: {
'title': 'y'
}
};
Plotly.newPlot(plotHolder, plotdata, layout, {showLink: true, "linkText": "Play with this data"});
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id='plotHolder'>
</div>