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

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

问题描述

我有一个 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)

推荐答案

您可以使用 touch-action CSS 属性:

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

#plot {
  touch-action: none;
}

将触摸事件转换为鼠标事件有点棘手,但您可以监听诸如 touchstarttouchmovetouchend 之类的触摸事件并进行模拟JavaScript 中的等效鼠标事件.请参阅 https://developer.mozilla.org/en-US/docs/Web/API/Touch_events/Using_Touch_Eventshttps://javascript.info/dispatch-eventsa> 了解更多信息.

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天全站免登陆