Интерактивное добавление точек к графику R без перерисовки фонового графика
MWE ниже упрощает мою реальную цель. Тем не менее, у меня есть фоновое изображение, на рисование которого уходит много времени (в приведенном ниже примере это просто диаграмма рассеяния из 32 наборов данных mtcars). Пользователи могут щелкать определенные точки на моем фоновом изображении, и это приведет к созданию новых точек. Моя цель состоит в том, чтобы эти новые точки просто перерисовывались на верхнем слое, в то время как график рассеяния фонового изображения не нужно перерисовывать для экономии времени и вычислений.
Мой MWE выглядит следующим образом:
library(plotly)
library(htmlwidgets)
g <- ggplot(mtcars, aes(x=mpg, y=cyl)) + geom_point()
gP <- ggplotly(g)
gP %>% onRender("
function(el, x) {
myGraph = document.getElementById(el.id);
el.on('plotly_click', function(e) {
console.log(e)
console.log(e.points[0].x)
var trace1 = {
x: [e.points[0].x-.3, e.points[0].x-.3, e.points[0].x+.3, e.points[0].x+.3],
y: [e.points[0].y-.3, e.points[0].y+.3, e.points[0].y-.3, e.points[0].y+.3],
type: 'scatter',
fillColor : 'red',
size: 20
};
Plotly.addTraces(el.id, trace1);
})}
")
Когда пользователь нажимает на любую из 32 черных точек, вокруг окрашенной черной точки рисуются четыре цветные красные точки. Это в основном работает, и если вы нажмете на любую из 32 черных точек данных, вы должны увидеть четыре цветные точки, нарисованные вокруг нее. Тем не менее, мне остается несколько вопросов:
1) Как я могу улучшить это, чтобы четыре цветные точки не были соединены линиями?
2) Как сделать так, чтобы размер и fillColor действительно работали? Когда я изменяю их значения, я не вижу их влияния.
3) Является ли это разумным синтаксисом, чтобы интерактивность и рисование были максимально быстрыми? Я почти уверен, что фоновое изображение не перерисовывается эффективным образом, но хотел бы услышать подтверждение об этом, поскольку я новичок в этом синтаксисе. Если бы я добавил сотни новых точек на верхний слой, это все равно было бы эффективно? Если нет, я был бы признателен за рекомендации по улучшению синтаксиса.
Спасибо.
1 ответ
1) Как я могу улучшить это, чтобы четыре цветные точки не были соединены линиями?
добавлять mode: 'markers'
на ваш trace
объект
2) Как сделать так, чтобы размер и fillColor действительно работали? Когда я изменяю их значения, я не вижу их влияния.
Значения должны быть внутри marker
объект и fillColor
должно быть color
,
marker:
{
color: 'red',
size: 20
}
3) Является ли это разумным синтаксисом, чтобы интерактивность и рисование были максимально быстрыми? Я почти уверен, что фоновое изображение не перерисовывается эффективным образом, но хотел бы услышать подтверждение об этом, поскольку я новичок в этом синтаксисе. Если бы я добавил сотни новых точек на верхний слой, это все равно было бы эффективно? Если нет, я был бы признателен за рекомендации по улучшению синтаксиса.
Это немного основано на мнении. Проблема в том, что вы используете ggplot для создания шаблона, который создает довольно сложный график. С 100 баллами вы получаете довольно некоторую задержку после каждого клика.
Исправление диапазонов оси x/y немного улучшит рисование, потому что график требует изменения размера, если новые значения находятся вне диапазона старых.
gP %>%
layout(
xaxis = list(range = c(8, 35)),
yaxis = list(range = c(3, 9))
)
Если вы можете нарисовать график без использования ggplotly, вы можете создать трассировку только один раз, а затем добавить значения через extendTraces
,
Но я думаю, что это настолько хорошо, насколько это возможно, в конце концов, это библиотека на основе браузера, а не отдельная программа.
library(plotly)
library(htmlwidgets)
g <- ggplot(mtcars, aes(x=mpg, y=cyl)) + geom_point()
gP <- ggplotly(g)
gP %>%
layout(
xaxis = list(range = c(8, 35)),
yaxis = list(range = c(3, 9))
)
gP %>% onRender("
function(el, x) {
myGraph = document.getElementById(el.id);
el.on('plotly_click', function(e)
{
var trace1 = {
x: [],
y: [],
mode: 'markers',
marker: {
color: 'red',
size: 20
}
};
for (var i = 0; i < 100; i+= 1){
trace1.x.push(e.points[0].x + Math.random() - 0.5)
trace1.y.push(e.points[0].y + Math.random() - 0.5)
}
Plotly.addTraces(el.id, trace1);
}
)}
")