更改要在 R Shiny 中绘制的变量时,防止重置绘图选定的迹线

2023-12-02

我正在尝试制作一个闪亮的应用程序,它由侧边栏面板和绘图组成。在面板中,我使用单选按钮来选择应绘制哪个 ID。我还有多个变量,用户可以使用情节图例关闭和打开这些变量。

我希望应用程序首次打开时绘图为空。为此,我正在使用visible = "legendonly"在我的阴谋中。但是,当侧边栏面板中的 ID 更改时,我想保留用户已经激活的痕迹(通过在图例中单击它们);然而,由于情节每次都会重新生成,因此它再次使用visible = "legendonly"选项并导致绘图重置。

当在侧边栏面板中选择不同的选项时,有没有办法保留痕迹(仅保留已选择的痕迹)?

请参阅下面的可重现示例;请注意,我使这个示例在本地运行。您需要将数据和包分别加载到 R 会话中。数据可以在问题底部找到。

library(shiny)
library(plotly)
library(lubridate)

### Read mdata into your R session
# UI 

uix <- shinyUI(pageWithSidebar(
  headerPanel("Data"),
  sidebarPanel(
    radioButtons('vars', 'ID', 
                 c("1", "2")),
    helpText('Select an ID.')
  ),
  mainPanel(
    h4("Plot"),
    plotlyOutput("myPlot")
  )
)
)
# SERVER 

serverx <- function(input, output) {
 
  #load("Data/mdata.RData") #comment out this part and load data locally
  
  # a large table, reative to input$show_vars
  output$uteTable = renderDataTable({
    ute[, input$show_vars, drop = FALSE]
  })
  
  output$myPlot = renderPlotly(
    {
      p <- plot_ly() %>% 
        layout(title = "Title", xaxis = list(tickformat = "%b %Y", title = "Date"),
               yaxis = list(title = "Y"))
      
      ## Add the IDs selected in input$vars
      for (item in input$vars) {
        mdata %>% 
          mutate(Date = make_date(Year, Month, 15)) %>% 
          filter(ID == item) -> foo
        
        p <- add_lines(p, data = foo, x = ~Date, y = ~Value, color = ~Variable, visible = "legendonly",
                       evaluate = TRUE)
        
        p <- p %>% layout(showlegend = TRUE,
                          legend = list(orientation = "v",   # show entries horizontally
                                        xanchor = "center",  # use center of legend as anchor
                                        x = 100, y=1))        
      }
      print(p)
    })
}
shinyApp(uix, serverx)

Created on 2020-06-12 by the reprex package (v0.3.0)

问: 可以保留吗Var1更改为时跟踪ID == 2?

Idea:我想如果我能改变的话这是可能的visible = 'legendonly to TRUE就在应用程序部署之后,因此它仅适用于该图的第一个示例。或许,我需要改变evaluate to FALSE以及。

Data:

mdata <- structure(list(Year = c(2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L), Month = c(1L, 1L, 
1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 5L, 5L, 
5L, 5L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 8L, 8L, 8L, 8L, 9L, 9L, 
9L, 9L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 
12L), Variable = c("Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2"), ID = c(1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 
2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 
1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2), Value = c(187.797761979167, 
6.34656438541666, 202.288468333333, 9.2249309375, 130.620451458333, 
4.61060465625, 169.033213020833, 7.5226940625, 290.015582677083, 
10.8697671666667, 178.527960520833, 7.6340359375, 234.53493728125, 
8.32400878125, 173.827054583333, 7.54521947916667, 164.359205635417, 
5.55496292708333, 151.75458625, 6.361610625, 190.124467760417, 
6.45046077083333, 191.377006770833, 8.04720916666667, 170.714612604167, 
5.98860073958333, 210.827157916667, 9.46311385416667, 145.784868927083, 
5.16647911458333, 159.9545675, 6.7466725, 147.442681895833, 5.43921594791667, 
153.057018958333, 6.39029208333333, 165.6476956875, 5.63139815625, 
197.179256875, 8.73210604166667, 148.1879651875, 5.58784840625, 
176.859451354167, 7.65670020833333, 186.215496677083, 7.12404453125, 
219.104379791667, 9.39468864583333)), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -48L), groups = structure(list(
    Year = 2015L, .rows = list(1:48)), row.names = c(NA, -1L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE))

以下用途plotlyProxy替换现有绘图对象(和迹线)的数据,从而避免重新渲染绘图。这种方法比重新渲染更快。

library(shiny)
library(plotly)
library(lubridate)
# UI
uix <- shinyUI(pageWithSidebar(
  headerPanel("Data"),
  sidebarPanel(
    radioButtons('myID', 'ID', 
                 c("1", "2")),
    helpText('Select an ID.')
  ),
  mainPanel(
    h4("Plot"),
    plotlyOutput("myPlot")
  )
)
)
# SERVER
serverx <- function(input, output, session) {

  output$myPlot = renderPlotly({
    p <- plot_ly() %>% 
      layout(title = "Title", xaxis = list(tickformat = "%b %Y", title = "Date"),
             yaxis = list(title = "Y"))
    
    mdata %>% 
      mutate(Date = make_date(Year, Month, 15)) %>% 
      filter(ID == 1) -> IDData
    
    p <- add_lines(p, data = IDData, x = ~Date, y = ~Value, 
                                     color = ~Variable, visible = "legendonly")
    
    p <- p %>% layout(showlegend = TRUE,
                      legend = list(orientation = "v",   # show entries horizontally
                                    xanchor = "center",  # use center of legend as anchor
                                    x = 100, y=1))        
    p
  })
  
  
  myPlotProxy <- plotlyProxy("myPlot", session)
  
  observe({
    mdata %>%
      mutate(Date = make_date(Year, Month, 15)) %>%
      filter(ID == input$myID) -> IDData
    
    req(IDData)
    uniqueVars <- unique(IDData$Variable)
    
    for(i in seq_along(uniqueVars)){
      IDData %>% filter(Variable == uniqueVars[i]) -> VarData
      plotlyProxyInvoke(myPlotProxy, "restyle", list(x = list(VarData$Date), 
                                                     y = list(VarData$Value)), list(i-1))
    }
  })
  
}
shinyApp(uix, serverx)

result

有关更多信息,请参阅章节“17.3.1 部分情节更新”情节书, 情节地功能参考 and 这个答案.

Data:

### Read mdata into your R session
mdata <- structure(list(Year = c(2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 2015L, 
2015L, 2015L, 2015L, 2015L, 2015L, 2015L), Month = c(1L, 1L, 
1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 5L, 5L, 
5L, 5L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 8L, 8L, 8L, 8L, 9L, 9L, 
9L, 9L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 
12L), Variable = c("Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1", "Var1", 
"Var2", "Var2"), ID = c(1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 
2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 
1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2), Value = c(187.797761979167, 
6.34656438541666, 202.288468333333, 9.2249309375, 130.620451458333, 
4.61060465625, 169.033213020833, 7.5226940625, 290.015582677083, 
10.8697671666667, 178.527960520833, 7.6340359375, 234.53493728125, 
8.32400878125, 173.827054583333, 7.54521947916667, 164.359205635417, 
5.55496292708333, 151.75458625, 6.361610625, 190.124467760417, 
6.45046077083333, 191.377006770833, 8.04720916666667, 170.714612604167, 
5.98860073958333, 210.827157916667, 9.46311385416667, 145.784868927083, 
5.16647911458333, 159.9545675, 6.7466725, 147.442681895833, 5.43921594791667, 
153.057018958333, 6.39029208333333, 165.6476956875, 5.63139815625, 
197.179256875, 8.73210604166667, 148.1879651875, 5.58784840625, 
176.859451354167, 7.65670020833333, 186.215496677083, 7.12404453125, 
219.104379791667, 9.39468864583333)), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -48L), groups = structure(list(
    Year = 2015L, .rows = list(1:48)), row.names = c(NA, -1L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE))

Edit:

以下是使用单个更新跟踪数据的替代服务器函数plotlyProxyInvoke调用(避免 for 循环):

serverx <- function(input, output, session) {
  output$myPlot = renderPlotly({
    p <- plot_ly() %>% 
      layout(title = "Title", xaxis = list(tickformat = "%b %Y", title = "Date"),
             yaxis = list(title = "Y"))
    
    mdata %>% 
      mutate(Date = make_date(Year, Month, 15)) %>% 
      filter(ID == 1) -> IDData
    
    p <- add_lines(p, data = IDData, x = ~Date, y = ~Value, 
                   color = ~Variable, visible = "legendonly")
    
    p <- p %>% layout(showlegend = TRUE,
                      legend = list(orientation = "v",   # show entries horizontally
                                    xanchor = "center",  # use center of legend as anchor
                                    x = 100, y=1))        
    p
  })
  
  myPlotProxy <- plotlyProxy("myPlot", session)
  
  IDDataList <- split(mdata %>% mutate(Date = make_date(Year, Month, 15)), ~ ID + Variable)
  
  observe({
    selectedIDDataList <- setNames(lapply(list("Date", "Value"), function(i){
      unname(lapply(IDDataList[paste0(input$myID, ".Var", c(1L, 2L))], function(j){j[[i]]}))
    }), c("x", "y"))
    plotlyProxyInvoke(myPlotProxy, "restyle", selectedIDDataList, seq_along(selectedIDDataList)-1)
  })
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更改要在 R Shiny 中绘制的变量时,防止重置绘图选定的迹线 的相关文章

  • R - 正则表达式错误(PCRE 版本)

    我正在尝试使用koRpus在 R 中在运行 RHEL6 的 Linux 服务器上进行词形还原 上周 当我安装了 MRO Microsoft R Open 3 2 3 时 下面的代码效果很好 library koRpus lw c danci
  • 将密度曲线拟合到 R 中的直方图

    R中有没有可以将曲线拟合到直方图的函数 假设您有以下直方图 hist c rep 65 times 5 rep 25 times 5 rep 35 times 10 rep 45 times 4 看上去很正常 但其实是歪曲的 我想拟合一条倾
  • 如何生成向量的所有组合[重复]

    这个问题在这里已经有答案了 假设我有 3 个绿球 2 个橙球和 8 个黄球 我想订购它们 鉴于所有相同颜色的球都是相同的 如何生成所有可能的序列 在 R 中 使用gregmisc 我可以 balls lt c orange orange g
  • R 中的 NA 替换函数

    我正在尝试替换矩阵中的 NA mat 零 我在用着mat is na mat lt 0 当我有 18946 个变量的 94531 个观察值或更小的矩阵时 效果很好 但我在 22752 个变量的 112039 个观察值的矩阵上尝试它 R 显示
  • 分离并重新附加“tools:rstudio”

    又名玩火 以下不起作用 rstd obj lt as environment tools rstudio detach tools rstudio attach rstd obj name tools rstudio 好吧 它似乎有效 但随
  • 如何让R使用所有处理器?

    我有一台运行 Windows XP 的四核笔记本电脑 但查看任务管理器 R 似乎一次只使用一个处理器 如何让 R 使用全部四个处理器并加速我的 R 程序 我有一个基本系统 我使用它在 for 循环上并行化我的程序 一旦您了解需要做什么 此方
  • 使用 R 的 flextable 包时,有没有办法将传递给 add_header_lines() 的字符串部分加粗

    我正在使用我喜欢的 flextable 包为 Word 文档创建几个表格 但是 我在将表格标题中的部分文本加粗时遇到了一些麻烦 例如 我希望标题为 Table 1 我的表格标题的其余部分 而不是 表 1 我的表格标题的其余部分 I 找到这个
  • 如何使用 R 中带引号的字符值内的序列读取 CSV?

    这是一个包含两个字符列的 CSV 文件 key value a 所有字符值都用双引号引起来 并且有一个顺序 在值之一内 转义引号加分隔符 我无法通过 read csv readr 中的 read csv 或 data table 中的 fr
  • dplyr,do(),从模型中提取参数而不丢失分组变量

    R 帮助中关于 do 的示例略有不同 by cyl lt group by mtcars cyl models lt by cyl gt do mod lm mpg disp data coefficients lt models gt d
  • 如何获得属于五分位数的x?

    我正在大学学习使用 R 进行计量经济学项目 所以请原谅我的笨拙 基本上 使用并给出 一个矩阵 股票价格 行 天 列 公司股票价格 另一个矩阵 市值 行 天 列 公司市值 我必须收集第三个矩阵每天观察的属于市值分布第一五分位数的股票价格 然后
  • R.matlab/readMat:readTag(this) 中出错

    我正在尝试使用 R matlab 将 matlab 文件读入 R 但遇到此错误 require R matlab r lt readMat file mat verbose T Trying to read MAT v5 file stre
  • 当每个记录都是一个段落并且某些记录有 4 个字段而其他记录有 6 个字段时,如何将文本文件读入 R

    如何读取文本文件 其中每条记录都是一个段落 每个换行符表示单独的字段 复杂的是 有些记录有 4 行 有些记录有 6 行 当字段数量的差异为 1 时 DWin 解决了我的问题 但当字段数量差异为 2 时 一切都崩溃了 你可以有一个在这里看看他
  • 解析,用三点参数替换

    让我们考虑一个典型的deparse substitute R call f1 lt function u x y print deparse substitute x varU vu varX vx varY vy f1 u varU x
  • 使用outer代替expand.grid

    我正在寻找尽可能快的速度并留在基地做该做的事expand grid做 我用过outer为过去类似的目的创建一个向量 像这样的东西 v lt outer letters LETTERS paste0 unlist v lower tri v
  • R - 通过覆盖和递归合并列表

    假设我有两个带有名字的列表 a list a 1 b 2 c list d 1 e 2 d list a 1 b 2 b list a 2 c list e 1 f 2 d 3 e 2 我想递归地合并这些列表 如果第二个参数包含冲突的值 则
  • 在 R 中使用 Huggingface Transformer 模型

    我正在尝试在 R 中使用不同的 Huggingface 模型 这是通过 reticulate 导入 Transformer 包来实现的 谢谢 https rpubs com eR ic transfoRmers https rpubs co
  • Python 3d 绘图设置固定色阶

    我正在尝试绘制两个 3d 数组 第一个数组的 z 值在范围内 0 15 0 15 第二个来自 0 001 0 001 当我绘图时 色标自动遵循数据范围 如何设置自定义比例 我不想看到 0 001 的浅色 而应该看到 0 15 的浅色 如何修
  • 如何在R中同时对三个字段进行网络分析

    如何在 R 中同时对三个字段进行网络分析 下面是示例数据以及desired output在最后一栏中 df lt data frame stringsAsFactors FALSE id 1 c ABC ABC BCD CDE DEF EF
  • 16 位以上整数的计算

    我有两个大整数 两者都超过 16 位 确切地说是 20 位 而且我知道由于双精度浮点运算 我在使用这些数字进行计算甚至将它们存储在变量中 独立于编程语言 时受到限制 不过 我想也许gmp图书馆应该处理它们 但不幸的是它没有 可以计算更大的整
  • 如何匹配 R 中的所有匹配项?

    我有 1000 个名字的列表 说A 我还有另外 5 个名字的清单 说B 我想找出这5个名字出现在1000个号码列表中的第几行 例如 Amy 在 A 中可以出现 25 次 B 里有艾米 我想知道 Amy 出现在 A 中的哪些行 我以前使用过

随机推荐

  • 如何在recycler视图中访问MainActivity的组件来制作onclick监听器?

    我创建了类似 YouTube 的应用程序 其中包含一个视频视图 顶部 和回收器视图 视频视图下方 我陷入困境 我想在 recyclerview 项目上创建 onclicklistner 并更改视频路径来更改视频 但是如何访问适配器类中的 v
  • PHP 中的 SFTP - 未定义的常量 CURLOPT_PROTOCOLS 和 CURLPROTO_SFTP?

    从我的 php 脚本中 我需要能够通过 sftp 将 csv 文件上传到远程服务器 我遵循了这个问题的公认答案 从 PHP 内部进行 SFTP 这是我的代码的样子
  • 使用公式将 Excel 子集列转换为数组

    我需要将帐号放入一个数组中 该数组在列选择上指示为 1 预期结果是 FD 002 17 FD 004 17 我计划在名称范围中使用它 子集感兴趣的表 我尝试使用 INDEX B2 B6 MATCH 1 A2 A6 1 但这失败了Match不
  • openFileInput() 和/或 openFileOutput() I/O 流默默失败

    我一直在研究 android 平台 研究不同的数据存储方式 现在我正在使用Context方法openFileInput and openFileOutput 正如这两种方法的文档告诉我的那样 我创建了一个名为 default 的文件 这是一
  • 几分钟后服务自动停止

    我正在创建一个服务 当活动处于后台以及整个应用程序被销毁时 该服务应该可以工作 我每隔 1 分钟调用一次服务中的位置坐标 但是 当我尝试这样做时 该服务会在 12 15 分钟后自动关闭 我希望该服务能够无休止地工作 直到并且除非它被用户交互
  • 定制系列化

    我有一些必须序列化的对象 class Displayable string name Sprite icon The icon字段需要自定义序列化 因为Sprites 已经被序列化 在不同的文件中 具有自己的格式 由游戏引擎 我只需要存储一
  • Jquery - 在悬停时添加类

    我想要当鼠标继续运行时lijquery 向元素添加一个类 ul class menu li Menu Item li li Menu Item li li Menu Item li li Menu Item li ul
  • Galaxy Note 5:自动降低密度

    我创建了一个依赖某些屏幕指标来运行的应用程序 它在除 Galaxy Note 5 之外的所有设备上都能正常工作 在 Note 5 上 它报告的屏幕尺寸为 1080x1920 而实际屏幕尺寸为 1440x2560 我还在 logcat 中看到
  • 使用泛型返回文字字符串或来自 Dictionary

    我想这一次我超越了自己 请随意编辑标题 我也想不出一个好的标题 我正在从一个文件中读取内容 然后该文件中将包含一个字符串 因为它就像一个 xml 文件 但文件中将是一个文字值或一个 命令 用于从 workContainer 获取值 so
  • 为什么这个巴特沃斯滤波器在 R 和 Matlab 中呈现不同的结果?

    我试图对 R 中的数据使用 20Hz 低通滤波器 但是当我使用 filtfilt 函数时 该图与 matlab 中的不同 我在 R 中使用以下代码 fc lt 20 fs lt 100 Wn lt pi fc 2 fs testar lt
  • 如何根据滚动位置缩小图像宽度

    我正在寻找基于滚动缩小徽标 到目前为止 我有这样的事情 logoSize function var headerOffset window height 650 var maxScrollDistance 1300 window scrol
  • 多租户Asp.net Core网站中基于参数的JWT认证

    我在 net core 2 1 网站中使用基于 JWT 的身份验证 目前这工作正常 现在 我必须创建一个 API 多租户 并且每个租户都将拥有自己的密钥 租户 ID 将作为参数传递给 API Authorize HttpGet tenant
  • 每次更改选项卡时选项卡片段都会获取数据

    活动配置文件 xml
  • 使用替换值的平面数组替换二维数组中的列值

    我有一个这种格式的二维数组 oldArr 0 gt color gt red shape gt circle size gt small 1 gt color gt green shape gt square size gt large 2
  • 使用 ncurses 创建一个函数来检查 Unix 中的按键情况

    我一直在寻找相当于kbhit 我读过几个关于这个主题的论坛 大多数似乎都建议使用 ncurses 我应该如何使用 ncurses 检查 C 中是否按下了某个键 功能getch ncurses 提供从窗口读取一个字符 我想写一个函数 只检查是
  • Laravel dusk 断言 404 错误

    我正在尝试使用 laravel dusk 来测试 404 未找到错误 特别是在加载图像时 阅读 laravel dusk 文档后 我发现没有断言可以帮助我测试是否发生 404 异常 有没有一种好的方法可以通过浏览器测试来了解资源是否加载失败
  • CSS、JS 和图像无法以漂亮的 url 显示

    我正在尝试通过 htaccess 文件重写 URL 以便以下 URL www domain com subfolder index php key 可以通过以下方式访问 www domain com subfolder index php
  • YouTube C# API V3,如何恢复中断的上传?

    我不知道如何在 C YouTube API V3 中恢复中断的上传 我现有的代码使用 V1 并且工作正常 但我正在切换到 V3 如果我调用 UploadAsync 而不更改任何内容 它将从头开始 使用 Fiddler 我可以看到此处给出的协
  • 80286:乘以 10 最快的方法是什么?

    要将一个数字乘以 2 的任意倍数 我将对其进行多次移位 有没有这样的技术可以在更少的周期内将一个数字乘以 10 80286 没有随 80386 一起引入的桶形移位器 根据 Microsoft Macro Assembler 5 0 文档 1
  • 更改要在 R Shiny 中绘制的变量时,防止重置绘图选定的迹线

    我正在尝试制作一个闪亮的应用程序 它由侧边栏面板和绘图组成 在面板中 我使用单选按钮来选择应绘制哪个 ID 我还有多个变量 用户可以使用情节图例关闭和打开这些变量 我希望应用程序首次打开时绘图为空 为此 我正在使用visible legen