如何绘制和擦除以及更改画笔大小和颜色?

问题描述 投票:0回答:1

拖动滑块按钮时,颜色应该出现并改变,但什么也没有发生,屏幕右侧只有一个空白画布。我改变了一些东西,之前它甚至不是屏幕右侧的画布,但现在当有画布时,当我使用滑块选项(如颜色应该出现)时,不会发生任何事情。当我从下拉列表中选择一种颜色并使用滑块时,颜色也会发生变化:

# install.packages(c("shiny", "shinyjs"))

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  titlePanel("Drawing App"),
  sidebarLayout(
    sidebarPanel(
      sliderInput("brushSize", "Brush Size", min = 1, max = 20, value = 5),
      selectInput("brushColor", "Brush Color",
                  choices = c("Black", "Red", "Blue", "Green", "Eraser"),
                  selected = "Black")
    ),
    mainPanel(
      div(id = "canvas", style = "border:1px solid #000; height: 400px;"),
      tags$script('
        var isDrawing = false;
        var context;

        $(document).ready(function(){
          var canvas = document.getElementById("canvas");
          context = canvas.getContext("2d");

          $("#canvas").mousedown(function(e){
            isDrawing = true;
            context.beginPath();
            context.moveTo(e.pageX - canvas.offsetLeft, e.pageY - canvas.offsetTop);
          });

          $("#canvas").mousemove(function(e){
            if(isDrawing){
              var x = e.pageX - canvas.offsetLeft;
              var y = e.pageY - canvas.offsetTop;
              var color = $("#brushColor").val();
              var size = $("#brushSize").val();
              context.lineWidth = size;
              if(color === "Eraser"){
                context.strokeStyle = "#FFF"; // White color for eraser
              } else {
                context.strokeStyle = color.toLowerCase();
              }
              context.lineTo(x, y);
              context.stroke();
            }
          });

          $("#canvas").mouseup(function(){
            isDrawing = false;
          });

          $("#canvas").mouseleave(function(){
            isDrawing = false;
          });

          Shiny.setInputValue("canvasData", canvas.toDataURL());
        });

        Shiny.addCustomMessageHandler("clearCanvas", function(message) {
          context.clearRect(0, 0, canvas.width, canvas.height);
        });
      ')
    )
  )
)

server <- function(input, output, session) {
  observe({
    brush_color <- switch(input$brushColor,
                          "Black" = "black",
                          "Red" = "red",
                          "Blue" = "blue",
                          "Green" = "green",
                          "Eraser" = "white")

    shinyjs::runjs(paste0('context.strokeStyle = "', brush_color, '";'))
  })

  observeEvent(input$canvasData, {
    session$sendCustomMessage("clearCanvas", NULL)
    shinyjs::runjs(paste0('var img = new Image(); img.src = "', input$canvasData, '"; context.drawImage(img, 0, 0);'))
  })
}

shinyApp(ui, server)
r shiny shinyjs
1个回答
0
投票

请注意:

  • 您不能在
    getContext()
    上使用
    div
    ,您必须使用
    canvas
    创建您的
    tags$canvas(height="400px", id="canvas", style="border: 1px solid #000;")
  • 通常需要
    $(document).on("shiny:connected"
    ,否则当您尝试使用
    shiny
    时,
    setInputValue
    可能尚未准备好。
  • 应正确设置
    canvas
    width
    height
    属性:
              canvas.setAttribute("width", canvas.parentNode.offsetWidth); canvas.setAttribute("height", canvas.parentNode.offsetHeight);
  • 我们需要边界
    var bounds = canvas.getBoundingClientRect();
    并访问它们(例如
    context.moveTo(e.pageX - bounds.left, e.pageY - bounds.top);
    ),否则光标位置将不匹配。

然后就可以了。

library(shiny)
library(shinyjs)

ui <- fluidPage(
    useShinyjs(),
    titlePanel("Drawing App"),
    sidebarLayout(
        sidebarPanel(
            sliderInput("brushSize", "Brush Size", min = 1, max = 20, value = 5),
            selectInput("brushColor", "Brush Color",
                        choices = c("Black", "Red", "Blue", "Green", "Eraser"),
                        selected = "Black")
        ),
        mainPanel(
            tags$canvas(
                height="400px", id="canvas", style="border: 1px solid #000;"
            ),
            tags$script(HTML('
        var isDrawing = false;
        var context;

        $(document).on("shiny:connected", function(){
          var canvas = document.getElementById("canvas");
          canvas.setAttribute("width", canvas.parentNode.offsetWidth);
          canvas.setAttribute("height", canvas.parentNode.offsetHeight);
          context = canvas.getContext("2d");
          var bounds = canvas.getBoundingClientRect();

          $("#canvas").mousedown(function(e){
            isDrawing = true;
            context.beginPath();
            context.moveTo(e.pageX - bounds.left, e.pageY - bounds.top);
          });

          $("#canvas").mousemove(function(e){
            if(isDrawing){
              var x = e.pageX - bounds.left;
              var y = e.pageY - bounds.top;
              var color = $("#brushColor").val();
              var size = $("#brushSize").val();
              context.lineWidth = size;
              if(color === "Eraser"){
                context.strokeStyle = "#FFF"; // White color for eraser
              } else {
                context.strokeStyle = color.toLowerCase();
              }
              context.lineTo(x, y);
              context.stroke();
            }
          });

          $("#canvas").mouseup(function(){
            isDrawing = false;
          });

          $("#canvas").mouseleave(function(){
            isDrawing = false;
          });

          Shiny.setInputValue("canvasData", canvas.toDataURL());
        });

        Shiny.addCustomMessageHandler("clearCanvas", function(message) {
          context.clearRect(0, 0, canvas.width, canvas.height);
        });
      '))
        )
    )
)

server <- function(input, output, session) {
    observe({
        brush_color <- switch(input$brushColor,
                              "Black" = "black",
                              "Red" = "red",
                              "Blue" = "blue",
                              "Green" = "green",
                              "Eraser" = "white")
        
        shinyjs::runjs(paste0('context.strokeStyle = "', brush_color, '";'))
    })
    
    observeEvent(input$canvasData, {
        session$sendCustomMessage("clearCanvas", NULL)
        shinyjs::runjs(paste0('var img = new Image(); img.src = "', input$canvasData, '"; context.drawImage(img, 0, 0);'))
    })
}

shinyApp(ui, server)
© www.soinside.com 2019 - 2024. All rights reserved.