自制“htmlwigets”?

自制“htmlwigets”?

如果有“王八拳”这个概念成立的话,我想我是把它发挥到了极致。

最近几天学了好多基于 htmlWidgets 的 R 包,感觉神奇极了。要是自己能自己写 htmlWidgets 该有多好。于是昨晚自己决定今天一定要搞懂如何自己写个htmlWidgets,然后我按照自己惯常的做法,首先打开htmlWidgets的官网找入门教程。

很不幸我没能看懂。那找个看起来简单的、使用了 htmlWidgets 创建的 R 包拆开看看吧,说不定能摸出什么门道。很不幸,一番研究的结论是:不会JS=学不会htmlWidgets

极其沮丧了。过去为了用 Stata 创建美丽的 JS 图片,我王八拳编程式的花了一些图。这些图的绘制非常符合“王八拳”的定义了。那么在 R 里面,我是不是也可以“王八拳”一下满足自己小小的意愿(这个意愿就是当自己看到美丽的JS图表可以把它搞成一个R函数便于重复使用)呢?

例如:

那么在 R 中如何实现这种神奇的操作呢?

Stata 文件操作是不是太麻烦了?一文中,我提到操作文件更为简单的办法其实是直接使用 shell 命令。这里可以使用的 shell 命令有:

  1. echo:用于在 shell 中打印 shell 变量的值,或者直接输出指定的字符串;
  2. touch:创建一个空的二进制文件;
  3. rm:删除一个文件;
  4. >:输出重定向,可以将输出重定向到文件中。
  5. >>:输出重定向,可以将输出重定向到文件中的下一行。

所以为了在 R 中实现这么一个操作,我们需要写一个 html 文件并且在写的时候把数据写进去。R 语言调用 shell 命令的方法是使用system()函数,这一步很简单。

接下来就是如何利用 RStudio 的 Viewer 窗口了,这个窗口可以看作一个简易的浏览器。R 中调用系统浏览器打开一个文件的方法很多,例如:

R
1
2
3
4
5
viewer <- getOption("viewer")
viewer("zingpie.html")

# 或者
browseURL("zingpie.html")

而如果你想把 html 文件在 RStudio 的 Viewer 窗口打开,可以使用ricomisc包的rstudio_viewer()函数:

R
1
2
library(ricomisc)
rstudio_viewer("zingpie.html")

这个就很令人奇怪了,为什么只有这种方式才能将 html 文件在 RStudio 的 Viewer 窗口打开呢?然后我去看了rstudio_viewer()函数的源码
是这样的:

核心部分就是这样的;

R
1
2
3
4
dir.create(tempfile())
(html_file <- file.path(temporary_file, "zingpie.html"))
file.copy(file.path("zingpie.html"), html_file)
rstudioapi::viewer(html_file)

这个操作是在路径
/var/folders/9p/6f00xrjj4gzd58nh54ddrvqr0000gn/T//Rtmpl7qaoC/file24eb5fffbf5d/
上创建了一个临时文件,然后被”zingpie.html”拷贝过去,再使用rstudioapi::viewer()就能将文件显示在 RStudio 的 Viewer 窗口了。

准备工作做完了就能开始试着写自己的第一个 R+JS 的函数了!
为了简单起见,我找了个饼图的模板:示例饼图.html,这是ZingChart图表库里的图表。

经过一番分解,我写了个zingpie()函数:

如果你想使用这个函数,可以:

R
1
source("https://gist.githubusercontent.com/czxa/dad3740270cea3309566852e04e07559/raw/a65995fc5f6ccdb9dcf45df263dd7970e8763777/zingpie")

这个函数的各个参数含义分别是:

  • name = name:名称,必须项
  • value = value:值,必须项
  • color = color:颜色值,必须项
  • title = ‘标题’:图表标题
  • titleColor = ‘#1A1B26’:标题的颜色
  • subtitleColor = ‘#202235’:副标题的背景颜色
  • legendPosition = ‘34%’:图片的水平位置,可以通过调整它来控制图例的水平位置
  • fileName = ‘zingpie.html’:html 文件的名称(要带后缀)
  • fontFamily = ‘STSongti-SC-Bold’:全局字体设置
  • backgroundColor = ‘#efeacc’:图表背景的颜色
  • titleBackgroundColor = ‘#efeacc’:标题背景的颜色

使用示例:

R
1
2
3
4
5
6
7
8
9
10
df <- data.frame(
name = c("男性", "女性", "未知"),
value = c(100, 200, 35),
color = c("#502117", "#be3c1a", "#f38a1c"))

zingpie(name = df$name,
value = df$value,
color = df$color,
title = "我的好友性别分布",
legendPosition = '35%')

这个配色来自一幅画:
记忆永恒

由于 R 允许代码直接断行,所以按照这种思路实现 R 和 JS 的结合比 Stata 和 JS 的结合更加容易了。

最后我们还可以用webshot包的webshot函数将 html 文件保存为图片:

R
1
2
library(webshot)
webshot::webshot("zingpie.html", "zingpie.png")

图片像素渣渣,所以还是不展示了。

后话

我是怎么想起来这么干的呢?源于昨天看到的这篇文章:可以滚的词云, 就问你怕不怕。这篇文章介绍了如何制作滚动的词云。

思路非常的简单,首先用wordcloud2包绘制一幅词云图,然后再截图保存,最后再使用threejs包把二维词云图片映射到球上:

R
1
2
3
4
5
6
7
8
library(threejs)
library(wordcloud2)
library(webshot)
wordcloud2(demoFreqC, size = 4) %>%
htmlwidgets::saveWidget("1.html", selfcontained = F)

webshot::webshot("1.html", "1.png", vwidth = 4000, vheight = 2000, delay =20)
globejs("1.png", bg = 'white')

globejs()函数可以将一张矩形图片映射充满整个球体,所以我还是截个图:

R
1
2
3
4
wordcloud2(demoFreq, size = 3, fontFamily = "微软雅黑",
color = "random-light", backgroundColor = "grey")

globejs("czxa_2018-11-26_01.50.03.png", bg = 'white')

效果:

这篇文章让我对 JS 佩服的五体投地,同时也意识到 RStudio Viewer 可以直接显示 html 文件。于是就找到了rstudio_viewer()函数。

最近发现 RStudio 对 R 的拓展好多呀,接下来计划把 RMarkdown、bookdown、knitr、pander 等包学习学习。具体来说,感觉这个文档上列举的包都很值得学习:

rstudio/RStartHere

# R

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×