有一个解决方案。它需要 (a) 覆盖默认的单击行为,以及 (b) 补充默认的双击行为。在这两种情况下,我们都需要编写自定义事件处理程序。
似乎人们倾向于通过引入一些延迟来区分单击和双击,以确保任何给定的单击都不是双击中的第一次或最后一次。这是合理的,但是当在这样的应用程序中使用时,延迟是显着的:单击绘制的点后,在该点被突出显示之前有一个明显的延迟。出现延迟是因为单击 (plotly_click) 事件处理程序正在等待确保触发它的单击不是双击的一部分。
幸运的是,我们不需要在此应用程序中引入这种延迟。关键是要认识到完全区分单击和双击是不必要的。我们只需要确保触发plotly_click 的点击不是双击中的第二次点击。为什么我们只需要检查这种情况,我不确定。但这已经足够了,我们可以检查这种情况,而不会在突出显示过程中引入任何明显的延迟。
这是完成这项工作的代码。在 R 中:
library(plotly)
x <- c(rnorm(3000, 0, 3), rnorm(1000, 0, 0.2))
y <- c(rnorm(3000, 0, 3), rnorm(1000, 0, 0.2))
groups <- rep(c("a", "b", "c", "d"), 1000)
myData <- data.frame(x, y, groups)
myPlot <- plot_ly(
x = ~x, y = ~y,
color = ~groups,
data = myData)
myPlot$elementId <- "myPlot"
myPlot <- highlight(myPlot, on = NULL, off = "plotly_doubleclick")
onRender(myPlot, readLines("onRender.js"))
“onRender.js”在哪里
function singleClickHandler (data, el, COLORS_TRACE, OPACITY_START, OPACITY_DIM) {
let t0 = Date.now();
// If the triggering click wasn't the second click in a double click...
if ((t0 - doubleClickTime) > interval) {
highlightTrace(data, el, COLORS_TRACE, OPACITY_START, OPACITY_DIM);
}
}
function highlightTrace (data, el, OPACITY_START, OPACITY_DIM) {
// We want clicking on a point to "highlight" that point and all other
// points in the trace -- by dimming the points in all -other- traces.
const numTraces = el.data.length; // total # of traces in plot
const traceNum = data.points[0].curveNumber; // number of clicked trace
// Initialize array with one element for each trace
let traceOpacity = new Array(numTraces).fill().map( () => OPACITY_DIM );
// Set only the clicked-on trace to have normal (relatively high) opacity
traceOpacity[traceNum] = OPACITY_START;
// Restyle
Plotly.restyle("myPlot", { "marker.opacity": traceOpacity } );
}
function onRender (el) {
// Get opacity of first mark in first trace when figure is first displayed
const OPACITY_START = el._fullData[0].marker.opacity;
const OPACITY_DIM = 0.2;
// Set timing
interval = 1000; // two clicks within 1 second (1000 ms) is a double click
doubleClickTime = 0;
// Wrap the singleClickHandler() event handler in onSingleClick(). We do
// this so we can pass both event info ("data") and other objects to
// singleClickHandler().
var onSingleClick = (data) => singleClickHandler(data, el, OPACITY_START, OPACITY_DIM);
el.on('plotly_click', onSingleClick);
el.on('plotly_doubleclick', function (d) {
doubleClickTime = Date.now();
Plotly.restyle("myPlot", { "marker.opacity": OPACITY_START } );
});
}
onRender