如何从R plotly图形中获取坐标 [英] How to get coordinates from a R plotly figure
问题描述
我一直在疯狂地努力解决一个看似基本的问题.想象一下,你有一个散点图,比如说... 10 个标记.我想这个图是在 Shiny 环境中使用 plotly 生成的.
I have been struggling like mad to solve an apparently basic question. Imagine you have a scatter plot, with say ... 10 markers. I suppose this plot has been generated using plotly within a Shiny environment.
使用 event_data("plotly_click")
代码可以轻松获取这些标记的坐标.
One can easily get the coordinates of these markers using the event_data("plotly_click")
code.
现在假设您不需要这些标记的坐标,而是通过鼠标单击生成的坐标,但恰好在不存在标记的位置(例如,因为您想在此处设置一个新标记,并且您想重新- 使用来自该鼠标点击的信息).
Now imagine you do not need the coordinates of these markers, but the coordinates generated by a mouse click but precisely where no marker exists (for example because you would like to set a new marker exactly there, and you would like to re-use the information coming from that mouse click).
我无法使用 onclick()
或其他方式获得这样的行为.
I cannot obtain such a behavior using onclick()
, or whatever.
有什么想法吗?
推荐答案
你可以在你的情节中添加一个 D3 事件监听器
You could add a D3 event listener to your plot
Plotly.d3.select('.plotly').on('click', function(d, i) {})
然后
- 根据点击位置(
d3.event.layerX
resp.layerY
)获取相对的 x 和 y 值 - 调整相对图形位置 (
document.getElementsByClassName('bg')[0].attributes['x']
) - 最后根据轴范围计算新值 (
myPlot.layout.xaxis.range[0]
)
- retrieve the relative x and y values based on the click position (
d3.event.layerX
resp.layerY
) - adjusting for the relative graph position (
document.getElementsByClassName('bg')[0].attributes['x']
) - and finally calculating the new values based on the axis ranges (
myPlot.layout.xaxis.range[0]
)
然后将新的 x
和 y
值推送到现有图表中
The new x
and y
value are then pushed to the existing graph
Plotly.extendTraces(myPlot, {
x: [[x]],
y: [[y]]
}, [1]);
完整的 R 代码
library("plotly")
library("htmlwidgets")
p <- plot_ly(x = c( -2, 0, 2 ),y = c( -2, 1, 2), type = 'scatter' ,mode = 'lines+markers') %>%
add_trace(x=c(-1,0.4,2),y=c(2, 0, -1),type='scatter',mode='lines+markers') %>%
layout(hovermode='closest')
javascript <- "
var myPlot = document.getElementsByClassName('plotly')[0];
Number.prototype.between = function (min, max) {
return this >= min && this <= max;
};
Plotly.d3.select('.plotly').on('click', function(d, i) {
var e = Plotly.d3.event;
var bg = document.getElementsByClassName('bg')[0];
var x = ((e.layerX - bg.attributes['x'].value + 4) / (bg.attributes['width'].value)) * (myPlot.layout.xaxis.range[1] - myPlot.layout.xaxis.range[0]) + myPlot.layout.xaxis.range[0];
var y =((e.layerY - bg.attributes['y'].value + 4) / (bg.attributes['height'].value)) * (myPlot.layout.yaxis.range[0] - myPlot.layout.yaxis.range[1]) + myPlot.layout.yaxis.range[1]
if (x.between(myPlot.layout.xaxis.range[0], myPlot.layout.xaxis.range[1]) &&
y.between(myPlot.layout.yaxis.range[0], myPlot.layout.yaxis.range[1])) {
Plotly.extendTraces(myPlot, {
x: [[x]],
y: [[y]]
}, [1]);
}
});"
p <- htmlwidgets::prependContent(p, onStaticRenderComplete(javascript), data=list(''))
p
<小时>
交互式 Javascript 示例
var traces = [{
x: [1, 2, 3, 4],
y: [10, 15, 13, 17],
mode: 'markers',
type: 'scatter'
}];
traces.push({
x: [2, 3, 4, 5],
y: [16, 5, 11, 9],
mode: 'markers',
type: 'scatter'
});
traces.push({
x: [1, 2, 3, 4],
y: [12, 9, 15, 12],
mode: 'markers',
type: 'scatter'
});
traces.push({
x: [],
y: [],
mode: 'lines+markers',
type: 'scatter'
});
var myPlot = document.getElementById('myPlot')
Plotly.newPlot('myPlot', traces, {hovermode: 'closest'});
Number.prototype.between = function(min, max) {
return this >= min && this <= max;
};
Plotly.d3.select(".plotly").on('click', function(d, i) {
var e = Plotly.d3.event;
var bg = document.getElementsByClassName('bg')[0];
var x = ((e.layerX - bg.attributes['x'].value + 4) / (bg.attributes['width'].value)) * (myPlot.layout.xaxis.range[1] - myPlot.layout.xaxis.range[0]) + myPlot.layout.xaxis.range[0];
var y = ((e.layerY - bg.attributes['y'].value + 4) / (bg.attributes['height'].value)) * (myPlot.layout.yaxis.range[0] - myPlot.layout.yaxis.range[1]) + myPlot.layout.yaxis.range[1]
if (x.between(myPlot.layout.xaxis.range[0], myPlot.layout.xaxis.range[1]) &&
y.between(myPlot.layout.yaxis.range[0], myPlot.layout.yaxis.range[1])) {
Plotly.extendTraces(myPlot, {
x: [
[x]
],
y: [
[y]
]
}, [3]);
}
});
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myPlot" style="width:100%;height:100%"></div>
闪亮的例子
library(shiny)
library("plotly")
library("htmlwidgets")
ui <- fluidPage(
plotlyOutput("plot")
)
server <- function(input, output) {
javascript <- "
function(el, x){
Number.prototype.between = function (min, max) {
return this >= min && this <= max;
};
Plotly.d3.select('.plotly').on('click', function(d, i) {
var e = Plotly.d3.event;
var bg = document.getElementsByClassName('bg')[0];
var x = ((e.layerX - bg.attributes['x'].value + 4) / (bg.attributes['width'].value)) * (el.layout.xaxis.range[1] - el.layout.xaxis.range[0]) + el.layout.xaxis.range[0];
var y =((e.layerY - bg.attributes['y'].value + 4) / (bg.attributes['height'].value)) * (el.layout.yaxis.range[0] - el.layout.yaxis.range[1]) + el.layout.yaxis.range[1]
if (x.between(el.layout.xaxis.range[0], el.layout.xaxis.range[1]) && y.between(el.layout.yaxis.range[0], el.layout.yaxis.range[1])) {
Plotly.extendTraces(el, {
x: [[x]],
y: [[y]]
}, [1]);
}
});
}"
output$plot <- renderPlotly({
plot_ly(x = c( -2, 0, 2 ),y = c( -2, 1, 2), type = 'scatter' ,mode = 'lines+markers') %>%
add_trace(x=c(-1,0.4,2),y=c(2, 0, -1),type='scatter',mode='lines+markers') %>%
layout(hovermode='closest') %>% onRender(javascript)
})
}
shinyApp(ui = ui, server = server)
这篇关于如何从R plotly图形中获取坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!