Related
I use Chart.js v4.2.1
<html>
<head>
<meta charset="utf-8" />
<title>Bar chart</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<div>
<canvas id="barchart"></canvas>
</div>
</body>
<script type="text/javascript">
var canvas = document.getElementById('barchart');
var chart = new Chart(canvas,
{
type: 'bar',
data:
{
labels: ["Audi", "VW", "KIA"],
datasets:
[
{
label: "Cars",
backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f"],
data: [2601, 4769, 602],
},
],
},
});
</script>
</html>
To get number of bars I execute chart.data.datasets[0].data.length and get 3.
To get the Y-value for the first bar I do chart.data.datasets[0].data[0] and get 2601.
How do I get the X-values (X-coordinates) for the bars?
(I am not interested in using any plugin).
Added:
Here is a sample where chart.scales.x is defined but chart.scales.y is not.
This happen when I add yAxisID which I need in my complete work.
<html>
<head>
<meta charset="utf-8" />
<title>Bar chart</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<div>
<canvas id="barchart"></canvas>
<div id="debug"></div>
</div>
<script type="text/javascript">
var canvas = document.getElementById('barchart');
var chart = new Chart(canvas,
{
type: 'bar',
data:
{
labels: ["Audi", "VW", "KIA"],
datasets:
[
{
label: "Cars",
backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f"],
data: [2601, 4769, 602],
yAxisID: "cars",
},
],
},
options:
{
scales:
{
cars:
{
position: "left",
ticks:
{
color: "red",
},
grid:
{
display: true,
},
},
},
},
});
var dataSets = chart.data.datasets;
var xPos = chart.scales.x.getPixelForValue(dataSets[0].data[0]);
try
{
var yPos = chart.scales.cars.getPixelForValue(dataSets[0].data[0]); // --> here y is undefined
document.getElementById("debug").innerHTML = "xPos=" + xPos + ", yPos=" + yPos;
}
catch(e)
{
document.getElementById("debug").innerHTML = "xPos=" + xPos + "<br>" + e;
}
</script>
</body>
</html>
You can use the following code: chartInstance.scales.x.getPixelForValue(chart instance.data.labels[labelIndex]
I have a c3 bar graphing categories. I'd like to format the category label to be able to truncate it to a certain length. But i can't figure it out.
Here is the graph definition:
var chart;
chart = c3.generate({
padding: {
top: 20,
bottom: 20
},
data: {
columns: [
["Listeners",4,2,0],
["Listens",4,2,0]],
type: 'bar',
groups:[["Listeners", "Listens"]]
},
axis: {
x: {
type: 'category',
categories: ["012345678890", "012345678890", "012345678890"],
}
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
},
legend: {
show: false
}
});
<link href="https://raw.githubusercontent.com/c3js/c3/0.4.11/c3.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://raw.githubusercontent.com/c3js/c3/0.4.11/c3.js"></script>
<div id="chart" class="c3" style="max-height: 280px; position: relative;"></div>
I tried adding this to format the tick inside the x axis definition, but it complains that chart is not defined
tick:{format:function (x) { return chart.categories()[x].substring(0, 10); }}
Thanks in advance!
Of course, you just declare the variable var chart; that has no value, is undefined.
Try to create the chart config before the function c3.generate() then pass the config as argument.
var config = {
padding : {
top : 20,
bottom : 20
},
data : {
columns : [ [ "Listeners", 4, 2, 0 ], [ "Listens", 4, 2, 0 ] ],
type : 'bar',
groups : [ [ "Listeners", "Listens" ] ]
},
axis : {
x : {
type: 'category',
categories: ["012345678890", "012345678890","012345678890"],
}
},
bar : {
width : {
ratio : 0.5
}
},
legend : {
show : false
}
};
config.axis.x.tick = {
format : function(x) {
return config.axis.x.categories[x].substring(0,10)
}
};
var chart = c3.generate(config);
In your code, you have named categories in the x-axis definition, I'm not sure why you wouldn't just change the labels?
** EXAMPLE **
var chart;
chart = c3.generate({
padding: {
top: 20,
bottom: 20
},
data: {
columns: [
["Listeners",4,2,0],
["Listens",4,2,0]],
type: 'bar',
groups:[["Listeners", "Listens"]]
},
axis: {
x: {
type: 'category',
_comment: "THIS IS WHERE YOU SET YOUR CATEGORY LABELS",
categories: ["Label1", "Label2", "Label3"],
}
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
},
legend: {
show: false
}
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.js"></script>
<div id="chart" class="c3" style="max-height: 280px; position: relative;"></div>
I'm trying to create a bar chart using C3 and D3 but I'm having trouble getting the columns to be unrelated to each other, other than for the fact that they use the same scale on the Y-axis.
I've included images to better explain.
var chart = c3.generate({
bindto: '#designerChart',
data: {
columns: [
['MA', 6],
['ME', 8],
['NY', 6],
['CN', 5],
['TX', 2]
],
type: 'bar',
},
axis: {
y: {
max: 10,
min: 0,
padding: { top: 0, bottom: 0 }
}
}
});
Results in a group of bars and when I hover over them I get the details for all the bars - not what I want.
I can change the data, so that it displays separate columns, but they are the same color and when I want to transition it to a pie chart you can't distinguish between the states.
var chart = c3.generate({
bindto: '#designerChart',
data: {
x: 'x',
columns: [
['x','MA', 'ME', 'NY', 'CN', 'TX'],
['rainfall', 6, 8, 6, 5, 4 ]
],
type: 'bar',
},
axis: {
x: {
type: 'category'
},
y: {
max: 10,
min: 0,
padding: { top: 0, bottom: 0 }
}
}
});
This is what I want:
Bar chart solution:
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.20/c3.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.20/c3.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>C3 Bar Chart</title>
</head>
<body>
<div id="designerChart"></div>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
columnColors = ['#9a4d6f', '#c76c47', '#f85115', '#d9b099', '#d4ba2f'];
function setColumnBarColors(colors, chartContainer) {
$('#' + chartContainer + ' .c3-chart-bars .c3-shape').each(function(index) {
this.style.cssText += 'fill: ' + colors[index] + ' !important; stroke: ' + colors[index] + '; !important';
});
$('#' + chartContainer + ' .c3-chart-texts .c3-text').each(function(index) {
this.style.cssText += 'fill: ' + colors[index] + ' !important;';
});
}
var chart = c3.generate({
bindto: '#designerChart',
data: {
columns: [
['rainfall', 6, 8, 6, 5, 4]
],
type: 'bar'
},
axis: {
x: {
label: {
text: 'States',
position: 'outer-center',
},
type: 'category',
categories: ['MA', 'ME', 'NY', 'CN', 'TX'],
tick: {
centered: true
}
},
y: {
label: {
text: 'Rainfall (inches)',
position: 'outer-middle'
},
max: 10,
min: 0,
padding: {
top: 0,
bottom: 0
}
}
},
legend: {
show: false
}
});
setColumnBarColors(columnColors, 'designerChart');
// Color turns to original when window is resized
// To handle that
$(window).resize(function() {
setColumnBarColors(columnColors, 'designerChart');
});
});
</script>
</body>
</html>
Colors turn to original in this fiddle (Full Page). But it changes colors as aspected on working local files , and local references of c3 , d3 ,and jquery.
References:
setColumnBarColors function:
jzcor...#gmail.com
https://groups.google.com/forum/
http://c3js.org/gettingstarted.html
http://c3js.org/samples/axes_x_tick_format.html
http://c3js.org/reference.html
I am facing an issue with exporting a column chart with scroll bar enabled which is not exporting a full chart after a scroll. It works for the first time, but when I scroll to the right or left and then when I export, the export is not happening completely.
Here is the sample.
var processedDataArray = [
{"Series_1_Value":1054237.31,"Series_2_Value":297367.88,"Series_3_Value":955472.31, "other":123450.45, "category":"CATEGORY-1"},
{"Series_1_Value":1914955.84,"Series_2_Value":472603.94,"Series_3_Value":1717425.84,"other":234560.45, "category":"CATEGORY-2"},
{"Series_1_Value":1172527.75,"Series_2_Value":368143.09,"Series_3_Value":1073762.75,"other":345670.45, "category":"CATEGORY-3"},
{"Series_1_Value":908568.43,"Series_2_Value":309490.05,"Series_3_Value":809803.43,"other":789010.45, "category":"CATEGORY-4"},
{"Series_1_Value":8001718.08,"Series_2_Value":5983055.85,"Series_3_Value":7112833.08,"other":890102.45, "category":"CATEGORY-5"},
{"Series_1_Value":1060572.17,"Series_2_Value":317503.11,"Series_3_Value":961807.17,"other":901230.45, "category":"CATEGORY-6"},
{"Series_1_Value":2484203.07,"Series_2_Value":1189924.57,"Series_3_Value":2187908.07,"other":435260.45, "category":"CATEGORY-7"},
{"Series_1_Value":6070895.44,"Series_2_Value":2722014.27,"Series_3_Value":5379540.44,"other":678900.45, "category":"CATEGORY-8"}
];
var series1DataArray = [];
var series2DataArray = [];
var series3DataArray = [];
var series4DataArray = [];
var categories = [];
var seriesNms = ['Series 1', 'Series 2', 'Series 3', 'Other'];
var _colors = ['#2F7ED8', '#915612', '#8BBC21', '#AA86F2', '#9054B6', '#76F0A3', '#A98835', '#09ACB6'];
for (i = 0; i < processedDataArray.length; i++) {
var dataObject = processedDataArray[i];
categories.push(dataObject['category']);
series1DataArray.push({
name: dataObject['category'],
y: parseInt(dataObject['Series_1_Value'])
});
series2DataArray.push({
name: dataObject['category'],
y: parseInt(dataObject['Series_2_Value'])
});
series3DataArray.push({
name: dataObject['category'],
y: parseInt(dataObject['Series_3_Value'])
});
series4DataArray.push({
name: dataObject['category'],
y: parseInt(dataObject['other'])
});
}
$(function() {
new Highcharts.Chart({
chart: {
type: 'column',
renderTo: 'colChart',
borderColor: '#000000',
borderWidth: 2,
plotBackgroundColor: 'rgba(255, 255, 255, .1)',
plotBorderColor: '#CCCCCC',
plotBorderWidth: 1,
zoomType: 'xy',
width: 960,
events: {
load: function() {
alert('Chart has loaded with exporting option ' + this.options.exporting.enabled + ", min:" + this.xAxis[0].min + ", max:" + this.xAxis[0].max + ", categories.length=" + categories.length);
}
}
},
scrollbar: {
enabled: true
},
colors: _colors,
exporting: {
enabled: true,
sourceWidth: 960,
sourceHeight: 400,
chartOptions: {
xAxis: [{
categories: categories,
max: categories.length - 1
}],
scrollbar: {
enabled: false
}
}
},
yAxis: {
title: {
text: 'Value($)'
}
},
xAxis: {
categories: categories,
max: categories.length > 5 ? 5 : categories.length - 1
},
plotOptions: {
series: {
pointPadding: 0.05,
groupPadding: 0.15
}
},
title: {
text: 'Column Chart',
align: 'center'
},
series: [{
name: seriesNms[0],
data: series1DataArray
}, {
name: seriesNms[1],
data: series2DataArray
}, {
name: seriesNms[2],
data: series3DataArray
}, {
name: seriesNms[3],
data: series4DataArray
}],
credits: {
enabled: false
}
}); //end of Chart const
}); //end of function...
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
<title>Highcharts</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="http://code.highcharts.com/stock/highstock.js"></script>
<script type="text/javascript" src="http://code.highcharts.com/highcharts.js"></script>
<script type="text/javascript" src="http://code.highcharts.com/modules/exporting.js"></script>
</head>
<body>
<div id="colChart"></div>
</body>
</html>
How to resolve the issue?. If you see the pop-up dialog it is not displaying the same "export enabled" boolean value.
Adding min and minRange to your exporting.chartOptions.xAxis seems to yield positive results. This does require max to still be there, and seemingly it gives varying results if any of those three are missing.
For example (updated JSFiddle):
exporting:{
enabled: true,
sourceWidth: 960,
sourceHeight: 400,
chartOptions: {
xAxis: [{
categories: categories,
min: 0, // Added for fix
minRange: categories.length-1, // Added for fix
max: categories.length-1
}],
scrollbar:{
enabled: false
}
}
}
Hopefully this resolves your issue. As to why, I do not know.
Is there a way to list let's say 2 charts on the same page where each chart has its data xml file? What I'm doing is generating xml files from rrdtool and I would like to view all charts for the same device on one page.
Here's the code I have that works for one chart:
test.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/data.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<script src="js/test.js" type="text/javascript"></script>
<script type="text/javascript">
$.ajax({
type: "GET",
url: "xml/test.xml",
dataType: "xml",
success: function(xml) {
var series = []
//define series
$(xml).find("entry").each(function() {
var seriesOptions = {
name: $(this).text(),
data: []
};
options.series.push(seriesOptions);
});
//populate with data
$(xml).find("row").each(function() {
var t = parseInt($(this).find("t").text()) * 1000
$(this).find("v").each(function(index) {
var v = parseFloat($(this).text())
v = v || null
if (v != null) {
options.series[index].data.push([t, v])
};
});
});
options.title.text = "CPU - Last 3 hours"
$.each(series, function(index) {
options.series.push(series[index]);
});
chart = new Highcharts.Chart(options);
}
})
</script>
</head>
<body>
<div id="cpu" style="width: 800px; height: 400px; margin: 0 auto; padding: 20px"></div>
</body>
</html>
test.js
Highcharts.setOptions({
global: {
useUTC: false
}
});
options = {
chart: {
renderTo: 'cpu',
type: 'area',
},
title: {
text: 'CPU'
},
subtitle: {
text: ''
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
hour: '%H. %M',
}
},
yAxis: {
title: {
text: 'Utilization %'
}
},
tooltip: {
formatter: function() {
return '<b>' + this.series.name + '</b><br/>' + Highcharts.dateFormat('%H:%M', this.x) + ': ' + Highcharts.numberFormat(this.y, 2) + ' %';
}
},
plotOptions: {
area: {
fillColor: {
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1},
stops: [
[0, Highcharts.getOptions().colors[1]],
[1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
]
},
lineWidth: 1,
marker: {
enabled: false
},
shadow: true,
states: {
hover: {
lineWidth: 1
}
},
threshold: null
}
},
series: []
}
And XML file - test.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xport>
<meta>
<start>1396030800</start>
<step>300</step>
<end>1396030800</end>
<rows>4</rows>
<columns>1</columns>
<legend>
<entry>cpu</entry>
</legend>
</meta>
<data>
<row><t>1396030800</t><v>2.8000000000e+01</v></row>
<row><t>1396031100</t><v>2.9780000000e+01</v></row>
<row><t>1396031400</t><v>3.1596666667e+01</v></row>
<row><t>1396041600</t><v>NaN</v></row>
</data>
</xport>
I encountered the same problem and just solved it!
Before the ready() function:
var chart;
var chart1;
$( document ).ready(function() {
your code....
I created two options, each options render to a different container
options = {
chart: {
renderTo: 'container',
type: 'area',
},
options2 = {
chart: {
renderTo: 'container2',
type: 'area',
},
and use the code below to add to different container:
chart = new Highcharts.Chart(options);
chart1 = new Highcharts.Chart(options2);
then in your html:
<div id="container">
<div id="container2">
Hope this brief explanation helps. Feel free to ask me if anything is not clear to you.
Cheers,