【问题标题】:How to arrange HTML Widgets inside of a RMarkdown Document (PDF, HTML)如何在 RMarkdown 文档(PDF、HTML)中排列 HTML 小部件
【发布时间】:2017-01-26 12:57:18
【问题描述】:

我在R notebook 工作,想用它来创建两个输出:HTML 文档和 PDF 文档。

我的分析包括传单地图(html 小部件),这在我将笔记本编入 PDF 文档时会导致问题。感谢webshot 函数现在包含在knitr 包中,“knitr 将尝试使用 webshot 包自动为 HTML 小部件生成静态屏幕截图”(https://github.com/yihui/knitr/blob/master/NEWS.md)。

当我的输出是一系列堆叠在一起的传单地图时,这很好用,但我想以更简洁的行排列将这些地图组合在一起(见下图)。

这是我的 R 笔记本的可重现示例:gist

不幸的是,当我尝试将其编入 PDF 文档时,我收到以下错误消息:

Error: Functions that produce HTML output found in document targeting latex output.
Please change the output type of this document to HTML. Alternatively, you can allow
HTML output in non-HTML formats by adding this option to the YAML front-matter of
your rmarkdown file:

  always_allow_html: yes

Note however that the HTML output will not be visible in non-HTML formats.

如何在 PDF 文档中获得这种单行排列?

【问题讨论】:

    标签: r leaflet knitr r-markdown htmlwidgets


    【解决方案1】:

    虽然选择的答案确实解决了我的问题,但我决定采用稍微不同的方法。

    我仍然调整 CSS 样式,但我没有使用针对所有 .leaflet 元素的 JS 脚本,而是将每个传单 htmlwidget 传递给一个名为 styleWidget 的辅助函数,该函数单独调整 CSS。这个函数解释了here,但我还是会在下面添加它的定义:

    styleWidget <- function(hw=NULL, style="", addl_selector="") {
            stopifnot(!is.null(hw), inherits(hw, "htmlwidget"))
    
            # use current id of htmlwidget if already specified
            elementId <- hw$elementId
            if(is.null(elementId)) {
                    # borrow htmlwidgets unique id creator
                    elementId <- sprintf(
                            'htmlwidget-%s',
                            htmlwidgets:::createWidgetId()
                    )
                    hw$elementId <- elementId
            }
    
            htmlwidgets::prependContent(
                    hw,
                    htmltools::tags$style(
                            sprintf(
                                    "#%s %s {%s}",
                                    elementId,
                                    addl_selector,
                                    style
                            )
                    )
            )
    }
    

    这改进了 Martin 的解决方案,因为它提供了更多控制权——例如,我现在可以将第三张地图的 stye 更改为 float: none;,这样地图旁边就不会显示以下元素。 styleWidget 函数可用于修改 any htmlwidget(虽然不是 Shiny 小部件)的 CSS,使其成为工具箱中一个很好的通用工具。

    【讨论】:

      【解决方案2】:

      如果我对您的理解正确,那么您所要做的就是添加一些块选项。这里的关键是选项fig.show='hold',它决定了块中的所有图都将被收集并一起显示在块的最后。

      ---
      title: "R Notebook"
      output:
        pdf_document: 
          keep_tex: yes
        html_notebook: default
      ---
      
      ###Default Arrangement
      ```{r, echo=FALSE,message=FALSE, fig.height=4, fig.width=2, fig.show='hold'}
      #devtools::install_github("wch/webshot")
      
      library(leaflet)
      library(htmltools)
      library(RColorBrewer)
      
      m1 <- leaflet(quakes) %>% 
              addTiles() %>% 
              addMarkers(lng=174.768, lat=-36.852)
      
      m2 <- leaflet(quakes) %>% 
              addProviderTiles("Esri.WorldGrayCanvas") %>% 
              addMarkers(lng=174.768, lat=-36.852)
      
      m3 <- leaflet(quakes) %>%
              addProviderTiles("Stamen.Toner") %>%
              addMarkers(lng=174.768, lat=-36.852)
      m1
      m2
      m3
      ```
      

      如果您希望 pdf 和 html 输出都采用这种格式,您可以将此脚本添加到 Rmd 文档的正文中(不在块内):

      <script>
        $(document).ready(function() {
          $('.leaflet').css('float','left');
        });
      </script>
      

      尝试通过块选项 out.extra 添加这个 CSS sn-p 不起作用,因为 LaTeX 不知道如何处理 CSS。虽然 JS 代码在编译成 pdf 时会被忽略。

      【讨论】:

      • 这正是我要寻找的 PDF 输出!不幸的是,现在 HTML 输出以堆叠格式显示地图。有没有办法在这里两全其美(即 pdf 和 html 文档都以单行排列显示地图)?
      • 我试了一下。更新了我的答案。
      • 将脚本添加到 R 块?到一个 js 块?
      • FWIW,在library(mapview) 我们有函数latticeView 以格状方式排列多个地图,sync 用于同步多个地图;有关示例,请参见 environmentalinformatics-marburg.github.io/mapview/sync/…。不过可能只适用于 html 文档。
      猜你喜欢
      • 2021-07-20
      • 1970-01-01
      • 2021-02-11
      • 1970-01-01
      • 2023-03-25
      • 2015-10-23
      • 2015-10-05
      • 2021-12-09
      • 2015-12-02
      相关资源
      最近更新 更多