OJS 单元格

OJS 代码单元格 {ojs} 与传统笔记本中的单元格行为略有不同,并且有许多选项可用于控制其显示和布局。

单元格执行

OJS 单元格执行与传统笔记本之间的一个关键区别是,OJS 单元格不需要按任何特定顺序定义。

由于执行是完全响应式的,运行时会根据单元格之间的引用关系自动按正确的顺序执行单元格。这更类似于电子表格,而不是具有线性单元格执行的传统笔记本。

例如,在这个单元格中,我们引用了一个尚未定义的变量(它定义在下方):

```{ojs}
x + 5
```
```{ojs}
x = 10
```

这段代码之所以有效,是因为 Observable 运行时自动确定了单元格的正确执行顺序。

单元格输出

默认情况下,OJS 单元格在渲染文档中显示其完整的源代码和输出。根据您创建的文档类型,您可能希望全局或针对个别单元格更改此行为。

代码可见性

echo 选项控制单元格是否显示其源代码。要阻止整个文档显示代码,请在 YAML 元数据中设置 echo: false 选项:

---
title: "我的文档"
execute:
  echo: false
---

您也可以在每个单元格的基础上指定此选项。例如:

```{ojs}
//| echo: false
data = FileAttachment("palmer-penguins.csv").csv({ typed: true })
```

输出可见性

OJS 单元格输出默认也是显示的。您可以使用 output 选项在全局或(更可能)每个单元格的基础上更改此行为。例如,这里我们禁用了单元格的输出:

```{ojs}
//| output: false
data
```

请注意,仅包含赋值的单元格默认不会打印其输出。例如,这个赋值不会打印任何内容:

```{ojs}
//| echo: fenced
dummy1 = "aHiddenAssignment"
```

如果您想打印赋值的结果,可以指定 output: all 选项。例如:

```{ojs}
//| echo: fenced
//| output: all
dummy2 = [{key: 1, value: [1, 2, [3, 4], dummy1]}]
```

如果您点击检查器,您将看到它展开以 JSON 格式显示数据。

代码显示

我们上面讨论了显示和隐藏源代码,但如何控制它的确切显示方式呢?

有一些选项可用于自定义代码块的外观(高亮显示、背景、边框等)以及如何处理水平溢出。有关所有详细信息,请参阅 HTML 代码块 文章。

我们想在这里特别强调的一个选项是代码折叠,它允许您折叠代码但仍为用户提供查看选项。这对于自定义 JavaScript 可视化特别方便,因为它们通常跨越数十行代码。

在代码单元格中添加 code-fold: true 选项以启用代码折叠(您也可以全局启用此功能)。例如,点击“代码”按钮以显示代码块(注意 code-fold: true 选项已指定)

Code
```{ojs}
//| code-fold: true
pdata = FileAttachment("palmer-penguins.csv").csv({typed: true})

Plot.plot({
  facet: {
    data: pdata,
    x: "sex",
    y: "species",
    marginRight: 80
  },
  marks: [
    Plot.frame(),
    Plot.rectY(pdata, 
      Plot.binX(
        {y: "count"}, 
        {x: "body_mass_g", thresholds: 20, fill: "species"}
      )
    ),
    Plot.tickX(pdata, 
      Plot.groupZ(
        {x: "median"}, 
        {x: "body_mass_g",
         z: d => d.sex + d.species,
         stroke: "#333",
         strokeWidth: 2
        }
      )
    )
  ]
})
```

单元格布局

您可以向 OJS 单元格添加额外的 panellayout 选项,以自定义其输出的呈现方式。以下是一些我们之前使用的示例,以侧边栏和标签集呈现:

我们通过首先向包含输入的单元格添加 panel: sidebar 选项来创建此布局:

```{ojs}
//| panel: sidebar

viewof bill_length_min = Inputs.range(
  [32, 50], 
  {value: 35, step: 1, label: "鸟嘴长度 (最小):"}
)
viewof islands = Inputs.checkbox(
  ["Torgersen", "Biscoe", "Dream"], 
  { value: ["Torgersen", "Biscoe"], 
    label: "岛屿:"
  }
)
```

然后我们添加了一个选项卡集(class为.panel-tabset的div),包含PlotData选项卡(div内的标题定义了选项卡):

::: {.panel-tabset}

## Plot

```{ojs}
Plot.rectY(filtered, 
  Plot.binX(
    {y: "count"}, 
    {x: "body_mass_g", fill: "species", thresholds: 20}
  ))
  .plot({
    facet: {
      data: filtered,
      x: "sex",
      y: "species",
      marginRight: 80
    },
    marks: [
      Plot.frame(),
    ]
  }
)
```

## Data

```{ojs}
Inputs.table(filtered)
```

:::

查看布局示例以获取完整源代码。

布局文章中了解更多关于交互式文档的内容。

单元格图表

OJS单元格也可以渲染为带编号、可交叉引用的图表。为此,将labelfig-cap选项添加到单元格中。例如:

```{ojs}
//| echo: fenced
//| label: fig-penguin-body-mass
//| fig-cap: "企鹅按性别和种类的体重"
Plot.rectY(filtered, 
  Plot.binX(
    {y: "count"}, 
    {x: "body_mass_g", fill: "species", thresholds: 20}
  ))
  .plot({
    facet: {
      data: filtered,
      x: "sex",
      y: "species",
      marginRight: 80
    },
    marks: [
      Plot.frame(),
    ]
  }
)
```
Figure 1: 企鹅按性别和种类的体重

查看@fig-penguin-body-mass以获得进一步说明。

要引用图表,请在其标签中使用markdown的交叉引用

查看@fig-penguin-body-mass以获得进一步说明。