You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Plotly中控制选框(Selection Box)与套索(Lasso)?

解决方案:在react-plotly.js中保存并恢复选框/套索选择

核心思路

react-plotly.js的<Plot/>组件本身没有暴露直接控制选框/套索的可控属性,但可以通过获取Plotly实例,结合Plotly原生的relayout和restyle方法实现选择状态的保存与恢复。

1. 捕获选框/套索的坐标

通过onSelected事件区分选框(box)和套索(lasso)类型,保存对应参数:

  • 选框选择:事件对象的range包含x/y轴范围
  • 套索选择:事件对象的lassoPoints包含选中点的坐标数组,建议同时映射对应点的索引,方便后续恢复
import { useState } from 'react';
import Plot from 'react-plotly.js';

function MyPlot() {
  const [savedSelection, setSavedSelection] = useState(null);

  const handleSelected = (event) => {
    // 示例数据为单一trace,实际需根据你的数据结构调整
    const traceData = data[0];
    
    if (event.range) {
      // 保存选框范围
      setSavedSelection({
        type: 'box',
        range: { ...event.range }
      });
    } else if (event.lassoPoints) {
      // 保存套索点坐标及对应点索引
      const selectedIndices = event.lassoPoints.map(point => 
        traceData.x.indexOf(point.x)
      );
      setSavedSelection({
        type: 'lasso',
        lassoPoints: [...event.lassoPoints],
        selectedIndices
      });
    }
  };

  // ...后续逻辑
}

2. 获取Plotly实例

通过useRef绑定<Plot/>组件,拿到底层的Plotly实例,用于调用原生方法:

const plotRef = useRef(null);

// 在Plot组件上绑定ref
<Plot
  ref={plotRef}
  data={/* 你的数据 */}
  layout={/* 你的布局 */}
  config={{ selectable: true }} // 必须开启选择功能
  onSelected={handleSelected}
/>

3. 恢复选框/套索选择

点击按钮时,根据保存的选择类型调用Plotly原生方法恢复:

  • 选框:用relayout设置坐标轴范围,同时高亮选框内的点
  • 套索:用restyle设置选中点索引;若需要显示套索路径,可通过添加临时trace模拟

完整代码示例:

import { useState, useRef } from 'react';
import Plot from 'react-plotly.js';

function MyPlot() {
  const [savedSelection, setSavedSelection] = useState(null);
  const plotRef = useRef(null);

  // 示例散点数据
  const data = [
    {
      x: [1, 2, 3, 4, 5, 6, 7],
      y: [2, 4, 1, 3, 5, 2, 6],
      mode: 'markers',
      type: 'scatter',
      marker: { size: 12 }
    }
  ];

  const handleSelected = (event) => {
    const traceData = data[0];
    if (event.range) {
      setSavedSelection({
        type: 'box',
        range: { ...event.range }
      });
    } else if (event.lassoPoints) {
      const selectedIndices = event.lassoPoints.map(point => 
        traceData.x.indexOf(point.x)
      );
      setSavedSelection({
        type: 'lasso',
        lassoPoints: [...event.lassoPoints],
        selectedIndices
      });
    }
  };

  const restoreSelection = () => {
    if (!savedSelection || !plotRef.current) return;
    const plot = plotRef.current.plotly;
    const traceData = data[0];

    if (savedSelection.type === 'box') {
      // 恢复坐标轴范围
      plot.relayout({
        'xaxis.range': [savedSelection.range.x[0], savedSelection.range.x[1]],
        'yaxis.range': [savedSelection.range.y[0], savedSelection.range.y[1]]
      });
      // 高亮选框内的点
      const filteredIndices = traceData.x.filter((x, idx) => 
        x >= savedSelection.range.x[0] && x <= savedSelection.range.x[1] &&
        traceData.y[idx] >= savedSelection.range.y[0] && traceData.y[idx] <= savedSelection.range.y[1]
      ).map(x => traceData.x.indexOf(x));
      plot.restyle({ selectedpoints: filteredIndices }, 0);
    } else if (savedSelection.type === 'lasso') {
      // 恢复选中点
      plot.restyle({ selectedpoints: savedSelection.selectedIndices }, 0);
      // 模拟套索路径(Plotly原生不支持直接恢复绘制路径)
      const lassoTrace = {
        x: savedSelection.lassoPoints.map(p => p.x),
        y: savedSelection.lassoPoints.map(p => p.y),
        mode: 'lines',
        type: 'scatter',
        line: { color: '#1f77b4', dash: 'dot' },
        name: 'Lasso Path',
        showlegend: false
      };
      // 移除已存在的套索路径trace
      const existingLassoIdx = data.findIndex(t => t.name === 'Lasso Path');
      if (existingLassoIdx !== -1) plot.deleteTraces(existingLassoIdx);
      plot.addTraces(lassoTrace);
    }
  };

  return (
    <div>
      <Plot
        ref={plotRef}
        data={data}
        layout={{ width: 600, height: 400, title: '选择恢复演示' }}
        config={{ selectable: true }}
        onSelected={handleSelected}
      />
      <button onClick={restoreSelection} disabled={!savedSelection}>
        恢复选择
      </button>
    </div>
  );
}

export default MyPlot;

关键说明

  • Plotly原生不支持直接恢复套索的绘制路径,只能恢复选中点;若需要显示路径,可通过添加临时trace模拟。
  • 保存选择时建议同时保存点索引,避免恢复时重新匹配坐标的性能损耗。
  • 必须确保<Plot/>的config中设置selectable: true,才能开启选框/套索功能。

内容的提问来源于stack exchange,提问作者LCIII

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 14:45:55