在智能手机上使用时,闪亮的交互式绘图无法理解手指的移动 [英] used on a smartphone, shiny interactive plot doesn't understand finger movements

查看:74
本文介绍了在智能手机上使用时,闪亮的交互式绘图无法理解手指的移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个R-Shiny应用程序,该应用程序的图实现了交互式操作:单击,悬停(悬停将鼠标移到该图上,可以通过闪亮检测到)。为了提出一个想法,我在下面发布了一个简化的闪亮应用程序,该程序具有对我来说有问题的功能,即交互式绘图。 (摘自我的老答案此处

I have a R-Shiny application with a plot that implements interactive actions: click, hovering (hovering is passing the mouse over the plot, which can be detected by shiny). To give an idea, I post below a simplified shiny-app with the functionality that is problematic to me, the interactive drawing plot. (it's taken from an old answer of mine here)

它实际上工作正常,但是我需要人们从他们的智能手机中使用它。问题是:我们在智能手机中所做的手指移动被手机解释为页面上的缩放或页面上的滚动,而不是鼠标选择或鼠标移动情节(悬停)。

It's actually working fine, however I need people to use it from their smartphones. The problem: the finger movements we do in the smartphone are interpreted by the phone as zooming on the page or scrolling on the page, and not as mouse selection or mouse movement over the the plot (hovering).

我是否可以在应用上实现对代码的修改(java?CSS?),以将触摸事件转换为鼠标事件,或者在

Is there a modification of the code (java? CSS?) that I can implement on the app to turn touch events into mouse events, or an option/gesture on the smartphone to enable a mouse-like movement?

非常感谢。代码:

library(shiny)
ui <- fluidPage(
  h4("Click on plot to start drawing, click again to pause"),
  sliderInput("mywidth", "width of the pencil", min=1, max=30, step=1, value=10),
  actionButton("reset", "reset"),
  plotOutput("plot", width = "500px", height = "500px",
             hover=hoverOpts(id = "hover", delay = 100, delayType = "throttle", clip = TRUE, nullOutside = TRUE),
             click="click"))
server <- function(input, output, session) {
  vals = reactiveValues(x=NULL, y=NULL)
  draw = reactiveVal(FALSE)
  observeEvent(input$click, handlerExpr = {
    temp <- draw(); draw(!temp)
    if(!draw()) {
      vals$x <- c(vals$x, NA)
      vals$y <- c(vals$y, NA)
    }})
  observeEvent(input$reset, handlerExpr = {
    vals$x <- NULL; vals$y <- NULL
  })
  observeEvent(input$hover, {
    if (draw()) {
      vals$x <- c(vals$x, input$hover$x)
      vals$y <- c(vals$y, input$hover$y)
    }})
  output$plot= renderPlot({
    plot(x=vals$x, y=vals$y, xlim=c(0, 28), ylim=c(0, 28), ylab="y", xlab="x", type="l", lwd=input$mywidth)
  })}
shinyApp(ui, server)


推荐答案

您可以使用 触摸操作 CSS属性:

You can disable panning/zoom gestures on the plot using the touch-action CSS property:

#plot {
  touch-action: none;
}

将触摸事件转换为鼠标事件有点棘手,但您可以听触摸事件,例如 touchstart touchmove touchend 并模拟等效项JavaScript中的鼠标事件。请参见 https://developer.mozilla.org/zh-CN / docs / Web / API / Touch_events / Using_Touch_Events https://javascript.info/dispatch-events 有关更多信息。

Turning touch events into mouse events is a little trickier, but you could listen to touch events like touchstart, touchmove, touchend and simulate equivalent mouse events in JavaScript. See https://developer.mozilla.org/en-US/docs/Web/API/Touch_events/Using_Touch_Events and https://javascript.info/dispatch-events for more info.

这并不完美,但我试了一下。我禁用了情节上的触摸手势,并添加了一个脚本,该脚本将 touchmove 转换为 mousemove ,并告诉服务器何时启动绘图(在 touchstart 上)并停止绘图(在 touchend 上)。

It's not perfect, but I gave it a shot. I disabled touch gestures on the plot and added a script that converts touchmove to mousemove, and tells the server when to start drawing (on touchstart) and stop drawing (on touchend).

library(shiny)

ui <- fluidPage(
  h4("Click on plot to start drawing, click again to pause"),
  sliderInput("mywidth", "width of the pencil", min=1, max=30, step=1, value=10),
  actionButton("reset", "reset"),
  plotOutput("plot", width = "400px", height = "400px",
             hover=hoverOpts(id = "hover", delay = 100, delayType = "throttle", clip = TRUE, nullOutside = TRUE),
             click="click"),
  tags$head(
    tags$script("
      $(document).ready(function() {
        var plot = document.getElementById('plot')

        plot.addEventListener('touchmove', function (e) {
          var touch = e.changedTouches[0];
          var mouseEvent = new MouseEvent('mousemove', {
            view: window,
            bubbles: true,
            cancelable: true,
            screenX: touch.screenX,
            screenY: touch.screenY,
            clientX: touch.clientX,
            clientY: touch.clientY
          })
          touch.target.dispatchEvent(mouseEvent);
          e.preventDefault()
        }, { passive: false });

        plot.addEventListener('touchstart', function(e) {
          Shiny.onInputChange('draw', true)
          e.preventDefault()
        }, { passive: false });

        plot.addEventListener('touchend', function(e) {
          Shiny.onInputChange('draw', false)
          e.preventDefault()
        }, { passive: false });
      })
    "),
    tags$style("#plot { touch-action: none; }")
    )
)

server <- function(input, output, session) {
  vals = reactiveValues(x=NULL, y=NULL)
  draw = reactiveVal(FALSE)

  observeEvent(input$click, {
    draw(!draw())
    vals$x <- append(vals$x, NA)
    vals$y <- append(vals$y, NA)
  })

  observeEvent(input$draw, {
    draw(input$draw)
    vals$x <- append(vals$x, NA)
    vals$y <- append(vals$y, NA)
  })

  observeEvent(input$reset, handlerExpr = {
    vals$x <- NULL; vals$y <- NULL
  })

  observeEvent(input$hover, {
    if (draw()) {
      vals$x <- c(vals$x, input$hover$x)
      vals$y <- c(vals$y, input$hover$y)
    }
  })

  output$plot= renderPlot({
    plot(x=vals$x, y=vals$y, xlim=c(0, 28), ylim=c(0, 28), ylab="y", xlab="x", type="l", lwd=input$mywidth)
  })
}

shinyApp(ui, server)

这篇关于在智能手机上使用时,闪亮的交互式绘图无法理解手指的移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆