Related
If we have two line charts, comparing say My Portfolio vs Overall Portfolio, the area between two lines need to be highlighted as green where My Portfolio is more than Overall portfolio, and red where it is less.
This is the kind of output that is expected -
var chartDom = document.getElementById('profileAumChart');
var myChart = echarts.init(chartDom);
var option;
option = {
title: {
show: false
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['My Portfolio', 'Overall Portfolio']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
show: false
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Jan-21','Feb-21','Mar-21','Apr-21','May-21', 'Jun-21', 'Jul-21', 'Aug-21', 'Sep-21', 'Oct-21', 'Nov-21', 'Dec-21']
},
yAxis: {
type: 'value'
},
series: [
{
name: 'My Portfolio',
type: 'line',
areaStyle: {
color: 'green',
//opacity: 1,
},
data: [150100,175965,185385,201384,206279,235905,238021,239323,245282,247671,255447,275911],
},
{
name: 'Overall Portfolio',
type: 'line',
areaStyle: {
color:'red',
//opacity:1
},
data: [155066,165142,190811,192906,231941,250216,270047,288033,291842,308232,320941,334013],
}
]
};
option && myChart.setOption(option);
<script src="https://cdn.jsdelivr.net/npm/echarts#5.3.0/dist/echarts.min.js"></script>
<div id="profileAumChart" style="width:100%; height:270px;"></div>
I was able to replicate the effect with an hack. I added a hidden series which has the lowest of the two series, and use the attribute "areastyle" and their sub-attribute color and opacity along with z-index and I am able to show such region.
I am still looking for an elegant solution and in case someone post it would really appreciate it.
I am sharing my code which can help someone who intend to have similar effects using e-charts.
Thanks.
var chartDom = document.getElementById('profileMonthlyNetSales');
var myChart = echarts.init(chartDom);
var option;
option = {
title: {
show: false
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['My Portfolio', 'Overall Portfolio'],
left: 'left'
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
show: false
},
xAxis: {
type: 'category',
boundaryGap: false,
axisLabel:{
margin: 20,
},
data: ['Jan-21','Feb-21','Mar-21','Apr-21','May-21', 'Jun-21', 'Jul-21', 'Aug-21', 'Sep-21', 'Oct-21', 'Nov-21', 'Dec-21']
},
yAxis: [{
type: 'value',
min: -15000,
offset: 10,
axisLabel: {
//formatter: '${value}M'
formatter: function (value, index) {
return '$' + (value/1000) + 'k';
}
}
}
],
series: [
{
z:-1,
name: 'My Portfolio',
type: 'line',
areaStyle: {
color: 'green',
opacity:0.25,
origin: "start",
},
symbolSize: 5,
emphasis:{
disabled:true
},
data: [-6000,-1000,-7500,-7500,15300,16000,4900,5000,800, -9800, -10000, -9000],
},
{
z:-1,
name: 'Overall Portfolio',
type: 'line',
color: "#808080",
areaStyle: {
color:'red',
opacity: 0.25,
origin: "start",
},
symbolSize: 5,
emphasis:{
disabled:true
},
data: [-3000,-4000,-3700,-5000,15000,14800,5000,10200,5000,-9800,-1000,-8000],
},
{
z:-1,
name: 'Overall Portfolio1',
tooltip: {
show: false
},
type: 'line',
areaStyle: {
color:"white",
opacity:1.0,
origin: "start",
},
lineStyle: {
opacity: 0,
},
emphasis:{
disabled:true
},
symbolSize: 0,
data: [-6000,-4000,-7500,-7500,15000,14800,4900,5000,800,-9800,-10000,-9000],
}
],
};
option && myChart.setOption(option);
<script src="https://cdn.jsdelivr.net/npm/echarts#5.3.0/dist/echarts.min.js"></script>
<div id="profileMonthlyNetSales" style="width:100%; height:270px;"></div>
I ended up doing something similar to what #Amit Pandey did, but with stacked area charts.
https://echarts.apache.org/examples/en/editor.html?c=area-stack
You find the minimum of the 2 points, and render that as the bottom line/area, then you stack another area chart on top of that bottom line (this values for this stacked chart is the difference between the minimum values and the 'actual' chart value). You can then change the colour of the stacked chart to whatever you want and you can visualize that difference.
This still doesn't solve the issue of line intersects - so if you really want it to look good, you still have to calculate the intersections and add those points in - I ended up using mathjs' intersect function to do this.
I am trying to change the font weight of footer in tooltips in Chart JS. According to this link (https://www.chartjs.org/docs/latest/configuration/tooltip.html#tooltip-configuration), footerFont seems to be the one to control this but I could not quite get it to work
My code:
options: {
tooltips:{
footerFont: {weight: 'normal'},
callbacks: {
footer: function(tooltipItem, data) {
return 'some text'
}
}
},
}
Fiddle: https://jsfiddle.net/dqdqdq/yp47oL9t/10/ . The footer is still bold when we hover any bubbles.
You are looking at the documentation of chart.js version 3 which has some major changes from version 2, if you take the version 2 docs: https://www.chartjs.org/docs/2.7.1/configuration/tooltip.html you can see that the property is called a bit different and also just accepts a string
Working sample:
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bubble',
data: {
datasets: [{
label: 'Top',
data: [{
x: 110,
y: 0,
r: 10,
name: "Performance"
}],
backgroundColor: "rgba(153,255,51,0.6)"
},
{
label: 'Average',
data: [{
x: 75,
y: 0,
r: 10,
name: "Performance"
}],
backgroundColor: "rgba(153,155,51,0.6)"
},
]
},
pointDot: true,
options: {
tooltips: {
footerFontStyle: 'normal',
callbacks: {
footer: function(tooltipItem, data) {
return 'some text'
}
}
},
}
});
<canvas id="myChart"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.2.0/dist/chartjs-plugin-datalabels.min.js"></script>
I'm displaying a balance of a bank account over time. My goal is to have individual tool tips that show the balance AND the transaction that the balance change corresponds to.
I know I can format the Y value with a formatter, but after looking for a few hours I can't find a way to add data to each tool tip. For example the first tool tip might change the balance from 100 to 50, the tooltip would say 'credit card payment' the next tool tip might change the balance to 500 and the tool tip would say 'Paycheck'. here's what I'm doing in my options:
series: [{
name: 'Balance',
data: [
{
x: new Date('2018-02-12').getTime(),
y: 76
}, {
x: new Date('2019-02-12').getTime(),
y: 100
},
{
x: new Date('2020-02-12').getTime(),
y: 200
}, {
x: new Date('2021-02-12').getTime(),
y: 300
},
{
x: new Date('2022-02-12').getTime(),
y: 150
}, {
x: new Date('2023-02-12').getTime(),
y: 22
}
]
}],
options: {
chart: {
type: 'line',
stacked: false,
height: 380,
zoom: {
type: 'x',
enabled: true,
autoScaleYaxis: true
},
toolbar: {
autoSelected: 'zoom'
}
},
dataLabels: {
enabled: false
},
markers: {
size: 2,
},
title: {
text: 'Account balance over time',
align: 'left'
},
yaxis: {
labels: {
formatter: function (val) {
return val.balance;
},
},
title: {
text: 'Balance'
},
},
xaxis: {
type: 'datetime',
},
tooltip: {
shared: true,
y: {
formatter: function (val) {
return "$"+val;
}
}
}
},
Here is what the tooltips look like now:
Above the word 'balance' Id like it to say the actual transaction that's changing the balance. I'm wondering if this is possible at all with apex charts.
Have you tried these options from the docs: https://apexcharts.com/docs/options/tooltip/
There is a 'custom' function you can pass to create your own custom html
under the section called 'custom: function || Array of functions'
Here is the codepen they provide.
tooltip: {
custom: function({ series, seriesIndex, dataPointIndex, w }) {
return (
'<div class="arrow_box">' +
"<span>" +
w.globals.labels[dataPointIndex] +
": " +
series[seriesIndex][dataPointIndex] +
"</span>" +
"</div>"
);
}
}
Also, there is the 'formatter: function' where you can just provide a function to the formatter, similar to what you've already done.
I am trying to prepare a Tornado Chart using the column chart in Highcharts. Here is my fiddle.
My current code is:
$('#container').highcharts({
chart: {
type: 'columnrange',
inverted: true
},
title: {
text: 'Net Sales'
},
subtitle: {
text: 'MM $'
},
xAxis: {
categories: ['Annual Revenue', 'Number of Years', 'Annual Costs']
},
yAxis: {
title: {
text: 'MM $'
}
},
plotOptions: {
columnrange: {
dataLabels: {
enabled: true,
formatter: function () {
return this.y;
}
}
},
scatter:{
marker:{
symbol:'line',
lineWidth:11,
radius:8,
lineColor:'#f00'
}
}
},
legend: {
enabled: false
},
series: [{
name: 'Temperatures',
data: [
[12.15, 46.86],
[15.45, 42.28],
[27.77, 31.24]
]
},
{
name:'Base',type: 'scatter',data:[120],
}]
});
The problem is that the last series (Annual Costs) does not show, as it is in reversed order. Also, I'd like the Tornado Chart to look more like this:
Note that the labels in this chart are different from the actual values plotted. Also note that the bar in the center - in the example code, there would be a vertical line at 29.5. I would also like to support a combined uncertainty bar like the one at the bottom. Any suggestions would be greatly appreciated.
Your last bat is not showing, because first number is lower than second, see: http://jsfiddle.net/kErPt/1/
If you want to display another values at labels, then add that info first. Example:
data: [{
low: 12,
high: 15,
lowLabel: 35,
highLabel: 46
}, {
low: 2,
high: 35,
lowLabel: 15,
highLabel: 26
} ... ]
And then use dataLabels.formatter for series.
To add vertical line use plotLines.
I'm not sure what is the last bar called 'combined uncertainty'.
I've used Highcharts with separate series (thanks jlbriggs) to create a Tornado Chart: http://jsfiddle.net/uRjBp/
var baseValue = 29.5;
var outputTitle = "Net Sales";
var chart = new Highcharts.Chart({
chart: {
renderTo:'container',
//type:'column'
//type:'area'
//type:'scatter'
//type:'bubble'
},
credits: {},
exporting: {},
legend: {},
title: {
text: outputTitle
},
subtitle: {
text: "MM $"
},
tooltip: {
formatter: function() {
var msg = "";
var index = this.series.chart.xAxis[0].categories.indexOf(this.x);
var low = round(this.series.chart.series[0].data[index].y+baseValue);
var high = round(this.series.chart.series[1].data[index].y+baseValue);
if (this.x === "Combined Uncertainty") {
msg = "Combined Uncertainty in "+outputTitle+": "+low+" to "+high;
} else {
var lowLabel = this.series.chart.series[0].data[index].label;
var highLabel = this.series.chart.series[1].data[index].label;
msg = '<b>'+outputTitle+'</b> goes from '+ low +' to '+ high+'<br/> when '+this.x +
' goes from <br/> '+lowLabel+" to "+highLabel;
}
return msg;
}
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
formatter: function () {
var index = this.series.chart.xAxis[0].categories.indexOf(this.x);
if (this.series.userOptions.labels === undefined) {
return this.y+baseValue;
}
return this.key === "Combined Uncertainty" ? "":this.series.userOptions.labels[index];
}
}
}
},
xAxis: {
title: {
text: 'Factor'
},
allowDecimals:false,
categories: ['Annual Revenue', 'Number of Years', 'Annual Costs', 'Combined Uncertainty']
},
yAxis: {
title: {
text: 'MM $'
},
labels: {
formatter:function() {
return this.value+baseValue;
}
}
},
series:[{
name: 'Low',
grouping:false,
type:'bar',
data:[{y:12.15-baseValue, label:10},{y:15.45-baseValue, label:1},{y:31.25-baseValue, label:2},{y:12.15-baseValue, color:'#99CCFF', label: ""}],
labels:[10,1,2,]
},{
name: 'High',
grouping:false,
type:'bar',
data:[{y:46.86-baseValue, label:30},{y:42.28-baseValue, label:3},{y:27.77-baseValue, label:4},{y:46.86-baseValue, color:'#99CCFF', label:""}],
labels:[30,3,4,]
},
{
name: 'Median',
type: 'scatter',
data: [null,null, null,27-baseValue],
marker: {
lineWidth: 2,
lineColor: Highcharts.getOptions().colors[3],
fillColor: 'white'
}
}]
});
function round(num) {
return Math.round(num*100)/100;
}
usually, this kind of chart is done using a separate series for the left and right portions
One way to do this is by setting one set of data as negative numbers, and then using the formatters to make the axis labels, datalabels, and tooltips display the absolute values
example:
http://jsfiddle.net/jlbriggs/yPLVP/68/
UPDATE:
to show a line as in your original chart, you can extend the marker symbols to include a line type, and use a scatter series to draw that point:
http://jsfiddle.net/jlbriggs/yPLVP/69/
If you don't want to have the extra code for the line marker type, you could use any of the other existing marker symbols for the scatter series.
I am trying to display values which I am getting dynamically. In the below code I am trying to store the values in array and I am trying to use the array values in "series: data".
Nothing is getting displayed in the graph.
I know this is very simple question but I did not get any satisfactory answer when I googled it. Please help
var x = window.location.search.replace( "?", "" );
x = x.substring(3);
var array = x.split(","); // I am storing my dynamic values in this array
$(function () {
//alert(array); ----- I am able to see the values here
$('#container').highcharts({
chart: {
type: 'bar'
},
title: {
text: 'Wireless Experience Meter'
},
subtitle: {
text: 'Sub - Time to Download'
},
xAxis: {
categories: ['Text'],
title: {
text: null
}
},
yAxis: {
min: 0,
title: {
text: 'Time (ms)',
align: 'high'
},
labels: {
overflow: 'justify'
}
},
tooltip: {
valueSuffix: ' ms'
},
plotOptions: {
bar: {
dataLabels: {
enabled: true
}
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -40,
y: 100,
floating: true,
borderWidth: 1,
backgroundColor: '#FFFFFF',
shadow: true
},
credits: {
enabled: false
},
series: [{
name: 'Attempt 1',
//data: [635, 203, 200]
data : [array[0]] // I need to pass the variables here to get it displayed
}, {
name: 'Attempt 2',
//data: [133, 408, 698]
data : [array[1]]
}, {
name: 'Attempt 3',
//data: [973, 914, 4054]
data : [array[2]]
}]
});
});
You don't tell us what the variable array equals but since its generated from x.split(","), it's elements are going to be strings and not the numeric values Highcharts needs.
So convert it with parseInt or parseFloat:
var numericData = [];
for (var i = 0; i < array.length; i++){
numericData.push(parseFloat(array[i]));
}
...
series: [{
name: 'Attempt 1',
data : numericData
},
...
[array[0]] is not an array, that looks like console output not javascript. But [[0]] or [0] technically would be. However, since a call to array (array(0)) generates an array then I think you want data: array(0).
Outside shot at data : [array(0)] if you didn't show the example data correctly. I've never used HighCharts so I don't know what it's expected but I still go with data : array(0)