Iam using Plotly.js https://plotly.com/javascript/. I am trying to develop a chart where I want to add a small image on each ticks on the y axis. For reference please see the image given below.
Notice the small gray discs on y axis (next to the texts "Red", "Green" and "Blue"). I am trying to achieve something like this. However on the reference document, I couldn't find anything that does this.
How can I achieve that?
[UPDATE]
After implementing the answer as suggested by #Ruben, and further making some updates, I get this little tip of the x-axis extended to the left to the negative side (ref. the screenshot of this extended tip below)
If it's really only about the dots, I've hacked together something that inserts this unicode shape as a solid, black circle at every bar using annotations. Then you can colour it if you want.
var data = [{
type: 'bar',
x: [20, 14, 23],
y: ['giraffes', 'orangutans', 'monkeys'],
orientation: 'h'
}];
var layout = {
annotations: data[0].y.map((v, i) => ({
x: -0.75,
y: i,
xref: 'x',
yref: 'y',
text: "⬤",
showarrow: false,
font: {
size: 14,
color: ['red', 'blue', 'green'][i % 3]
}
}))
};
Plotly.newPlot('myDiv', data, layout);
<script src='https://cdn.plot.ly/plotly-latest.js'></script>
<div id='myDiv'></div>
Edit: now using changed labels:
var data = [{
type: 'bar',
x: [20, 14, 23],
y: ['giraffes', 'orangutans', 'monkeys'],
orientation: 'h'
}];
data[0].y = data[0].y.map((v, i) => {
const color = ['red', 'blue', 'green'][i % 3];
return `${v} <span style="color: ${color};">⬤</span>`
})
var layout = {
xaxis: {
showline: true,
},
margin: {
l: 100,
}
};
Plotly.newPlot('myDiv', data, layout);
<script src='https://cdn.plot.ly/plotly-latest.js'></script>
<div id='myDiv'></div>
Related
I'm having hard time adding the dial/needle to the gauge chart from plotly.js.
gauge without needle
: As you could see in the image above it's gauge chart without any needle.
gauge with needle
: I want to build something similar to "gauge with needle", which is giving me hard time.
my code for "gauge without needle/dial" :
`https://codepen.io/vivek137/pen/rNyembX`
You will need to add an arrow annotation on top of your gauge chart. I answered a similar question and in that answer, I described how you can use polar coordinates to find out the ending position x and y for your arrow. Under the hood, the gauge chart you made has an x-range of [0,1] and a y-range of [0,1], so the starting point is ax=0.5 and ax=0 which are both parameters for your annotation. Then the ending position is given by x = 0.5 + r * cos(theta) and y = r * sin(theta) where theta is the angle taken from the right side of the chart and moving counterclockwise.
One thing you should keep in mind is that if the render area in your browser isn't a perfect square, then the r and theta values may need to be adjusted. For example, in my codepen, I used r=0.7, theta=93.5 to point to the 40.
let data = [
{
mode: "gauge",
type: "indicator",
value: 40,
gauge: {
shape: "angular",
bar: {
color: "blue",
line: {
color: "red",
width: 4
},
thickness: 0
},
bgcolor: "#388",
bordercolor: "#a89d32",
borderwidth: 3,
axis: {
range: [0,100],
visible: true,
tickmode: "array",
tickvals: [5, 10, 40, 80, 100],
ticks: "outside"
},
steps: [
{
range: [0, 40],
color: "#9032a8"
}
]
}
}
]
var theta = 93.5
var r = 0.7
var x_head = r * Math.cos(Math.PI/180*theta)
var y_head = r * Math.sin(Math.PI/180*theta)
let layout = {
xaxis: {range: [0, 1], showgrid: false, 'zeroline': false, 'visible': false},
yaxis: {range: [0, 1], showgrid: false, 'zeroline': false, 'visible': false},
showlegend: false,
annotations: [
{
ax: 0.5,
ay: 0,
axref: 'x',
ayref: 'y',
x: 0.5+x_head,
y: y_head,
xref: 'x',
yref: 'y',
showarrow: true,
arrowhead: 9,
}
]
};
Plotly.newPlot('gauge1', data, layout)
I want to display some scatter dots at the right-end edge of the bars and successfully did it, as shown in the Image 1 below.
But when there is only one length of data for the bar chart to draw, the bar disappears or become super thin, so only scatter dot are visible, as shown in Image 2 below.
Then, I disabled the scatter trace and the bars are visible as shown in Image 3 below.
Below are the scripts to produce these plots.
let initial = new Date("2020-11-08T00:00:00.000Z");
let final = new Date("2020-12-08T00:00:00.000Z");
let half = new Date((initial.getTime() + final.getTime())/2);
Plotly.newPlot(
testplot, {
data: [
{ y: [1000], x: [half], type: 'bar', offsetgroup: 0},
{ y: [1000], x: [half], type: 'bar', offsetgroup: 1},
{ y: [250], x: [final]},
], layout: { title: 'single bar', bargap: 0}, config: { responsive: true },
}
);
let t0 = initial, t1 = half, t2 = final;
let h0 = new Date((t0.getTime() + t1.getTime())/2);
let h1 = new Date((t1.getTime() + t2.getTime())/2);
Plotly.newPlot(
testplot2, {
data: [
{ y: [500, 750], base: [0, 250], x: [h0, h1], type: 'bar', offsetgroup: 0},
{ y: [500, 750], base: [0, 250], x: [h0, h1], type: 'bar', offsetgroup: 1},
{ y: [200, 800], x: [half, final]}
], layout: { title: 'more than one bar', bargap: 0 }, config: { responsive: true }
}
)
Right now, I have to calculate the midpoint of the date myself so I can offset the bars to the left so the dots appear at the right-edge of the bars. If I use the default dates to plot the bars and the dots, the dots will be placed at the center of the bars, but the bar on "single bar" did not disappear, as shown in Image 4 below.
I have no issue when the data length is more than one, but when the length is one; is there any way to make bars filled the canvas and the dot stays at the right edge? or how to offset the dots to the right?
I am trying a plot in a div using plotly.js which is a bit large in height. I want to fit it to div's height. If I use
<div id="plotDiv"></div>
and
var trace1 = {
x: ['giraffes', 'orangutans', 'monkeys'],
y: [20, 14, 23],
name: 'SF Zoo',
type: 'bar'
};
var trace2 = {
x: ['giraffes', 'orangutans', 'monkeys'],
y: [12, 18, 29],
name: 'LA Zoo',
type: 'bar'
};
var data = [trace1, trace2];
var layout = {
autosize:true,
barmode: 'stack',
xaxis: {
tickangle: -45
},
};
Plotly.newPlot('plotDiv', data, layout);
The plot is a bit large in height, so i put a max-height in div, this way :
<div id="plotDiv" style="max-height:300px"></div>
But this doesn't fit the plot in the div, and hides some of the plot. How to fit the complete plot in the div?
As suggested by someone, (who had deleted his answer later on, before I could try and accept his answer), following the link here: example,
I was able to resize the plot, :
var approved = {
x: approvedX,
y: approvedY,
name: 'Approved',
type: 'bar'
};
var unApproved = {
x: unApprovedX,
y: unApprovedY,
name: 'UnApproved',
type: 'bar'
};
var data = [approved, unApproved];
var layout = {
barmode: 'stack',
xaxis: {
tickangle: -20
},
// title: 'Applications Comparison'
};
// Plotly.newPlot('plotDiv', data, layout);
var d3 = Plotly.d3;
var HEIGHT_IN_PERCENT_OF_PARENT = 80;
var gd3 = d3.select('#plot2').append('div').style({
height: HEIGHT_IN_PERCENT_OF_PARENT + 'vh',
'margin-top': 0 + 'vh',
'margin-bottom': 10 + 'vh'
});
var gd = gd3.node();
Plotly.plot(gd, data, layout);
window.onresize = function() {
Plotly.Plots.resize(gd);
};
where approvedX, approvedY, unApprovedX, unApprovedY are lists.
Just add a new div around the #plotdiv. Try out the following code.
<div style="max-height:300px">
<div id="plotDiv" style="width:100%">
</div>
</div>
Suppose I'm using the simple box plot example in plotly's documentation:
var data = [
{
y: [0, 1, 1, 2, 3, 5, 8, 13, 21],
boxpoints: 'all',
jitter: 0.3,
pointpos: -1.8,
type: 'box'
}
];
Plotly.newPlot('myDiv', data);
I want to overlay a marker on top of the underlying data scatter plot that's to the left of the box plot. This marker would have its own hover text and everything. This is how I envision this looking:
Is there a way to do this in plotly? I've looked all over for an example of this, and I can't find anything that looks relevant. Thanks!
If you are plotting your points on top of the box plot (pointpos = 0) you can add another trace with an x value which is identical to your boxplot name, trace 0 in this case.
If you are plotting your points next to your boxplot, it becomes a lot more tricky because the scatter points do not have defined x-values on the axis.
You could your new point manually but then the hover info is still in the old position.
var data = [{
y: [0, 1, 1, 2, 3, 5, 8, 13, 21],
boxpoints: 'all',
jitter: 0.3,
pointpos: 0,
type: 'box'
},
{
y: [0, 1, 1, 2, 3, 5, 8, 13, 21],
boxpoints: 'all',
jitter: 0.3,
pointpos: 1.8,
type: 'box'
},
{
x: ['trace 0'],
y: [18],
name: 'My special marker',
text: 'Some really interesting hover info',
marker: {
size: 20
}
},
{
x: ['trace 1'],
y: [18],
name: 'Another special marker',
text: 'Some really interesting hover info',
marker: {
size: 20
}
}
];
Plotly.newPlot('myDiv', data);
var boxPoint = document.getElementsByClassName('trace boxes')[1].getElementsByClassName('point')[0];
var point = document.getElementsByClassName('scatterlayer')[0].getElementsByClassName('point')[1];
var y = point.attributes['transform'].value.split(',')[1];
var x = boxPoint.attributes['transform'].value.split(',')[0];
point.setAttribute('transform', x + ', ' + y);
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv"></div>
I am using Highcharts and it is working just amazing, i am stuck at a place where i want to plot a pie chart in which every pie slice (in a single pie chart) has a different radius.
Below is the image attached of the expexted pie chart.
You can skip making it a donout or designing it this specific. I just want to know how each pie slice can have different radius.
Each series in a pie chart can have their own size. So, I stacked a bunch of pie series calculating their begin and end angles. You'll have to do a little clean up to get the tooltips displaying the value instead of 100, but I think it's a workable solution.
Note: The following code makes a bad assumption that the data points add to 100. void fixes that assumption in his fiddle http://jsfiddle.net/58zfb8gy/1.
http://jsfiddle.net/58zfb8gy/
$(function() {
var data = [{
name: 'Thane',
y: 25,
color: 'red'
}, {
name: 'Nagpur',
y: 15,
color: 'blue'
}, {
name: 'Pune',
y: 30,
color: 'purple'
}, {
name: 'Mumbai',
y: 30,
color: 'green'
}];
var start = -90;
var series = [];
for (var i = 0; i < data.length; i++) {
var end = start + 360 * data[i].y / 100;
data[i].y = 100;
series.push({
type: 'pie',
size: 100 + 50 * i,
innerSize: 50,
startAngle: start,
endAngle: end,
data: [data[i]]
});
start = end;
};
$('#container').highcharts({
series: series
});
});
Another way I toyed with, that I didn't like as much, was having each series have invisible points:
series = [{
type: 'pie',
size: 100,
innerSize: 50,
data: [{y:25, color: 'red'}, {y:75, color:'rgba(0,0,0,0)'}]
},{
type: 'pie',
size: 150,
innerSize: 50,
data: [{y:25, color: 'rgba(0,0,0,0)'},{y:15, color: 'blue'}, {y:60, color:'rgba(0,0,0,0)'}]
}, ... ];
The variablepie series type, introduced in Highcharts 6.0.0, handles this with less code. In this series type you can specify a z-parameter for each data point to alter its z-size.
For example (JSFiddle, documentation):
Highcharts.chart('container', {
chart: {
type: 'variablepie'
},
title: {
text: 'Variable pie'
},
series: [{
minPointSize: 10,
innerSize: '20%',
zMin: 0,
name: 'countries',
data: [{
name: 'Pune',
y: 35,
z: 25
}, {
name: 'Mumbai',
y: 30,
z: 20
}, {
name: 'Nagpur',
y: 15,
z: 15
} , {
name: 'Thane',
y: 25,
z: 10
}]
}]
});
This requires including:
<script src="https://code.highcharts.com/modules/variable-pie.js"></script>