makes shapes with loop in Plotly - javascript

So far i got this code `
shapes: [
{
type: "line",
xref: "x",
yref: "paper",
x0: data[i],
y0: 0,
x1: data[i],
y1: 1,
line: {
color: "red",
width: 2,
dash: "longdash",
},
},
],
I want to set up a vertical line in my plot on a specific position and this works fine. Now how can i do more of the exact same line ? cause my array of data will be updated after a button. If there is only one point in my array i get a line , but if a try to set up a second line it just wont work. Can i somehow make a for loop to plot me those lines ? i just want to plot more than one vertical lane at different places.

You can construct shapes as an array containing multiple dictionaries: something in the form [{shape 1 info}, ..., {shape N info}]. To do that you can loop through your data array, and use data[i] as the x-coordinates of each line in your shapes array.
Here is some sample code and the codepen.
var data = [1,2,3,5]
shapes = []
for (let i = 0; i < data.length; i++) {
shapes.push({
type: "line",
xref: "x",
yref: "paper",
x0: data[i],
y0: 0,
x1: data[i],
y1: 1,
line: {
color: "red",
width: 2,
dash: "longdash",
},
})
}
var trace1 = {
x: [2, 6],
y: [1, 2],
mode: 'markers+lines'
};
var layout = {
title: 'Vertical Line Annotations',
xaxis: {
range: [0, 7]
},
yaxis: {
range: [0, 6]
},
shapes: shapes
};
var plotdata = [trace1];
Plotly.newPlot('myDiv', plotdata, layout);

Related

how to add a needle or dial to gauge indicator in plotly.js?

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)

Plotly JavaScript: Customize y ticks or labels on y axis

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>

How to remove batch of points in the period based on xAxis(time) coordinates from the series in Highstock

I've got a series and I need to remove points selected by time.
For example points from 4 Dec to 25 Dec in this fiddle:
http://jsfiddle.net/9rLbft5q/
series: [{
name: 'AAPL Stock Price',
data: data,
type: 'areaspline',
threshold: null,
tooltip: {
valueDecimals: 2
},
fillColor: {
linearGradient: {
x1: 0,
y1: 0,
x2: 0,
y2: 1
},
stops: [
[0, Highcharts.getOptions().colors[0]],
[1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
]
}
}]
Filter data retrieved from getJson() with array.filter() function:
var start = new Date("4 Dec 2017").getTime();
var end = new Date("25 Dec 2017").getTime();
var filtered = data.filter(function(item, index, arr) {
if (item[0]>end || item[0]<start) return item;
}, []);
Check fiddle updated: http://jsfiddle.net/beaver71/axxm0fh1/

Is it possible to overlay a marker on top of a plotly.js box plot?

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>

How to show gradient vertically on chart js grouped bar chart?

I am using Chart.js grouped bar chart. I want to show my bars with gradient colors. Currently it show as shown in below image. Any help will be greatly appreciated.
var rateOfReturn= document.getElementById("rateofreturn-chart-canvas").getContext('2d');
var rateOfReturnData = {
labels: ["Monthly", "Quarterly", "Semiannually", "Annually"],
datasets: [
{
label: "label1",
backgroundColor: [
'#26343b',
'#26343b',
'#26343b',
'#26343b'
],
data: [4, 6, 8, -3],
},
{
label: "",
backgroundColor: [
'#be1a33',
'#be1a33',
'#be1a33',
'#be1a33'
],
data: [6, 10, 11, 7],
},
{
label: "",
backgroundColor: [
'#00b786',
'#00b786',
'#00b786',
'#00b786'
],
data: [13, 10, 9, 4],
},
{
label: "",
backgroundColor: [
'#f86929',
'#f86929',
'#f86929',
'#f86929'
],
data: [6, 8, 2, 11],
},
{
label: "",
backgroundColor: [
'#046cd0',
'#046cd0',
'#046cd0',
'#046cd0'
],
data: [4, 8, 7, 13],
}
]
};
rateOfReturn.canvas.height = 80;
var myBarChart = new Chart(rateOfReturn, {
type: 'bar',
data: rateOfReturnData,
options: {
legend:
{
display: false
},
scales:
{
xAxes: [{
title: "Test title",
ticks: {
beginAtZero: true,
titleFontWeight: "bold"
},
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Rate Of Return (ROR) % '
},
ticks: {
beginAtZero:true,
mirror:false,
suggestedMin: 0
},
}]
}
}
});
You want to use Chart.js plugins. They let you handle some events triggered through the chart creation such as the initialization, the resize, etc.
Chart.pluginService.register({
beforeUpdate: function(chart) {
// All the code added here will be executed before a chart update
}
});
You also want to use createLinearGradient to create a gradient color usable in a canvas :
var gradient = ctx.createLinearGradient(0,0,200,0); // Dimensions of the color rectangle
gradient.addColorStop(0,"green"); // First color
gradient.addColorStop(1,"white"); // Second color
Now you want to use both into one. Let's first see how it works.
You first have to add the two colors of the gradient you want to see in your chart data :
datasets: [{
label: "label1",
backgroundColor: [
['#26343b', 'white'], // `white` and `#FFFFFF` both stand for a white color
['#26343b', 'white'],
['#26343b', 'white'],
['#26343b', 'white']
],
data: [4, 6, 8, -3],
}, {
// ...
}]
Then you need to add the following plugin before you create the chart (using new Chart()), or else it won't be added into the chart's plugin service :
Chart.pluginService.register({
beforeUpdate: function(chart) {
// For every dataset ...
for (var i = 0; i < chart.config.data.datasets.length; i++) {
// We store it
var dataset = chart.config.data.datasets[i];
// For every data in this dataset
for (var j = 0; j < dataset.data.length; j++) {
// We store the data model (graph information)
var model = dataset._meta[0].data[j]._model;
// We use the model to get the left & right borders X position
// and to create the gradient
var start = model.x,
end = model.x + model.width,
gradient = rateOfReturn.createLinearGradient(start, 0, end - 5, 0);
// The colors of the gradient that were defined in the data
gradient.addColorStop(0, dataset.backgroundColor[j][0]);
gradient.addColorStop(1, dataset.backgroundColor[j][1]);
// We set this new color to the data background
dataset.backgroundColor[j] = gradient;
}
}
}
});
Follows the result of the plugin with your example, which you can find on this jsFiddle :

Categories