I want to change the origin of the c3 bar graph from zero to one.All the values must be drawn from one not from zero.For better understanding i have attached an image.
There is no config/easy way to change the origin from (0,0) to something different(0,100).
So the alternate/easy way to do this is by changing the axis tick labels and putting grid lines, and manipulating the data values, as shown below:-
In below example, I have tried to move the origin(x-axis from 0 to 100)
Hope this helps.
var chart = c3.generate({
bindto:'#chart_example',
data: {
columns: [
//['data1', 0, 200, -100, 400, 150, -250, 50, 100, 250] // Actual values
['data1', -100, 100, -200, 300, 50, -350, -50, 0, 150] // actual values -100
],
type: 'bar'
},
axis: {
x: {
type: 'category',
categories: ['cat1', 'cat2', 'cat3', 'cat4', 'cat5', 'cat6', 'cat7', 'cat8', 'cat9'],
show: false,
},
y : {
tick: {
//format: d3.format("$,")
format: function (d) { return "$" + (d+100); }
}
}
},
grid: {
y: {
lines: [
{value: 0, text: ''},
]
}
}
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.5/d3.min.js"></script>
<div id="chart_example"/>
Related
I am creating a some charts with billboard.js and stumbled upon some overflow logic i can't sort out.
Case: A simple linechart w/o labels on y-axis (these will be solved on a container level and not in the chart). I want the chart to have zero padding on x, to make it take upp the full width.
Issue: If the y-ticks are all 0, or something below 10 the x-ticks text will be cropped, thus not displaying it's full text on the first or last tick.
bb.generate({
bindto: "#chart",
grid: {
y: {
show: true
},
x: {
show: false
}
},
area: {
linearGradient: true
},
data: {
x: "x",
columns: [
[
"x",
"2022-10-23T07:31:00Z",
"2022-10-23T07:32:00Z",
"2022-10-23T07:33:00Z",
"2022-10-23T07:34:00Z",
"2022-10-23T07:35:00Z",
"2022-10-23T07:36:00Z",
"2022-10-23T07:37:00Z",
"2022-10-23T07:38:00Z",
"2022-10-23T07:39:00Z",
"2022-10-23T07:40:00Z",
"2022-10-23T07:41:00Z",
"2022-10-23T07:42:00Z",
"2022-10-23T07:43:00Z"
],
[
"yTicks",
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
]
],
types: {
yTicks: "area"
}
},
axis: {
x: {
tick: {
format: "%H:%M:%S",
fit: false
},
type: "timeseries",
padding: {
left: 0,
right: 0
}
},
y: {
padding: {
bottom: 0
},
tick: {
show: false,
}
},
line: {
zerobased: true
},
},
legend: {
show: false
},
});
Link to codepen
So is there a way to let the chart use all available width (padding 0 on x-tick) and display the full tick-text without setting y-label? Something like an overflow setting in plain css, but can't figure out a correct solution for svgs.
The first & last tick text can be hidden when the tick's position are set close to the edge. In this case, tick text can't be fully visible.
The easiest way to solve this, is giving some left/right padding.
Checkout the example.
bb.generate({
size: {
width:500
},
padding: {
left: 20,
right: 20
},
grid: {
y: {
show: true
},
x: {
show: false
}
},
area: {
linearGradient: true
},
data: {
x: "x",
columns: [
[
"x",
"2022-10-23T07:31:00Z",
"2022-10-23T07:32:00Z",
"2022-10-23T07:33:00Z",
"2022-10-23T07:34:00Z",
"2022-10-23T07:35:00Z",
"2022-10-23T07:36:00Z",
"2022-10-23T07:37:00Z",
"2022-10-23T07:38:00Z",
"2022-10-23T07:39:00Z",
"2022-10-23T07:40:00Z",
"2022-10-23T07:41:00Z",
"2022-10-23T07:42:00Z",
"2022-10-23T07:43:00Z"
],
[
"yTicks",
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
]
],
types: {
'yTicks': "area"
}
},
clipPath: false,
axis: {
x: {
clipPath: false,
tick: {
format: "%H:%M:%S",
fit: true,
//count:2,
values: [
// "2022-10-23T07:31:00Z",
"2022-10-23T07:32:00Z",
//"2022-10-23T07:33:00Z",
//"2022-10-23T07:34:00Z",
//"2022-10-23T07:35:00Z",
"2022-10-23T07:36:00Z",
//"2022-10-23T07:37:00Z",
//"2022-10-23T07:38:00Z",
//"2022-10-23T07:39:00Z",
"2022-10-23T07:40:00Z",
//"2022-10-23T07:41:00Z",
//"2022-10-23T07:42:00Z",
"2022-10-23T07:43:00Z"
],
},
type: "timeseries",
padding: {
left: 0,
right: 0
}
},
y: {
show: false
},
line: {
zerobased: true
},
},
legend: {
show: false
},
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/billboard.js/dist/theme/datalab.min.css">
<script src="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.js"></script>
</head>
<body>
<div id="chart"></div>
</body>
</html>
I have been trying to create overlays with Plotly.js, e.g. Week over Week, Month over Month etc., and I am required to render a similar looking chart as below. I believe the candleStick chart can get me somewhat near to it, but just wanted to explore if anyone has got a better idea.
Year Over Year, chart sample
The candleStick plots are a good option indeed, but they are somewhat limited in Plotly (see below). Another one is to use fill between two curves, something that'd look like this:
Here is the code to produce this:
<html>
<head>
<!-- Plotly.js -->
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<div class="item-graph" id="plotly_graph">
</div>
</body>
<script>
// Some random data
const date = ["2022/01/01", "2022/01/07", "2022/01/13", "2022/01/18", "2022/01/25", "2022/02/01", "2022/02/07", "2022/02/13", "2022/02/18", "2022/02/25"]
const new_date = date.map(function (d) { return new Date(d) })
const bluecurve = [450, 550, 460, 450, 530, 440, 340, 345, 290, 270]
const graycurve = [390, 410, 320, 490, 470, 380, 480, 410, 190, 310]
const min = [350, 430, 420, 410, 480, 350, 320, 310, 230, 190]
const max = [500, 600, 520, 490, 540, 500, 450, 390, 350, 360]
// Setting range of Forecast for hoverinfo
var hovertemplate = []
for (let i = 0; i < min.length; i++) {
hovertemplate.push(min[i] + ' - ' + max[i])
}
// Setting up the traces:
traces = [
{
x: new_date,
y: max,
// name: 'Forecast',
yaxis: 'y',
showlegend: false,
line: { width: 1, shape: 'hvh', color: "lightblue" },
hoverinfo: 'skip',
mode: 'lines',
},
{
x: new_date,
y: min,
name: 'Forecast',
yaxis: 'y',
showlegend: false,
line: { width: 1, shape: 'hvh', color: "lightblue" },
// hoverinfo: 'skip',
hovertemplate: hovertemplate,
mode: 'lines',
fillcolor: "lightblue",
fill: 'tonexty',
},
{
x: new_date,
y: bluecurve,
name: "This Year",
yaxis: 'y',
type: 'scatter',
showlegend: false,
mode: 'markers',
marker: {
size: 20,
color: "blue",
line: {
width: 2,
color: 'DarkSlateGrey'
},
},
},
{
x: new_date,
y: graycurve,
name: "Last Year",
yaxis: 'y',
type: 'scatter',
showlegend: false,
mode: 'markers',
marker: {
size: 20,
color: "lightgray",
line: {
width: 2,
color: 'DarkSlateGrey'
},
},
},
]
// Setting up layout
const layout = {
yaxis: {
rangemode: 'nonnegative',
range: [0, 700]
},
hovermode: "x unified",
};
// Creating the plots
Plotly.react("plotly_graph", traces, layout);
</script>
</html>
If you want to use candlesticks, you can change the layout and the first two elements on the traces to, respectively:
const layout= {
xaxis: {
type: 'date',
rangeslider: {
visible: false,
},
},
yaxis: {
rangemode: 'nonnegative',
range: [0,700]
},
hovermode: "x unified",
};
and
{
x: new_date,
low: min,
open: min,
high: max,
close: max,
decreasing: {line: {color: "lightblue" }},
increasing: {line: {color: "lightblue" }},
yaxis: 'y',
type: 'candlestick',
showlegend: false,
// text: hovertemplate,
hoverinfo: 'skip',
},
The hoverinfo of the candlesticks seem to always include high, low, open and close (I couldn't find a way to edit it, as text just adds to those, so I deactivated it). Here is how it looks like:
There's also no control over the width, apart from the number of sticks in the figure.
As you can see my bars are not covering the entire width of the label 'column'.
My tooltip only shows if I am exactly hovering the bar, or, if I remove the bars, exactly on the line point.
options: {
plugins: {
legend: { display: false },
title: { display: false },
tooltip: {
displayColors: false, backgroundColor: '#ffffff',
bodyColor: '#595f69', bodyFont: {size: 14},
borderColor: '#595f69', borderWidth: 1,
titleFont: {size: 0}
}
},
responsive: true, aspectRatio: 4,
scales: {
y: { display: true, suggestedMin: 0, suggestedMax: 80, ticks: { stepSize: 20 } },
y1: {display: false, suggestedMin: 0, suggestedMax: 80, ticks: { stepSize: 2 }},
x: { grid: { drawBorder: false, display: false } }
I tried plugins like chartjs crosshair, but don't manage to make it work with typescript.
How can I make it so that anywhere my mouse hover in the label 'column' area, the tooltip displays?
You can set the intersect property to false to always get the tooltip without needing to intersect the bar exactly:
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
}]
},
options: {
plugins: {
tooltip: {
intersect: false
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.js"></script>
</body>
You can make your own tooltip by editing the callbacks, i had to get the nearest values around my cursor, from all datasets, on my line chart. this works for me on Chartjs 2.9.3:
tooltips: {
mode: "x",
position: "nearest",
intersect: false,
callbacks: {
beforeBody: function(tooltipItems, allData) {
let x = tooltipItems[0].x; // get x coordinate
let datasets = allData.datasets; // datasets
let values = [];
for (i in datasets) {
let dataset = datasets[i];
let meta = this._chart.getDatasetMeta(i); // dataset metadata
let xScale = this._chart.scales[meta.xAxisID]; // dataset's x axis
let xValue = xScale.getValueForPixel(x); // we get the x value on the x axis with x coordinate
let data = dataset.data // data
// search data for the first value with a bigger x value
let index = data.findIndex(function(o) {
return o.x >= xValue;
});
let value = data[index]; // this is our nearest value
// format label
if (isNaN(value.ymax)) {
values.push(`${dataset.label}: ${value.y}\n`);
} else {
values.push(`${dataset.label}: ${value.y}, min: ${value.ymin}, max: ${value.ymax}\n`)
}
}
return values.join(""); // return label
},
label: function() { // this needs to be empty
},
}
},
I have figured out how to set the size for an annotation individually:
labels: [
{
point: {
x: chart.xAxis[0].max - 0.1,
y: 50,
xAxis: 0,
yAxis: 0
},
height: 100,
shape: "rect",
text: "test",
verticalAlign: "bottom"
}
]
I would like it to position between 50 and 150. How can I achieve that?
And additionally, I would like the text to be aligned in the center of the box?!
You can calculate the height by using toPixels method. You have to also take a padding into account. To center the text you can use asynchronous function, because annotations do not exist in load event yet.
chart: {
events: {
load: function() {
const chart = this;
const height =
chart.yAxis[0].toPixels(50) - chart.yAxis[0].toPixels(150);
chart.addAnnotation({
labels: [
{
point: {
x: chart.xAxis[0].max - 0.1,
y: 150,
xAxis: 0,
yAxis: 0
},
y: 0,
padding: 0,
height: height,
shape: "rect",
text: "test",
verticalAlign: "top"
}
]
});
}
}
}
Live demo: https://codesandbox.io/s/qqqkx2zr49
API: https://api.highcharts.com/class-reference/Highcharts.Axis#toPixels
I have generated a bar chart for the data to show ratings of five topics on scale of 5 (Ratings).On x-axis I showed Topic names.
$scope.options = {
chart: {
type: 'discreteBarChart',
height: 450,
margin: {
top: 20,
right: 20,
bottom: 50,
left: 55
},
x: function(d) {
return d.label;
},
y: function(d) {
return d.value;
},
showValues: true,
duration: 500,
xAxis: {
axisLabel: 'X Axis'
},
yAxis: {
axisLabel: 'Y Axis',
axisLabelDistance: -10
}
}
};
$scope.data = [{
values: $scope.Details.ratings
}];
HTML:
<nvd3 options="options" data="data"></nvd3>
On y-axis the max value should be 5, but here it is taking the maximum value among the data and the bars in the bar chart are having large width. How can I change the bar width and max range on y-axis?
i used the following code to set bar width and adjust the bar curvature
enter code here
dispatch: {
renderEnd: function (e) {
d3.selectAll("rect.nv-bar").attr('rx', 4).attr('ry', 4).attr('width', 15)
}
}
putting
groupSpacing : 0.57,
in chart dict will also help to adjust width dynamically