I’m trying to select multiple charts under each other with Plotly, in JavaScript. The best I could do so far is to create a stacked chart, but it still does not allow selection of multiple rows.
The idea is to detect in which row, at which point did the user start to drag there mouse and at which row, which point it ended. The charts should be selected from start to end. If there are multiple charts between the starting and ending row, the whole chart should be selected. Is there some sort of built-in solution for this in Plotly? I want to avoid HTML Canvases on top of Plotly at all costs, but so far I can’t see any other solution.
My code so far:
var trace1 = {
x: [0, 1, 2],
y: [10, 20, 30],
type: "scatter",
xaxis: "x",
yaxis: "y",
};
var trace2 = {
x: [2, 3, 4],
y: [10, 20, 30],
type: "scatter",
xaxis: "x",
yaxis: "y2",
};
var trace3 = {
x: [3, 4, 5],
y: [10, 20, 30],
type: "scatter",
xaxis: "x",
yaxis: "y3",
};
var dummyTrace = {
x: [0],
y: [0],
xaxis: "x_overlay",
yaxis: "y_overlay",
mode: "markers",
marker: { opacity: 0 }, // invisible dummy trace
showlegend: false,
hoverinfo: "skip",
};
var data = [trace1, trace2, trace3, dummyTrace];
var layout = {
grid: { rows: 3, columns: 1, pattern: "independent" },
xaxis: { domain: [0, 1] }, // real xaxis
yaxis: { domain: [0.66, 1] }, // top subplot
yaxis2: { domain: [0.33, 0.66] }, // middle
yaxis3: { domain: [0, 0.33] }, // bottom
// This is the transparent overlay axis (spanning entire figure)
xaxis_overlay: { domain: [0, 1], overlaying: "x", visible: false },
yaxis_overlay: { domain: [0, 1], overlaying: "y", visible: false },
dragmode: "select",
selectdirection: "any",
margin: { l: 50, r: 20, t: 20, b: 50 },
};
Plotly.newPlot("myDiv", data, layout);
// Listen to selection events — this works across entire panel now:
document.getElementById("myDiv").on("plotly_selected", function (eventData) {
if (eventData) {
console.log("Selected points:", eventData.points);
// You can now filter which subplot they came from:
eventData.points.forEach((pt) => {
console.log(`subplot: ${pt.yaxis}, x: ${pt.x}, y: ${pt.y}`);
});
}
});
It looks like this:
