Plotly.js悬停标记时平移功能失效问题求助
问题:Plotly.js 悬停标记时平移功能异常
悬停在图表标记上时,使用平移工具拖拽图表后,图表会自动恢复到原始位置。
重现步骤
- 选择平移工具
- 悬停在标记上
- 拖拽图表进行平移
- 图表立即恢复至原始位置
相关代码
JavaScript
var data = [{ mode: "lines+markers", x:["December", "January", "February"], y:[4,1,3] }] Plotly.react('myDiv', data).then(gd => { gd.on('plotly_hover', d => { var width_vals = gd.data.map(x => 5) Plotly.restyle(gd, 'line.width', width_vals) }).on('plotly_unhover', d => { var width_vals = gd.data.map(x => 1) Plotly.restyle(gd, 'line.width', width_vals) }) })
HTML
<head> <!-- Load plotly.js into the DOM --> <script src='https://cdn.plot.ly/plotly-2.12.1.min.js'></script> </head> <body> <div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div> </body>
问题演示

原因分析
每次触发plotly_hover或plotly_unhover事件时调用Plotly.restyle(),会触发Plotly完整的图表重渲染流程,这个过程会重置图表的视图状态(包括平移后的坐标轴范围),导致拖拽平移后图表立刻回到初始位置。
解决方法
方法1:直接操作SVG元素修改线条宽度(推荐)
绕过Plotly的重渲染API,直接定位图表中的线条SVG元素修改样式,不会影响视图状态:
var data = [{ mode: "lines+markers", x:["December", "January", "February"], y:[4,1,3] }] Plotly.react('myDiv', data).then(gd => { // 预获取所有线条元素 const lineElements = gd.querySelectorAll('.scatterlayer path.line'); gd.on('plotly_hover', () => { lineElements.forEach(el => el.setAttribute('stroke-width', 5)); }).on('plotly_unhover', () => { lineElements.forEach(el => el.setAttribute('stroke-width', 1)); }) })
方法2:重渲染后恢复视图状态
如果必须使用Plotly.restyle(),可在操作前后保存并恢复当前视图范围:
var data = [{ mode: "lines+markers", x:["December", "January", "February"], y:[4,1,3] }] Plotly.react('myDiv', data).then(gd => { gd.on('plotly_hover', d => { // 保存当前坐标轴范围 const xRange = gd.layout.xaxis.range; const yRange = gd.layout.yaxis.range; var width_vals = gd.data.map(x => 5) Plotly.restyle(gd, 'line.width', width_vals).then(() => { // 恢复之前的视图范围 Plotly.relayout(gd, { 'xaxis.range': xRange, 'yaxis.range': yRange }); }) }).on('plotly_unhover', d => { const xRange = gd.layout.xaxis.range; const yRange = gd.layout.yaxis.range; var width_vals = gd.data.map(x => 1) Plotly.restyle(gd, 'line.width', width_vals).then(() => { Plotly.relayout(gd, { 'xaxis.range': xRange, 'yaxis.range': yRange }); }) }) })
内容的提问来源于stack exchange,提问作者Williams86
相关产品推荐
相关产品推荐

