I am trying to create a graph with Apexcharts that looks like below. You can ignore the 2 vertical lines as they are not necessary.
Looking at the examples that apexcharts have, the closest thing I have found is Stacked Bar Charts. Maybe there is something better and I missed? If so please let me know.
https://apexcharts.com/javascript-chart-demos/bar-charts/stacked/
The way the chart below behaves is I get an array of data such as this:
[3, 7, 21, 55, 32, 3, 7, 58, 38] // and so on. You will notice the numbers can duplicate.
To simply things I will use Book and pages as a reference. The X axis represents number of pages and Y axis represents number of books. So by looking at the image I posted you can see there are 22 books that have 100 or less pages. There are 2 books with greater than 100 but less than 300 pages and 1 book with more than 300 and less than 400 pages.
I am having a real hard time figuring out how to configure the stacked bar chart to display things in this manner. I am not looking for an answer on how to manipulate my data, but more of how to configure the settings of the graph in order to get the correct display.
I have tried several configurations to no avail. Any help on this is most appreciated!
For reference to show work, some of things I have tried:
series: [{
name: 'Range 1',
data: [{ y: 44, x: 100 }, { y: 55, x: 100 }, { y: 41, x: 100 }, { y: 37, x: 100 }, { y: 22, x: 100 }, { y: 43, x: 100 }, { y: 21, x: 100 }]
}, {
name: 'Range 2',
data: [{ y: 44, x: 200 }, { y: 55, x: 200 }, { y: 41, x: 200 }, { y: 37, x: 200 }, { y: 22, x: 200 }, { y: 43, x: 200 }, { y: 21, x: 200 }]
}]
series: [{
name: 'Range 1',
data: [{ x: 44, y: 100 }, { x: 55, y: 100 }, { x: 41, y: 100 }, { x: 37, y: 100 }, { x: 22, y: 100 }, { x: 43, y: 100 }, { x: 21, y: 100 }]
}, {
name: 'Range 2',
data: [{ x: 44, y: 200 }, { x: 55, y: 200 }, { x: 41, y: 200 }, { x: 37, y: 200 }, { x: 22, y: 200 }, { x: 43, y: 200 }, { x: 21, y: 200 }]
}]
series: [{
name: 'Range 1',
data: [44, 55, 41, 37, 22, 43, 21]
}, {
name: 'Range 2',
data: [53, 32, 33, 52, 13, 43, 32]
}]
One of the largest issues I'm finding is that I can't seem to control values on the X axis or to keep the bars same width.
Here is an example of how it comes out from one of the attempts.
Lastly, the first image I showed above is generated from a Histogram from google charts. My requirements were to move all the google charts to apex charts so I'm trying to find something in apex charts equivalent to do the job.
There are two things that I do not really understand in your question: your data and why you want a stacked bar chart.
If you need to put the number of pages on your xaxis and the number of books on your yaxis, then a basic bar chart should be enough. I give you an example below:
let options = {
series: [{
name: 'Series',
data: [22, 2, 2, 1, 0, 0, 2, 0]
}],
chart: {
type: 'bar',
height: 350
},
dataLabels: {
enabled: false
},
xaxis: {
categories: [0, 100, 200, 300, 400, 500, 600, 700],
labels: {
offsetX: -13
},
title: {
text: 'Number of pages',
offsetY: 100
}
},
yaxis: {
title: {
text: 'Number of books'
}
},
tooltip: {
custom: ({series, seriesIndex, dataPointIndex, w}) => {
return `<div class="arrow_box"><div>Book(s): <strong>${series[seriesIndex][dataPointIndex]}</strong></div><div>Pages: <strong>${w.globals.labels[dataPointIndex]}-${w.globals.labels[dataPointIndex] + 100}</strong></div>`;
}
}
};
let chart = new ApexCharts(document.querySelector('#chart'), options);
chart.render();
.arrow_box {
padding: 10px;
}
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart"></div>
The trickiest part is the custom tooltip. I did this to put intervals in there instead of the category.
EDIT 1
Oops! I did not pay attention: my example above is not responsive (see labels). So maybe you could do something like that:
let options = {
series: [{
name: 'Series',
data: [22, 2, 2, 1, 0, 0, 2]
}],
chart: {
type: 'bar',
height: 350
},
dataLabels: {
enabled: false
},
xaxis: {
categories: ['0-100', '101-200', '201-300', '301-400', '401-500', '501-600', '601-700'],
title: {
text: 'Number of pages',
offsetY: 100
}
},
yaxis: {
title: {
text: 'Number of books'
}
},
responsive: [
{
breakpoint: 400,
options: {
xaxis: {
title: {
offsetY: 150
}
}
}
}
]
};
let chart = new ApexCharts(document.querySelector('#chart'), options);
chart.render();
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart"></div>
This is not very elegant but I did not find a better solution.
EDIT 2
After reading your comment, I updated my example:
let options = {
series: [{
name: 'Sci-fi',
data: [44, 55, 41, 37, 22, 43, 21]
}, {
name: 'Fantasy',
data: [53, 32, 33, 52, 13, 43, 32]
}],
chart: {
type: 'bar',
height: 350,
stacked: true
},
dataLabels: {
enabled: false
},
xaxis: {
categories: ['0-100', '101-200', '201-300', '301-400', '401-500', '501-600', '601-700'],
title: {
text: 'Number of pages'
}
},
yaxis: {
title: {
text: 'Number of books'
}
}
};
let chart = new ApexCharts(document.querySelector('#chart'), options);
chart.render();
<script src="https://cdn.jsdelivr.net/npm/apexcharts#3.36.0"></script>
<div id="chart"></div>
EDIT 3
Using the analogy above, each stacked bar would show title of the book. As they are all different books.
If you want to do that, I think you will have to create one series for each book and just set one color to avoid getting an unreadable rainbow. But if you have a lot of books, you will most likely face performance issues.
You will find a better example below. It is not consistent because I randomized all series, but it seems closer to what you are trying to do.
function getAllSeries() {
let allSeries = [];
for (let i = 1; i <= 7; i++) {
let series = {};
series.name = `Book ${i}`;
series.data = [];
for (let j = 0; j < 7; j++) {
if ((Math.random() * 10) < 5) {
series.data.push(1);
} else {
series.data.push(null);
}
}
allSeries.push(series);
}
return allSeries;
}
let options = {
series: getAllSeries(),
chart: {
type: 'bar',
height: 350,
stacked: true
},
dataLabels: {
enabled: false
},
xaxis: {
categories: ['0-100', '101-200', '201-300', '301-400', '401-500', '501-600', '601-700'],
title: {
text: 'Number of pages'
}
},
yaxis: {
title: {
text: 'Number of books'
}
},
legend: {
show: false
},
colors: ['#269ffb'],
stroke: {
colors: ['#ffffff'],
width: 1
},
tooltip: {
custom: ({series, seriesIndex, dataPointIndex, w}) => {
return `<div class="arrow_box"><div>Name: <strong>${w.config.series[seriesIndex].name}</strong></div><div>Pages: <strong>${w.globals.labels[dataPointIndex]}</strong></div>`;
}
}
};
let chart = new ApexCharts(document.querySelector('#chart'), options);
chart.render();
.arrow_box {
padding: 10px;
}
<script src="https://cdn.jsdelivr.net/npm/apexcharts#3.36.0"></script>
<div id="chart"></div>
Related
I've got a Gantt chart:
And I want to use the series.gantt.custom object to set specific properties for each series on the yAxis.
From these properties I want to construct the yAxis labels.
My code:
Highcharts.ganttChart('container', {
yAxis: {
categories: ['1', '2'],
labels: {
formatter() {
return this.value
/* + this.chart.series[this.pos].custom.size */
},
}
},
series: [{
groupPadding: 1,
custom: {
size: "small",
},
type: 'line',
zoneAxis: 'x',
data: [{
y: 0,
x: Date.UTC(2022, 10, 18),
custom: {
label: 1,
}
}, {
y: 0,
x: Date.UTC(2022, 10, 25, 12),
custom: {
label: 2
}
}]
}, {
type: 'line',
zoneAxis: 'x',
custom: {
size: "large",
},
data: [{
y: 1,
x: Date.UTC(2022, 10, 18),
custom: {
label: 1
}
}, {
y: 1,
x: Date.UTC(2022, 10, 25, 12),
custom: {
label: 2
}
}]
}]
});
this.chart.series[this.pos].custom.size it's the bit that is not working.
The labels should be 1 small and 2 large.
A fiddle
You can reach this property through the series.options:
this.chart.series[this.pos].options.custom.size
Demo:
https://jsfiddle.net/BlackLabel/gLkn9uqf/
(Highcharts version 6)
Is it possible to have a time line looking chart in addition to data points like in this example:
https://jsfiddle.net/s1eL30Lh/97/
<script src="https://code.highcharts.com/stock/highstock.js"></script>
but without using highstock and instead only use highcharts ?
I know it's possible to use xrange module but it's not quite the same:
https://jsfiddle.net/deep3015/q18yvy75/
If the ranges are long enough to simulate a line then you lack the ability to add "data points" on top of the line, and if you make the ranges small enough to look like data points then you don't have a line.
NOTE
I'm aware of the new chart type 'timeline' in version 7 but I need to work with version 6.1
Yes, it is possible. However, you can't use flags series because it is only supported by Highstock. Check the demo and code posted below.
Code:
function toMs(yeah, month) {
return Date.UTC(yeah, month, 1);
}
var series = [{
// First series
name: 'Running',
color: 'green',
id: 'green',
dataRaw: [{
y: 1,
xRanges: [
// first value: from; second value: to
[toMs(2000, 1), toMs(2002, 8)],
[toMs(2006, 10), toMs(2006, 11)]
]
}]
}, {
// Second series
name: 'Filed',
color: 'yellow',
id: 'yellow',
dataRaw: [{
y: 1,
xRanges: [
// first value: from; second value: to
[toMs(2002, 8), toMs(2006, 10)]
]
}]
},
{
// Second series
name: 'Granted',
color: 'blue',
id: 'blue',
dataRaw: [{
y: 1,
xRanges: [
// first value: from; second value: to
[toMs(2006, 11), toMs(2021, 8)]
]
}]
}
].map(function(series) {
series.data = [];
series.dataRaw.forEach(function(dataRaw) {
dataRaw.xRanges.forEach(function(xRange) {
series.data.push([xRange[0], dataRaw.y], [xRange[1], dataRaw.y], [xRange[1], null]); // null breakes the line
}); // forEach
}); // forEach
return series;
});
console.log(series);
var chart = Highcharts.chart('container', {
chart: {
type: 'scatter'
},
title: {
text: 'Example'
},
plotOptions: {
scatter: {
lineWidth: 5,
marker: {
enabled: true,
symbol: 'circle',
fillColor: '#FFFFFF',
lineWidth: 2,
lineColor: null,
radius: 5
},
dataLabels: {
enabled: true,
align: 'right',
rotation: -30,
x: -2,
y: 15,
formatter: function() {
return Highcharts.dateFormat('%Y-%m', this.x);
}
},
tooltip: {
pointFormatter: function() {
return Highcharts.dateFormat('%Y-%m', this.x);
}
}
},
flags: {
lineWidth: 1
}
},
xAxis: {
title: {
text: 'Time'
},
type: 'datetime',
minTickInterval: 365 * 24 * 36e5,
labels: {
align: 'left'
},
plotBands: [{
from: Date.UTC(2000, 10, 27),
to: Date.UTC(2004, 11, 1),
color: '#EFFFFF',
label: {
text: 'Office 1',
style: {
color: '#999999'
},
y: 30
}
}, {
from: Date.UTC(2004, 11, 1),
to: Date.UTC(2012, 9, 1),
color: '#FFFFEF',
label: {
text: 'Office 2',
style: {
color: '#999999'
},
y: 30
}
}, {
from: Date.UTC(2012, 9, 1),
to: Date.UTC(2020, 10, 27),
color: '#FFEFFF',
label: {
text: 'Office 3',
style: {
color: '#999999'
},
y: 30
}
}]
},
yAxis: {
tickInterval: 1
},
series: series,
annotations: [{
labelOptions: {
backgroundColor: 'rgba(255,255,255,0.5)'
},
labels: [{
distance: 10,
point: {
xAxis: 0,
yAxis: 0,
x: toMs(2002, 8),
y: 1
},
text: 'Filled Date'
}]
}]
});
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/6.1/highcharts.js"></script>
<script src="https://code.highcharts.com/6.1/modules/annotations.js"></script>
<div id="container" style="height: 400px"></div>
Demo:
https://jsfiddle.net/BlackLabel/6eahoxjv/
I'm using chartjs lib to draw charts.
And I want to draw some simple, linear chart, but when do it some how the first point of the chart isn't shown correctly :
https://scr.hu/ALkPXP
It happends when the lowest data point x value have the same value as the minimum xAxes.
When I decrease minimum ax value it works correcty:
https://scr.hu/Gw4Lpy
My whole chart looks like :
const scatterChart2 = new Chart(this.canvas.nativeElement,
{
'type': 'line',
'data':
{
'datasets': [
{
'label': 'Scatter Dataset',
'data': [
{
x: 1,
y: 0,
}, {
x: 65,
y: 20,
}, {
x: 30,
y: 22,
}, {
x: 44,
y: 55,
}],
'fill': false,
'borderColor': 'rgb(75, 192, 192)'
}]
},
'options': {
scales: {
xAxes: [{
ticks: {
min: 1,
stepSize: 1
},
offset: true,
type: 'linear',
position: 'bottom'
}]
},
'showLines': true
}
});
}
And in HTML my Canvas looks like :
<div style="max-width: 1000px;max-height: 1000px;">
<canvas #canvas id="myChart" ></canvas>
</div>
How should I show first point correctly ?
I am very new to data visulizations.
Currently we are having a requirement to draw a chart similar to below using HighChart.js
See jsfiddle: http://jsfiddle.net/rgpz2ru5/22/ for what I tried so far.
I am successfully able to draw chart but facing issue while drawing lines between the datalabel and point (just shown in above image)?
Can you please help?
See below code to draw a chart:
$('#container').highcharts({
chart: {
type: 'scatter',
},
xAxis: {
visible: false
},
yAxis: {
title: {
text: ''
},
labels: {
formatter: function() {
return null
}
}
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
inside: false,
formatter: function(){
console.log("X"+this.x)
console.log("this.x%2"+this.x%2)
if(this.x%2 == 0){
console.log("in if")
return "<div style='position: relative;height:70px; border-left:solid thin #ff0000;margin-left:10px'><span style='position: absolute;bottom: 0;right: 0;'>hello</span></div>";
}else{
console.log("in else")
return "<span style='color:black'>"+this.key+"</span><div style='height:70px; border-left:solid thin #ff0000;margin-left:10px'/>";
}
},
useHTML:true
}
},scatter: {
marker: {
radius: 5,
states: {
hover: {
enabled: false,
lineColor: "#ffb74d"
}
}
},
states: {
hover: {
marker: {
enabled: false
}
}
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: '{point.x} cm, {point.y} kg'
}
}
},
series: [{
data: [{
x: 1,
y: 1,
dataLabels: {
y: -80
},
marker: {
radius: 3
},
name: 'SDS',
color: "#ffb74d"
}, {
x: 2,
y: 1,
dataLabels: {
y: 80
},
marker: {
radius: 5
},
name: 'MIP',
color:"#ffe0b2"
}, {
x: 3,
y: 1,
dataLabels: {
y: -80,
distance : 50,
softConnector : false,
connectorColor : '#D0D0D0',
},
marker: {
radius: 7
},
name: 'MDP',
color:"#ff9800"
},{
x: 4,
y: 1,
dataLabels: {
y: 80
},
marker: {
radius: 9
},
name: 'RAD',
color:"#ffb74d"
},{
x: 5,
y: 1,
dataLabels: {
y: -80
},
marker: {
radius: 3
},
name: 'SDS',
color: "#ffb74d"
}, {
x: 6,
y: 1,
dataLabels: {
y: 80
},
marker: {
radius: 5
},
name: 'MIP',
color:"#ffe0b2"
}, {
x: 7,
y: 1,
dataLabels: {
y: -80
},
marker: {
radius: 7
},
name: 'MDP',
color:"#ff9800"
},{
x: 8,
y: 1,
dataLabels: {
y: 80
},
marker: {
radius: 9
},
name: 'RAD',
color:"#ffb74d"
},{
x: 9,
y: 1,
dataLabels: {
y: -80
},
marker: {
radius: 3
},
name: 'SDS',
color: "#ffb74d"
}, {
x: 10,
y: 1,
dataLabels: {
y: 80
},
marker: {
radius: 5
},
name: 'MIP',
color:"#ffe0b2"
}, {
x: 11,
y: 1,
dataLabels: {
y: -80
},
marker: {
radius: 7
},
name: 'MDP',
color:"#ff9800"
},{
x: 12,
y: 1,
dataLabels: {
y: 80
},
marker: {
radius: 9
},
name: 'RAD',
color:"#ffb74d"
}]
}]
});
Can you please help?
Your chart seems to be of a specific kind. I personally have not seen any such visualizations before. Also, having worked with HighCharts, I doubt if any type of highchart can be transformed as yours.
However, on the first look on your figure the following idea appeared in my mind with angular framework.
You can achieve this kind of visualization using basic html and css.
Assuming you are aware with Angular terminology. I suggest having a list of all your values. Loop them in a simple div as follows:
<div ng-repeat = "c in pointsList" > </div>
Next you can use ng-style or ng-class to add dynamic css to your each div.
Seeing your figure, I assume you only following css properties:
1. border-radius
2. background-color
3. width
4. height
Seems like you have fixed categories for each type of bubbles. So you can make few fixed classes in your css and apply them dynamically on the basis of your type of point. Basically, it would look like:
<div ng-repeat = "c in pointsList" ng-class = "{'css1' : c.type1, 'css2' : c.type2}" > </div>
Along with this you will need to apply display: inline-block to bring all divs in a line.
I know, its too naive solution, but if you have limited requirements of such chart, this can help you achieve it with minimal adjustments.
To make similar chart you can use bubble chart: http://jsfiddle.net/rgpz2ru5/
Or standard scatter chart: http://jsfiddle.net/rgpz2ru5/1/
You can change marker size of scatter using marker.radius parameter:
marker: {
radius: 5,
states: {
hover: {
lineColor: "#ffb74d"
}
}
},
You can add your labels using chart.renderer.path and chart.renderer.label:
http://api.highcharts.com/highcharts/Renderer.path
http://api.highcharts.com/highcharts/Renderer.label
var drawLabels = function(chart) {
$('.cLabels').remove();
var series = chart.series,
renderer = chart.renderer,
plotTop = chart.plotTop,
plotLeft = chart.plotLeft;
Highcharts.each(series, function(s) {
Highcharts.each(s.data, function(p) {
renderer.path(['M', p.plotX + plotLeft, p.plotY + plotTop, 'L', p.plotX + plotLeft, p.plotY + plotTop - 30]).attr({
stroke: 'black',
'stroke-width': 1
}).addClass('cLabels').add();
renderer.label(p.name, p.plotX + plotLeft, p.plotY + plotTop - 50).attr({
'text-anchor': 'middle',
padding: 0
}).addClass('cLabels').add();
});
});
}
Here you can see an example how it can work: http://jsfiddle.net/rgpz2ru5/29/
i have the base line highchart with the trend line and points ..now i want to add Range for the xaxis in the Single line series highstock ...
This is Jsfiddle please observe :
http://jsfiddle.net/hj22wbe5/7/
And this is the Highstock :
http://www.highcharts.com/stock/demo
or
http://jsfiddle.net/gh/get/jquery/1.9.1/highslide-software/highcharts.com/tree/master/samples/stock/demo/basic-line/
How to add the Navigator for first jsfiddle graph that is having the in the highstock ..
please help
Thanks !!
Edited code :
<!DOCTYPE html>
<html lang="en">
<title>RNA</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv='X-UA-Compatible' content='IE=Edge'/>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://code.highcharts.com/stock/highstock.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<body>
<div id="container" style="height: 400px"></div>
</body>
<script type="text/javscript">
$(function () {
var sourceData = [
[0, 99.43],
[1, 99.40],
[2, 99.24],
[3, 99.40],
[4, 99.21],
[5, 99.45],
[6, 99.41],
[7, 99.18],
[8, 99.36],
[9, 99.31],
[10, 99.38],
[11, 99.20],
[12, 99.38],
[13, 99.32]
];
var dates = ['18-Jul-14', '19-Jul-14', '20-Jul-14', '18-Jul-14', '19-Jul-14', '20-Jul-14', '18-Jul-14', '19-Jul-14', '20-Jul-14', '18-Jul-14', '19-Jul-14', '20-Jul-14', '19-Jul-14', '20-Jul-14', '20-Jul-14'];
$('#container').highcharts({
title: {
text: 'RNA - CP ( Radio Network Availability - Customer Perceived)',
x: -20 //center
},
tooltip: {
formatter: function () {
if (this.series.name == 'Series 2') {
return false;
}
//console.log(this.point.extprop);
var s = 'The value for <b>' + this.x +
'</b> is <b>' + this.y + '</b>';
if (this.point.extprop) {
s += 'for <b>' + this.point.extprop + '</b>';
}
return s;
}
},
subtitle: {
text: '',
x: -20
},
navigator: {
enabled: true
},
xAxis: {
labels: {
rotation: 90,
align: "left",
formatter: function () {
return dates[this.value];
},
},
tickInterval: 1
},
yAxis: {
title: {
text: 'Percent'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
legend: {
layout: 'vertical',
//align: 'right',
//verticalAlign: 'middle',
borderWidth: 0
},
series: [{
name: 'RNA',
data: [{
x: 0,
y: 99.43,
extprop: 'power issue'
}, {
x: 1,
y: 99.40,
extprop: 'flood'
}, {
x: 2,
y: 99.24,
color: 'red',
extprop: 'power issue'
}, {
x: 3,
y: 99.40,
extprop: 'flood'
}, {
x: 4,
y: 99.21,
color: 'red',
extprop: 'power issue'
}, {
x: 5,
y: 98.45,
color: 'red',
extprop: 'flood'
}, {
x: 6,
y: 98.41,
color: 'red',
extprop: 'power issue'
}, {
x: 7,
y: 99.18,
color: 'red',
extprop: 'flood'
}, {
x: 8,
y: 99.36,
extprop: 'power issue'
}, {
x: 9,
y: 99.31,
color: 'red',
extprop: 'flood'
}, {
x: 10,
y: 99.38,
extprop: 'power issue'
}, {
x: 11,
y: 99.20,
color: 'red',
extprop: 'flood'
}, {
x: 12,
y: 99.38,
extprop: 'power issue'
}, {
x: 13,
y: 99.32,
extprop: 'flood'
}]
}, {
type: 'line',
marker: {
enabled: false
},
/* function returns data for trend-line */
data: (function () {
return fitData(sourceData).data;
})()
}],
credits: {
enabled: false
}
});
});
</script>
</html>
yes , this is script and one issue when i load in the browser the graph is not displaying and also when i inspect element no errors are there ..i cant able to find the issue ..in the browser its showing empty page..#pawel .
Thanks