如何同时使用Plotly的plotly_click与plotly_selected事件?
plotly_click Event Conflict with plotly_selected Hey there! The issue you're facing happens because Plotly's event handling can prioritize box/lasso selection events over click events when both are active. Here are two straightforward solutions to get both features working together:
Solution 1: Use Native Click Event with Plotly's getPoint
Instead of relying on Plotly's plotly_click event, use the browser's native click event paired with Plotly's getPoint method to fetch the clicked coordinates. This bypasses any event conflicts with plotly_selected.
First, make sure your layout.shapes array is initialized (critical for avoiding errors):
// Initialize shapes array if it doesn't exist yet if (!layout.shapes) { layout.shapes = []; }
Then replace your original plotly_click handler with this native click listener:
// Handle click to add vertical line using native click event plotDiv.addEventListener('click', function(event) { // Get the exact Plotly data point clicked const clickedPoint = Plotly.getPoint(event, 'myDiv'); if (clickedPoint) { const xVal = clickedPoint.x; console.log("Vous voulez ajouter une rupture au point : ", xVal); // Add vertical line to the layout shapes layout.shapes.push({ 'type': 'line', 'x0': xVal, 'y0': line_bottom, 'x1': xVal, 'y1': line_top, 'line': { 'color': 'black', dash: 'dot', 'width': 3, } }); Plotly.redraw('myDiv'); } });
Keep your existing plotly_selected handler as-is, but add a check to skip it for click-only actions:
// Handle box selection to draw rectangle plotDiv.on('plotly_selected', (eventData) => { const xRange = eventData.range.x; const yRange = eventData.range.y; // Only run if it's a real box selection (not a click) if (xRange[0] !== xRange[1] && yRange[0] !== yRange[1]) { console.log("x0 = ",xRange[0]," x1 = ",xRange[1]," y0 = ",yRange[0]," y1 = ",yRange[1]); // Add the four lines for the rectangle layout.shapes.push({ 'type': 'line', 'x0':xRange[0], 'y0':yRange[0], 'x1':xRange[0], 'y1':yRange[1], 'line': { 'color': 'red', dash: 'dot', 'width':3, } }); layout.shapes.push({ 'type': 'line', 'x0':xRange[1], 'y0':yRange[0], 'x1':xRange[1], 'y1':yRange[1], 'line': { 'color': 'red', dash: 'dot', 'width':3, } }); layout.shapes.push({ 'type': 'line', 'x0':xRange[0], 'y0':yRange[1], 'x1':xRange[1], 'y1':yRange[1], 'line': { 'color': 'red', dash: 'dot', 'width':3, } }); layout.shapes.push({ 'type': 'line', 'x0':xRange[0], 'y0':yRange[0], 'x1':xRange[1], 'y1':yRange[0], 'line': { 'color': 'red', dash: 'dot', 'width':3, } }); Plotly.redraw('myDiv'); } });
Solution 2: Merge Logic into plotly_selected Event
If you prefer to keep everything in one event handler, check if the "selection" is actually a click (where the start and end coordinates are identical). Then run the appropriate logic:
// Initialize shapes array if (!layout.shapes) { layout.shapes = []; } // Combined handler for clicks and box selections plotDiv.on('plotly_selected', (eventData) => { const xRange = eventData.range.x; const yRange = eventData.range.y; // Check if it's a click (no range change) if (xRange[0] === xRange[1] && yRange[0] === yRange[1]) { const xVal = xRange[0]; console.log("Vous voulez ajouter une rupture au point : ", xVal); // Add vertical line layout.shapes.push({ 'type': 'line', 'x0': xVal, 'y0': line_bottom, 'x1': xVal, 'y1': line_top, 'line': { 'color': 'black', dash: 'dot', 'width': 3, } }); } else { // It's a box selection, draw the rectangle console.log("x0 = ",xRange[0]," x1 = ",xRange[1]," y0 = ",yRange[0]," y1 = ",yRange[1]); // Add rectangle lines layout.shapes.push({ 'type': 'line', 'x0':xRange[0], 'y0':yRange[0], 'x1':xRange[0], 'y1':yRange[1], 'line': { 'color': 'red', dash: 'dot', 'width':3, } }); layout.shapes.push({ 'type': 'line', 'x0':xRange[1], 'y0':yRange[0], 'x1':xRange[1], 'y1':yRange[1], 'line': { 'color': 'red', dash: 'dot', 'width':3, } }); layout.shapes.push({ 'type': 'line', 'x0':xRange[0], 'y0':yRange[1], 'x1':xRange[1], 'y1':yRange[1], 'line': { 'color': 'red', dash: 'dot', 'width':3, } }); layout.shapes.push({ 'type': 'line', 'x0':xRange[0], 'y0':yRange[0], 'x1':xRange[1], 'y1':yRange[0], 'line': { 'color': 'red', dash: 'dot', 'width':3, } }); } Plotly.redraw('myDiv'); });
Key Notes
- Make sure
line_bottomandline_topare properly defined with your chart's y-axis bounds. - Both solutions ensure clicks and box selections don't interfere with each other.
内容的提问来源于stack exchange,提问作者kowsik186

