Fit a plot in a div's max height - javascript

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>

Related

how to update plotly.js chart with new data from website?

I am trying to update the chart with plotly.js with data from a server. My function should plot updated data in the charts every time new data is sent.
I have two different graphs in my chart. Both with the same X value but different values for the Y axis. I can create the expected graphs in the chart with the first values. But when new values are sent, the restyle function did not update the values.
I don't know how to parse the data to the restyle function. Or, do I need to use a different function?
var source = new EventSource("http://old.iolab.sk/evaluation/sse/sse.php");
source.onmessage = function(event) {
count++;
if(count == 1){ // only on first data from server
var layout = {title: "Website graph"};
var trace1 = {
x: [event.data.match(/\d+/g)[0]],
y: [(event.data.match(/\d+/g)[2] + "." + event.data.match(/\d+/g)[3])], // y1 from server
name: "hehe",
type: 'scatter'
};
var trace2 = {
x: [event.data.match(/\d+/g)[0]],
y: [(event.data.match(/\d+/g)[5] + "." + event.data.match(/\d+/g)[6])], // y2 from server
name: "hehe",
type: 'scatter'
};
Plotly.newPlot("websiteGraph", [trace1, trace2], layout);
return;
}
if(!isClicked){ // keeps updating the chart with data from the server until the button is clicked
trace1 = {'x': [[event.data.match(/\d+/g)[0]]], 'y': [[(event.data.match(/\d+/g)[2] + "." + event.data.match(/\d+/g)[3])]]},
trace2 = {'x': [[event.data.match(/\d+/g)[0]]], 'y': [[(event.data.match(/\d+/g)[5] + "." + event.data.match(/\d+/g)[6])]]};
Plotly.restyle("websiteGraph", trace1+trace2);
}
return;
}
This is the data from the server, one ID is for one update:
id: 0
data: {
data: "x": "0",
data: "y1": "0.05",
data: "y2": "1.03"
data: }
id: 1
data: {
data: "x": "1",
data: "y1": "0.077452406437284",
data: "y2": "1.0998476951564"
data: }
id: 2
data: {
data: "x": "2",
data: "y1": "0.1048994967025",
data: "y2": "1.0893908270191"
data: }
id: 3
data: {
data: "x": "3",
data: "y1": "0.13233595624294",
data: "y2": "1.0086295347546"
data: }
To answer your question, try using Plotly.react or Plotly.newPlot for new data.
Plotly.restyle seems to be wrong (layout changes only?), as well as some argument passed into the functions.
The comments and examples below are from the Plotly docs at https://plotly.com/javascript/plotlyjs-function-reference/#plotlyrestyle.
To see the code in action, check out this fiddle: https://jsfiddle.net/a0cj6bnm/
In restyle, arrays are assumed to be used in conjunction with the trace indices provided. Therefore, to apply an array as a value, you need to wrap it in an additional array. For example:
var graphDiv = document.getElementById(graphDiv);
var update = {
opacity: 0.5,
marker: {
size: [40, 60, 80, 100],
color: ['rgb(93, 164, 214)', 'rgb(255, 144, 14)', 'rgb(44, 160, 101)', 'rgb(255, 65, 54)']
}
}
Plotly.restyle(graphDiv, update, 0);
Note: To me, it seems that restyle is for layout changes only. Not sure though. Instead of 0, restyle can get an array of values but this had no effect on my tests.
newPlot draws a new plot in an element, overwriting any existing plot. To update an existing plot in a , it is much more efficient to use Plotly.react than overwrite it.
The function seems to expect an array and a layout hash as an argument.
var graphDiv = document.getElementById(graphDiv);
var layout = {
title: "Website graph",
xaxis: {
title: 'Year',
showgrid: false,
zeroline: false
},
yaxis: {
title: 'Percent',
showline: false
}
};
var trace1 = {
x: [1],
y: [1], // y1 from server
name: "hehe1",
type: 'scatter'
};
var trace2 = {
x: [2],
y: [2],
name: "hehe2",
type: 'scatter'
};
Plotly.newPlot(graphDiv, [trace1, trace2], layout);
Plotly.react has the same signature as Plotly.newPlot above, and can be used in its place to create a plot, but when called again on the same will update it far more efficiently than Plotly.newPlot, which would destroy and recreate the plot. Plotly.react is as fast as Plotly.restyle/Plotly.relayout documented below.
var graphDiv = document.getElementById(graphDiv);
var trace1 = {
x: [1,2,3,4,5],
y: [1,3,5,7], // y1 from server
name: "hehe1",
type: 'scatter'
};
var trace2 = {
x: [2,3,4,5,7,8],
y: [2,2,2,2,3,4],
name: "hehe2",
type: 'scatter'
};
Plotly.react(graphDiv, [trace1, trace2], layout);

Why is my bar plots disappear when scatter plots appear?

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?

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>

Can I assign a different radius for each pie slice using Highcharts?

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>

Adding data to empty rickshaw chart

I am charting different data with RickshawJS. But I need a way to update the chart when a user clicks the #search button. Right now it just creates a new chart below the old one, and that is pretty messy.
The user enters the page and enters some details and clicks the button to chart it. So ideally I'd like to start with an empty chart that isn't shown, but I can't really figure out how to remove the data from the chart and axes and then update it.
I could call $('#chart svg').remove(); on the chart and axes but it seems messy.
$('#search').click(function(event){
event.preventDefault();
var data = utils.malletData();
var graph = new Rickshaw.Graph( {
element: document.querySelector("#chart"),
width: 800,
height: 250,
series: [ {
name: data['name'],
color: 'steelblue',
data: data['series']
} ]
} );
graph.render();
var hoverDetail = new Rickshaw.Graph.HoverDetail( {
graph: graph,
xFormatter: function(x) {
var date = new Date(x).getTime();
return moment(x).format('MMMM Do YYYY, h:mm:ss a');
},
yFormatter: function(y) { return Math.floor(y) + " users" }
} );
var xAxis = new Rickshaw.Graph.Axis.X( {
graph: graph,
orientation: 'bottom',
element: document.getElementById('x_axis'),
tickFormat: function(x) { return moment(x).fromNow(); },
ticks: 7,
tickSize: 1,
} );
xAxis.render();
var ticksTreatment = 'glow';
var yAxis = new Rickshaw.Graph.Axis.Y( {
graph: graph,
orientation: 'left',
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
ticksTreatment: ticksTreatment,
element: document.getElementById('y_axis'),
} );
yAxis.render();
});
There's no official way to do so. However, you could leverage the fact that arrays in javascript are passed by reference and then update the graph.
Have a look at this demo on fiddle
var data = [
{
data: [ { x: 0, y: 120 }, { x: 1, y: 890 }, { x: 2, y: 38 }, { x: 3, y: 70 }, { x: 4, y: 32 } ],
color: "#c05020"
}, {
data: [ { x: 0, y: 80 }, { x: 1, y: 200 }, { x: 2, y: 100 }, { x: 3, y: 520 }, { x: 4, y: 133 } ],
color: "#30c020"
}
];
var graph = new Rickshaw.Graph( {
element: document.getElementById("chart"),
renderer: 'line',
height: 300,
width: 800,
series: data
} );
var y_ticks = new Rickshaw.Graph.Axis.Y( {
graph: graph,
orientation: 'left',
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
element: document.getElementById('y_axis'),
} );
graph.render();
$('button#add').click(function() {
data.push({
data: [ { x: 0, y: 200 }, { x: 1, y: 390 }, { x: 2, y: 1000 }, { x: 3, y: 200 }, { x: 4, y: 230 } ],
color: "#6060c0"
});
graph.update();
});

Categories