第 2 章 HTML空间尺寸调整

2.1 概述

在HTML控件的工作中,就像R中的绘图(plot),HTML控件智能的将他们自己的大小放在容器中,无论是在Rstudio Viewer中,knitr中的图还是在Shiny UI中的面板。htmlwidgets框架提供了一种丰富的机制来指定控件的大小调整行为。

这种大小调整机制是为了解决影响控件的自然尺寸的以下约束:

  • The kind of widget it is.有些控件可能仅仅需要设计成小的,固定尺寸(例如sparkline),而有些控件可能需要基于像素点做不断地调整(例如network graphs)

  • The context into which the widget is rendered.有些控件在R Markdown中看起来是以 \(980px \times 480px\),相同的控件在Rstudio的Viewer中看起来要小的多。

分两步处理控件的大小:

  1. 首先为控件指定大小调整策略,这是通过createWidget函数中的sizingPolicy参数实现的。大多数控件可以接受默认的大小调整策略((或者只覆盖其中的一个或两个方面)并获得满意的大小调整行为(详见下文)。)

  2. 框架使用大小调整策略来计算给定的窗口中所呈现的窗口的正确宽度和高度。然后将其大小信息传递给控件JavaScript绑定的初始化和调整大小方法。控件将大小的信息传递给底层的JS库。

2.2 指定大小调整策略

默认HTML窗口大小调整策略使用与R图相同大小的语义来处理控件。当在R控制台上打印时,窗口小部件显示在RStudio Viewer中,并且大小以填充查看器窗格(模数任何填充)。当在R Markdown文档中呈现时,控件大小基于默认的图片文件的大小。

需要注意的是对于大多数的控件来说默认的大小是很不错的选择,你不需要去创建一个大小调整的策略。如果你想轻微的修改大小策略,使得与默认的不同,那么你可以调用sizingPolicy函数,然后把结果传递给createWidget函数。例如:

htmlwidgets::createWidget(
  "sigma", 
  x, 
  width = width, 
  height = height,
  sizingPolicy = htmlwidgets::sizingPolicy(
    viewer.padding = 0,
    viewer.paneHeight = 500,
    browser.fill = TRUE
  )
)

2.2.1 例子

networkD3包对所有的控件直接使用了自定义的大小策略,simpleNetwork控件消除填充(因为D3已经提供填充),并且指定当它在一个独立的Web浏览器中显示时,它希望填充尽可能多的空间:

sizingPolicy(padding = 0, browser.fill = TRUE)

sankeyNetwork控件需要比Rstudio Viewer提供的更多的空间或典型的knitr图片,因此它禁用了那些自动调整大小的行为。针对于knitr文档他还提供了一个恰当的默认的宽和高:

sizingPolicy(viewer.suppress = TRUE,
             knitr.figure = FALSE,
             browser.fill = TRUE,
             browser.padding = 75,
             knitr.defaultWidth = 800,
             knitr.defaultHeight = 500)

2.2.2 可用选项

以下是在大小调整策略中可以指定的各种选项:

Option Description
defaultWidth The default width used to display the widget. This parameter specifies the default width for viewing in all contexts (browser, viewer, and knitr) unless it is specifically overridden with e.g. browser.defaultWidth.
defaultHeight The default height used to display the widget. This parameter specifies the default height for viewing in all contexts (browser, viewer, and knitr) unless it is specifically overridden with e.g. browser.defaultHeight.
padding Padding around the widget (in pixels). This parameter specifies the padding for viewing in all contexts (browser and viewer) unless it is specifically overridden by e.g. browser.padding.
viewer.defaultWidth The default width used to display the widget within the RStudio Viewer.
viewer.defaultHeight The default height used to display the widget within the RStudio Viewer.
viewer.padding Padding around the widget when displayed in the RStudio Viewer (defaults to 15 pixels).
viewer.fill When displayed in the RStudio Viewer, automatically size the widget to the viewer dimensions (note that viewer.padding is still applied). Default to TRUE.
viewer.suppress Never display the widget within the RStudio Viewer (useful for widgets that require a large amount of space for rendering). Defaults to FALSE.
viewer.paneHeight Request that the RStudio Viewer be forced to a specific height when displaying this widget.
browser.defaultWidth The default width used to display the widget within a standalone web browser.
browser.defaultHeight The default height used to display the widget within a standalone web browser
browser.padding Padding around the widget when displayed in a standalone browser (defaults to 40 pixels).
browser.fill When displayed in a standalone web browser, automatically size the widget to the browser dimensions (note that browser.padding is still applied). Defaults to FALSE.
browser.external When displaying in a browser, always use an external browser (via browseURL()). Defaults to FALSE, which will result in the use of an internal browser within RStudio v1.1 and higher.
knitr.defaultWidth The default width used to display the widget within documents generated by knitr (e.g. R Markdown).
knitr.defaultHeight The default height used to display the widget within documents generated by knitr (e.g. R Markdown).
knitr.figure Apply the default knitr fig.width and fig.height to the widget when it’s rendered within R Markdown documents. Defaults to TRUE.

2.3 JavaScript调整大小方法

设置大小策略允许htmlwidgets在展示图像的区域计算控件的宽和高,然而你仍然需要把你定义的这种大小信息传递给底层你创建控件所使用的JavaScript库。

每一个JavaSript库在处理动态大小调整问题时都有一些不同,有些可能自动调整,有些可能需要通过resize()函数调用布局,有些可能需要通过设置数据或其他选项实现。无论哪种情况,htmlwidhets框架将把计算的大小传递给函数factory和resize函数.下面是一个空的JavaScript binding的说明例子:

HTMLWidgets.widget({

  name: "demo",
  
  type: "output",
  
  factory: function(el, width, height) {
  
    return {
      renderValue: function(x) {
      
      },
      
      resize: function(width, height) {
        
      }
    };
  }
});

您所处理的宽度和高度是由您决定的,它取决于您正在创建控件的基础JavaScript库的大小调整语义。

2.3.1 例子

2.3.1.1 dygraphs

dygraphs控件中,调整大小的实现现对简单,因为dygraphs库包含一个resize()方法来自动的将该图大小映射到封闭HTML元素。

resize: function(width, height) {
  if (dygraph)
    dygraph.resize();
}

2.3.1.2 forceNetwork

forceNetwork通过适用于承载D3网络可视化的<svg>标签来传递宽和高的大小变化。

factory: function(el, width, height) {

  // instance data
  var el = el;
  var force = d3.layout.force();

  d3.select(el).append("svg")
    .attr("width", width)
    .attr("height", height);
      
  return {
    renderValue: function(x) {
      // implementation excluded
    },
      
    resize: function(width, height) {
         
      d3.select(el).select("svg")
        .attr("width", width)
        .attr("height", height);

      force.size([width, height]).resume();
    }
  };
}

我们看到在不同的JavaScript库中,resize方法可能会提供灵活的自动调整大小的逻辑,这是我们需要注意的。