问题背景
楼主参照reactable 包的一个例子,打算用 DT 包鼓捣试试,顺便了解下 css/html/js。已知原始数据中有三列数据,还有一些图片,需要将图片和原数据中的其中两列合到一起。俺已经用一个笨方法实现了,但是很麻烦,请教各位小伙伴们有没有什么聪明的办法能直接在原始数据上操作的?
此题目包含三个细节:
- 一是将图片插入到表格中进行展示,每行数据对应不同的图片;
- 二是将图片和原始数据中的前两列结合到一列中进行展示;
- 三是合为一列展示时,原来的多列数据可以设置各自的 css 样式。
原始数据:
```{r}
library(DT)
df1 <-
data.frame(
team = c('USA', 'France', 'Germany', 'Canada'),
pts = c(6, 6, 6, 6),
group = c('A', 'A', 'B', 'B')
)
```
图片位置:
一个笨方法
首先把图片下载下来,存放在工作目录的“images”文件夹下面。接着建立一个新的数据框df2
,把原本应该合到一起展示的数据按照 html 的方式写到一起。最后,用DT::datatable(df2, escape = FALSE)
绘制出表格。
```{r}
df2 <- data.frame(
flag = c(
'<div class="team"><img class="team-flag" src="images/USA.png" /><div><span class="team-name">USA<span/><span class="team-record"> 6pts<span/><div/><div/>',
'<div class="team"><img class="team-flag" src="images/France.png" /><div><span class="team-name">France<span/><span class="team-record"> 6pts<span/><div/><div/>',
'<div class="team"><img class="team-flag" src="images/Germany.png" /><div><span class="team-name">Germany<span/><span class="team-record"> 6pts<span/><div/><div/>',
'<div class="team"><img class="team-flag" src="images/Canada.png" /><div><span class="team-name">Canada<span/><span class="team-record"> 6pts<span/><div/><div/>'
),
group = c('A', 'A', 'B', 'B')
)
DT::datatable(df2, escape = FALSE)
```
1.上面的 html 代码格式化以后长这样:
首先,建立一个div
框。接着,在里面放进去一个img
图片框和一个新的div
框。最后,在新div
框里面再放两个span
框,分别放原始数据中的两列值。
```{html}
<div class="team">
<img class="team-flag" src="images/USA.png" />
<div>
<span class="team-name">USA<span/>
<span class="team-record"> 6pts<span/>
<div/>
<div/>
```
2.上面用到的 css 样式设定如下:
```{css}
.team {
display: flex;
align-items: center;
}
.team-flag {
height: 1.3rem;
border: 1px solid #f0f0f0;
}
.team-name {
margin-left: 0.5rem;
font-size: 1.125rem;
font-weight: 700;
}
.team-record {
margin-left: 0.35rem;
color: hsl(0, 0%, 45%);
font-size: 0.8125rem;
}
```
尝试别的方法均卡关
一列数据中插入图片时需要在JS()
中使用sprintf()
函数但是怎么用?
往一列数据中插入同一张图片如下,<img class="team-flag" src="images/USA.png" />
,在src=" "
里面写入图片的路径。
```{r}
DT::datatable(df1,
rownames = FALSE,
options = list(columnDefs = list(list(
targets = 0,
render = JS(
"function(data, type, row, meta) {
return '<img src=\"images/USA.png\" />'
}"
)
))))
```
若是需要往一列数据中插入不同的图片,则需要写入每张图片的路径,可以用sprintf()
函数。
```{r}
sprintf("images/%s.png", c("USA", "France", "Germany", "Canada"))
```
[1] "images/USA.png" "images/France.png" "images/Germany.png" "images/Canada.png"
这个函数在 R 里面有,但是在 Javascript 里面是一个独立库,我猜在 R 里面用JS()
的时候是不能直接用属于 JS 的sprintf()
函数,应该是要新建一个这样的函数。可是不知道怎么在 R 里面新建 JS 可以引用的函数?
用DT中formatString()
函数将多列合为一列,但是怎么给合起来的数据单独设置样式?
```{r}
DT::datatable(df1,
rownames = FALSE,
options = list(columnDefs = list(
list(targets = 1,
class = "team-name"),
list(targets = 1, #隐藏不展示 pts 列
visible = FALSE)
))) |>
formatString('team',
suffix = paste('', df1$pts, 'pts.'))
```