JavaScript, Plotly: How to customise axis labels on bar plot? - javascript

I am plotting a bar chart with date values on the x-axis. Simply setting the values for bins and bar heights gives the desired plot, but the axis labels (date values) are positioned below centres of the bars (see the screenshot).
However each bar represents date range and I would like the labels to be located below the edges of the bars. How do I do that?

You could convert your plot to a scatter line plot and fill it to the x-axis. The labels appearing on the x-axis can be specified via layout: xaxis: tickvals.
If you want equally size bars, set layout: xaxis: type to category.
var data = {
x: ['2013-11-02', '2013-11-04', '2013-11-05', '2013-11-07', '2013-11-09', '2013-11-11', '2013-11-13'],
y: [1, 3, 6, 4, 5, 2, 6],
};
var trace = {
x: [],
y: [],
type: 'scatter',
mode: 'lines',
fill: 'tozeroy'
};
for (var i = 0; i < data.x.length - 1; i += 1) {
trace.x.push(data.x[i]);
trace.y.push(0);
trace.x.push(data.x[i]);
trace.y.push(data.y[i]);
trace.x.push(data.x[i + 1]);
trace.y.push(data.y[i]);
}
trace.x.push(data.x[data.x.length - 1]);
trace.y.push(0);
var layout = {
xaxis: {
type: 'category',
tickvals: data.x,
tickangle: -45
}
}
Plotly.newPlot('myDiv', [trace], layout);
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv"></div>

Related

Highcharts - overlapping values with the x-Axis

I am trying to create a line graph, wherein if all the values for the particular series is zero then, I want the line to be drawn on the bottom over the x-axis line. But it seems like the line of the x-axis takes the preference than the series line. Is there any way to change that?
Below is my configuration:
xAxis: {
type: "datetime",
tickmarkPlacement: "on",
lineWidth: 10,
lineColor: 'red',
},
yAxis: {
min: 0,
minRange : 0.1,
title: {
text: ""
}
},
plotOptions: {
line: {
softThreshold: false
}
},
Example:
http://jsfiddle.net/shivajyothibalavikas/twxs7mL2/3
In the above example the axis line color is red and series line color is black. but red takes the preference. I want the black line to take the preference while displaying
It is not possible to move a series line above an axis line by options in Highcharts API. As a solution, you can use the Highcharts.SVGRenderer class and draw a custom line at the chart bottom.
chart: {
...,
events: {
render: function() {
const chart = this;
const x1 = chart.plotLeft;
const x2 = x1 + chart.plotWidth;
const y = chart.plotTop + chart.plotHeight;
if (!chart.customLine) {
chart.customLine = chart.renderer
.path().attr({
stroke: 'red',
'stroke-width': 10
}).add();
}
chart.customLine.attr({
d: ['M', x1, y, 'L', x2, y]
});
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/70d6sg2o/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer

Putting the Z-Coordinate in the Highcharts Tooltip

I have three graphs. All three graphs have the same x axis values (category), different y-values, and the same z-value (date). The graphs have synced tooltips when you hover over a point. I want to be able to populate the tooltip with the z-coordinate for each point. I do not want to plot the z coordinate... just have it show in the tooltip. I am not sure how to do this because there are more multiple graphs with synced tooltips.
I made a basic example to show how to put the z-value (date) in a tooltip for one graph. https://codepen.io/austeng/pen/ZEGxWyK
Highcharts.chart('container', {
tooltip: {
formatter: function() {
return 'x: ' + this.x + ', y: ' + this.y + ', z: ' + Highcharts.dateFormat('%b/%e/%Y',
new Date(this.point.z));
}
},
xAxis:{
type: 'category'
},
series: [{
data: [{
x: 0,
y: 0,
z: 1564358400000
},
{
x: 1,
y: 5,
z: 1564531200000
},
{
x: 2,
y: 2,
z: 1564963200000
}
]
}]
});
This is my codepen for the three graphs: https://codepen.io/austeng/pen/gOppRWY
Any help on how to extend my example for one graph to my current code of three graphs w/sync tooltip would be very appreciated. Thanks.
I think that it will be better to achieve it in a different way.
Create some global function, let's say setTooltip which will take a point as a parameter.
For each chart config set the tooltip.pointFormatter callback which returns above function.
tooltip: {
pointFormatter() {
let point = this;
return setTooltip(point)
}
},
Use the keys feature to get the z value in the point object.
API: https://api.highcharts.com/highcharts/series.line.keys
Final output: https://jsfiddle.net/BlackLabel/sjv18rbn/

How to make mathematical chart with HighCharts?

Hi there, I'm doing a web project which aims to replace a back-end chart renderer with front-end chart renderer. The front-end charting library I'm using is HighCharts. The 1st image shows what the chart supposed to look, and the 2nd is the chart rendered by HighCharts based on same data. As you can see, at point 3 & 4 (count from right to left), since their values are equal, the line between them are considered horizontal, which is different in image 1 as desired.
Is there anyway we can use HighCharts to achieve the first image - like chart? Cheers.
In general, when two points have the same value, then line will be rendered as straight one. You can change that by wrapping getPointSpline. Here is simple POC:
(function(H) {
H.wrap(H.seriesTypes.spline.prototype, 'getPointSpline', function(p, points, point, i) {
var path = p.call(this, points, point, i),
offset = -10;
if (points[i - 1] && points[i - 1].y === point.y) {
path[2] += offset;
path[4] += offset;
}
return path;
});
})(Highcharts)
And working demo: http://jsfiddle.net/99w72efv/8/
Highcharts splice type series doesn't provide the kind of line approximation you are looking for. You could add more data points (that might be hidden) to get the shape that you are looking for.
Example: http://jsfiddle.net/99w72efv/9/
$(function() {
$('#container').highcharts({
chart: {
type: 'spline'
},
yAxis: {max: 3},
series: [{
data: [2, 1, 0, 1, 3, 1, 2, 3, 0, 1, 2, 3, {x: 11.5, y: 3.2, marker: {enabled:false}}, 3, 1, 2, {x: 14.5, y: 2.2, marker: {enabled:false}}, 2, 0, 1]
}]
});
});

How to add 2nd horizontal x axis scale to jqplot and customize axis settings?

Note: Although this is a self-answered question, I am always curious about better approaches.
sin(x) and cos(x) for x in degrees.
Goal: I would like to adjust this initial plot and add a 2nd X axis to show both degrees and radians.
How do I set up jqPlot PlotOptions to add x and y labels, change scales, and add a second X axis?
I am using a JavaScript library that I wrote called html5csv [License: GPL] that support various data analysis operations and interfaces to jqPlot for plotting. It allows the specification of the jqPlot plotOptions object for each plot.
The (currently blank) plotOptions are on the first line of code. You may assume the plotOptions are correctly delivered to jqPlot by the subsequent code invoking CSV().jqplot() from the html5csv library.
html5csv + jqplot dual line graph without special axes
plotOptions = {};
CSV.begin('%F', {dim:[36,4],header:['deg','rad','sin','cos'],
func: function(i,j){
var deg = 10*(i);
var rad = deg*2*Math.PI/360.0;
if (j===0) return deg;
if (j===1) return rad;
if (j===2) return Math.sin(rad);
if (j===3) return Math.cos(rad);
}
}).
jqplot([['chart1',[['deg','sin'],['deg','cos']], plotOptions]]).
table('tab1',{header:1}).
go();
jsfiddle of single axes sine, cosine wave plot
This jqPlot documentation shows up to 2 X axes and 9 Y axes but when calling new Axis() I get Uncaught ReferenceError: Axis is not defined in the console. To fix this I tried adding more of the jqplot .js files to the script headers but it did not help.
jqplot Axis formatting options documentation shows all the options to configure axis labels, ticks, etc. for a particular axis if I could create one.
How do I proceed from here?
Don't call new Axis(); This is done for you internally in jqPlot.
Basically, if you declare the right keys in plotOptions, the Axis will be set up for you. But if the keys are missing or misnamed, it will obviously fail.
Here are the finished examples:
Part 1: Customized set of single axes
Output
jqplot PlotOptions Input
plotOptions = {
axes: {
xaxis: {
show: true,
label: 'deg',
min: 0,
max: 360,
tickInterval: 45
},
yaxis: {
show: true,
label: 'y',
min: -2.0,
max: 2.0
}
}
};
Note: You don't need to call new Axis, but you do need to name the object fields as shown.
plotOptions = {
axes: {
xaxis: {
show: true,
label: 'deg',
min: 0,
max: 360,
tickInterval: 45
},
yaxis: {
show: true,
label: 'y',
min: -2.0,
max: 2.0
}
}
};
CSV.begin('%F', {
dim: [36, 4],
header: ['deg', 'rad', 'sin', 'cos'],
func: function(i, j) {
var deg = 10 * (i);
var rad = deg * 2 * Math.PI / 360.0;
if (j === 0) return deg;
if (j === 1) return rad;
if (j === 2) return Math.sin(rad);
if (j === 3) return Math.cos(rad);
}
}).
jqplot([
['chart1', [
['deg', 'sin'],
['deg', 'cos']
], plotOptions]
]).
table('tab1', {
header: 1
}).
go();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/jquery.jqplot.css" />
<script src="https://cdn.rawgit.com/DrPaulBrewer/html5csv/7f39da16/html5csv.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/jquery.jqplot.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/plugins/jqplot.canvasAxisLabelRenderer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/plugins/jqplot.canvasAxisTickRenderer.js"></script>
Part 2: Dual X axes, with degrees and radians scales
Output
jqPlot PlotOptions Input
plotOptions = {
axes: {
xaxis: {
show: true,
label: 'deg',
min: 0,
max: 360,
tickInterval: 45
},
x2axis: {
show: true,
label: 'rad',
min: 0,
max: 2 * Math.PI,
numberTicks: 9
},
yaxis: {
show: true,
label: 'y',
min: -2.0,
max: 2.0
}
}
};
plotOptions = {
axes: {
xaxis: {
show: true,
label: 'deg',
min: 0,
max: 360,
tickInterval: 45
},
x2axis: {
show: true,
label: 'rad',
min: 0,
max: 2 * Math.PI,
numberTicks: 9
},
yaxis: {
show: true,
label: 'y',
min: -2.0,
max: 2.0
}
}
};
CSV.begin('%F', {
dim: [36, 4],
header: ['deg', 'rad', 'sin', 'cos'],
func: function(i, j) {
var deg = 10 * (i);
var rad = deg * 2 * Math.PI / 360.0;
if (j === 0) return deg;
if (j === 1) return rad;
if (j === 2) return Math.sin(rad);
if (j === 3) return Math.cos(rad);
}
}).
jqplot([
['chart1', [
['deg', 'sin'],
['deg', 'cos']
], plotOptions]
]).
table('tab1', {
header: 1
}).
go();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/jquery.jqplot.css" />
<script src="https://cdn.rawgit.com/DrPaulBrewer/html5csv/7f39da16/html5csv.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/jquery.jqplot.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/plugins/jqplot.canvasAxisLabelRenderer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/plugins/jqplot.canvasAxisTickRenderer.js"></script>
Notes: No need to call new Axis() here, either. Name the plotOptions keys properly and it works.
Plotting of data used the original single X coordinate using the 1st X axis.
Reference
From the jqPlot Axis docs:
Axes options are specified within an axes object at the top level of the plot options like so:
{
axes: {
xaxis: {min: 5},
yaxis: {min: 2, max: 8, numberTicks:4},
x2axis: {pad: 1.5},
y2axis: {ticks:[22, 44, 66, 88]}
}
}
There are 2 x axes, ‘xaxis’ and ‘x2axis’, and 9 yaxes, ‘yaxis’, ‘y2axis’. ‘y3axis’, ... Any or all of which may be specified.
Useful axis options excerpted from the documentation
Note: Additional options do exist. These are the most basic ones.
In a few of these I edited slightly for clarity.
show
true to display the axis on the graph.
label
Label for the axis
showLabel
true to show the axis label.
min
minimum value of the axis (in data units, not pixels).
max
maximum value of the axis (in data units, not pixels).
autoscale
true to Autoscale the axis min and max values to provide sensible tick spacing.
If axis min or max are set, autoscale will be turned off. The numberTicks, tickInterval and pad options do work with autoscale, although tickInterval has not been tested yet. padMin and padMax do nothing when autoscale is on.
ticks
1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis. If no label is specified, the value is formatted into an appropriate label.
numberTicks
Desired number of ticks. Default is to compute automatically.
tickInterval
number of units between ticks. Mutually exclusive with numberTicks.
showTicks
true to show the ticks (both marks and labels) or not. Will not override showMark and showLabel options if specified on the ticks themselves.
showTickMarks
true to show the tick marks (line crossing grid) or not. Overridden by showTicks and showMark option of tick itself.
syncTicks
true to try and synchronize tick spacing across multiple axes so that ticks and grid lines line up. This has an impact on autoscaling algorithm, however. In general, autoscaling an individual axis will work better if it does not have to sync ticks.
tickSpacing
A number giving approximate pixel spacing between ticks on graph. Used during autoscaling. This number will be an upper bound, actual spacing will be less.

NVD3 chart: Plot toggle with muiltiChart / multiple yScales causes axis to disappear, but not the plot

I'm trying to get two lines to use two different scales.
When I try to toggle a plot, the grid lines disappear, instead of the plot.
Can you figure out what I'm doing wrong?
http://jsfiddle.net/3ZP3S/
var dataset1 = {
values : [],
key : "Math.cos",
type: "line",
color: '#2ca02c',
yAxis: 1
};
var dataset2 = {
values : [],
key : "sin",
type: "line",
color : "#ff7f0e",
yAxis: 2
};
for (var i = -3.14; i < 3.1415; i+= .01){
dataset1.values.push( { x: i , y : Math.cos(i) });
dataset2.values.push( { x: i , y : Math.sin(i) * 3 });
}
var data = [dataset1, dataset2];
nv.addGraph( function() {
var chart = nv.models.multiChart()
.margin({top: 30, right: 60, bottom: 50, left: 70})
.color(d3.scale.category10().range());
chart.xAxis
.tickFormat(d3.format(',.2f'));
chart.yAxis1
.tickFormat(d3.format(',.1f'));
chart.yAxis2
.tickFormat(d3.format(',.1f'));
d3.select('#chart svg')
.datum(data)
.transition().duration(500).call(chart);
return chart;
});
This was a bug with nvd3. I tried several "previous" versions of nvd3, and d3, and this always occurred.
We also decided to drop nvd3 and switch to C3.js, which seems to be "much" more mature in terms of stability...

Categories

Resources