在数据可视化领域,仪表盘的外观和感觉是非常重要的,因为它可以帮助用户消化你在仪表盘中显示的洞察力。我们通常用彩色的图表和现代调色板来设计仪表盘,这是改善仪表盘风格的好方法,但表格也是仪表盘的重要元素,需要进行改造以使其具有吸引力。在闪亮的应用程序中,我们有默认的表格小部件和其他流行的小部件,如DT、reactable等。这些表格的默认外观并不那么令人印象深刻。在这篇文章中,我们将向你展示如何用bootstrap 4的样式和类来设计你的基本html表格。
我创建了一个用户定义的函数,名为tbl( )
,用于实现带有表格的bootstrap 4类。该函数有四个参数,如下所示。
data
你想在表中显示的数据框架的名称。index
行数。将作为表格中的第一列显示。你需要为序列号创建一个列。它可以有任何字符串或字体,如 。fas fa-star
namecol
表格的第二列。它可以是任何一列,你想在它旁边显示图标或图像。nameicon
可选参数。包含图像链接的列的名称。
示例数据框架
df <- data.frame(
col0 = c("fas fa-star", "01", "02"),
nameicon = c("https://www.freepnglogos.com/uploads/bitcoin-png/bitcoin-all-about-bitcoins-9.png",
"https://freepngimg.com/thumb/bitcoin/59549-cryptocurrency-money-bitcoin-gold-cash-free-photo-png-thumb.png",
"https://freepngimg.com/thumb/bitcoin/59526-cryptocurrency-badge-bitcoin-gold-png-file-hd-thumb.png"),
Name = c("Bitcoin", "Ripple", "Bitcoin cash"),
`Market cap` = c("$146,169,768.00", "$56,169,768.00", "$446,569,768.00"),
Price = c("$8,536.79", "$8,536.79", "$8,836.79"),
Volume = c("$7,576,878.89", "$7,576,878.89", "$7,576,878.89"),
Change = c("-1.22%", "-0.18%", "+1.21%"),
check.names = FALSE
)
在下面的程序中,我们正在使用tbl(df, col0, Name, nameicon)
library(shiny)
library(dplyr)
tbl <- function(data, index, namecol, nameicon = NULL) {
temp <- list()
index <- deparse(substitute(index))
namecol <- deparse(substitute(namecol))
if(!missing(nameicon)) {
nameicon <- deparse(substitute(nameicon))
}
# Convert to Character
col_names <- names(data)
data[,col_names] <- lapply(data[,col_names] , as.character)
# Loop over Rows
for(i in 1:nrow(data)) {
col0 = data[i,index]
col1 = data[i,namecol]
icon = data[i,nameicon]
first2cols <- list(
tags$td(tags$div(
class = "d-flex mt-2 border-right",
tags$div(
class = "box p-2 rounded",
tags$span(
class = ifelse(substr(col0,1,2)=="fa", paste(col0, "fa-lg text-primary px-2"),
"text-primary px-2 font-weight-bold"),
ifelse(substr(col0,1,2)=="fa", '', col0)
)
)
)),
tags$td(tags$div(
class = "d-flex flex-column",
tags$div(
class = "text-muted",
namecol
),
if(!is.null(nameicon)) {
tags$div(
class = "d-flex align-items-center",
tags$div(tags$img(
src = icon,
alt = NA,
class = "icons"
)),
tags$b(
class = "pl-2",
col1
)
) } else {
tags$div(
tags$b(
col1
)
)
}
))
)
# Loop over Columns (ignoring index, name and icon columns)
temp.col <- list()
data2 <- data[!(names(data) %in% c(index, namecol, nameicon))]
for(j in 1:ncol(data2)) {
temp.col[[j]] <-
tags$td(tags$div(
class = "d-flex flex-column",
tags$div(
class = "text-muted",
colnames(data2)[j]
),
tags$div(tags$b(data2[i,j]))
))
}
temp[[i]] <- tags$tr(first2cols, temp.col)
}
tags$div(
class = "bg-white table-responsive",
tags$table(
class = "table",
tags$tbody(
temp
))
)
}
# Bootstrap 4
theme <- bslib::bs_theme(version = 4)
# UI
ui <- fluidPage(
theme = theme,
br(),
htmltools::htmlDependency(name = "font-awesome",
version = "5.13.0",
src = "www/shared/fontawesome",
package = "shiny",
stylesheet = c("css/all.min.css", "css/v4-shims.min.css")),
tags$style("@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
font-size: 0.95rem
}
body {
background-color: #f3f3f3
}
#starred {
box-shadow: 3px 3px 10px #b5b5b5
}
.table div.text-muted {
font-size: 0.85rem;
font-weight: 600;
margin-bottom: 0.3rem;
margin-top: 0.3rem
}
.icons {
object-fit: contain;
width: 25px;
height: 25px;
border-radius: 50%
}
.graph img {
object-fit: contain;
width: 40px;
height: 50px;
transform: scale(2) rotateY(45deg)
}
.graph .dot {
width: 12px;
height: 12px;
border-radius: 50%;
border: 3px solid #fff;
position: absolute;
background-color: blue;
box-shadow: 1px 1px 1px #a5a5a5;
top: 25px
}
.graph .dot:after {
background-color: #fff;
content: '$9,999.00';
font-weight: 600;
font-size: 0.7rem;
position: absolute;
top: -25px;
left: -20px;
box-shadow: 1px 1px 2px #a5a5a5;
border-radius: 2px
}
.font-weight-bold {
font-size: 1.3rem
}
#ethereum {
transform: scale(2) rotateY(45deg) rotateX(180deg)
}
#ripple {
transform: scale(2) rotateY(10deg) rotateX(20deg)
}
#eos {
transform: scale(2) rotateY(50deg) rotateX(190deg)
}
.table tr td {
border: none
}
.red {
color: #ff2f2f;
font-weight: 700
}
.green {
color: #1cbb1c;
font-weight: 700
}
.labels,
.graph {
position: relative
}
.green-label {
background-color: #00b300;
color: #fff;
font-weight: 600;
font-size: 0.7rem
}
.orange-label {
background-color: #ffa500;
color: #fff;
font-weight: 600;
font-size: 0.7rem
}
.border-right {
transform: scale(0.6);
border-right: 1px solid black !important
}
.box {
transform: scale(1.5);
background-color: #dbe2ff
}
#top .table tbody tr {
border-bottom: 1px solid #ddd
}
#top .table tbody tr:last-child {
border: none
}
select {
background-color: inherit;
padding: 8px;
border-radius: 5px;
color: #444;
border: 1px solid #444;
outline-color: #00f
}
.text-white {
background-color: rgb(43, 159, 226);
border-radius: 50%;
font-size: 0.7rem;
font-weight: 700;
padding: 2px 3px
}
a:hover {
text-decoration: none
}
a:hover .text-white {
background-color: rgb(20, 92, 187)
}
::-webkit-scrollbar {
width: 10px;
height: 4px
}
::-webkit-scrollbar-thumb {
background: linear-gradient(45deg, #999, #777);
border-radius: 10px
}
@media(max-width:379px) {
.d-lg-flex .h3 {
font-size: 1.4rem
}
}
@media(max-width:352px) {
#plat {
margin-top: 10px
}
}"),
fluidRow(
tags$div(
class = "container mt-5",
tags$div(
class = "d-lg-flex align-items-lg-center py-4",
tags$div(
class = "h3 text-muted",
"Top Cryptocurrency Prices"
)
),
tags$div(
id = "top",
tbl(df, col0, Name, nameicon)
)
))
)
# Server
server <- function(input, output, session) { }
# Run App
shinyApp(ui = ui, server = server)
条件性格式化
为 "change "列中的负号和正号分别着色,我们可以使用javascript进行有条件的格式化。在下面的代码中,我们正在格式化第6列td:nth-child(6)
。你可以根据你的数据框架来改变它。
jscode <- "var CONTROL_INTERVAL2 = setInterval(function(){
$('table tbody td:nth-child(6) b').each(function() {
const value = $(this).text().substr(0,1);
if ( value == '-') {
$(this).css('color', 'red');
}
else {
$(this).css('color', 'green');
}
});
clearInterval(CONTROL_INTERVAL2);
}, 500);"
请看下面的完整代码
theme <- bslib::bs_theme(version = 4)
# UI
ui <- fluidPage(
theme = theme,
br(),
htmltools::htmlDependency(name = "font-awesome",
version = "5.13.0",
src = "www/shared/fontawesome",
package = "shiny",
stylesheet = c("css/all.min.css", "css/v4-shims.min.css")),
tags$script("
Shiny.addCustomMessageHandler('closeWindow', function(data) {
eval(data.message)
});"
),
tags$style("@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
font-size: 0.95rem
}
body {
background-color: #f3f3f3
}
#starred {
box-shadow: 3px 3px 10px #b5b5b5
}
.table div.text-muted {
font-size: 0.85rem;
font-weight: 600;
margin-bottom: 0.3rem;
margin-top: 0.3rem
}
.icons {
object-fit: contain;
width: 25px;
height: 25px;
border-radius: 50%
}
.graph img {
object-fit: contain;
width: 40px;
height: 50px;
transform: scale(2) rotateY(45deg)
}
.graph .dot {
width: 12px;
height: 12px;
border-radius: 50%;
border: 3px solid #fff;
position: absolute;
background-color: blue;
box-shadow: 1px 1px 1px #a5a5a5;
top: 25px
}
.graph .dot:after {
background-color: #fff;
content: '$9,999.00';
font-weight: 600;
font-size: 0.7rem;
position: absolute;
top: -25px;
left: -20px;
box-shadow: 1px 1px 2px #a5a5a5;
border-radius: 2px
}
.font-weight-bold {
font-size: 1.3rem
}
#ethereum {
transform: scale(2) rotateY(45deg) rotateX(180deg)
}
#ripple {
transform: scale(2) rotateY(10deg) rotateX(20deg)
}
#eos {
transform: scale(2) rotateY(50deg) rotateX(190deg)
}
.table tr td {
border: none
}
.red {
color: #ff2f2f;
font-weight: 700
}
.green {
color: #1cbb1c;
font-weight: 700
}
.labels,
.graph {
position: relative
}
.green-label {
background-color: #00b300;
color: #fff;
font-weight: 600;
font-size: 0.7rem
}
.orange-label {
background-color: #ffa500;
color: #fff;
font-weight: 600;
font-size: 0.7rem
}
.border-right {
transform: scale(0.6);
border-right: 1px solid black !important
}
.box {
transform: scale(1.5);
background-color: #dbe2ff
}
#top .table tbody tr {
border-bottom: 1px solid #ddd
}
#top .table tbody tr:last-child {
border: none
}
select {
background-color: inherit;
padding: 8px;
border-radius: 5px;
color: #444;
border: 1px solid #444;
outline-color: #00f
}
.text-white {
background-color: rgb(43, 159, 226);
border-radius: 50%;
font-size: 0.7rem;
font-weight: 700;
padding: 2px 3px
}
a:hover {
text-decoration: none
}
a:hover .text-white {
background-color: rgb(20, 92, 187)
}
::-webkit-scrollbar {
width: 10px;
height: 4px
}
::-webkit-scrollbar-thumb {
background: linear-gradient(45deg, #999, #777);
border-radius: 10px
}
@media(max-width:379px) {
.d-lg-flex .h3 {
font-size: 1.4rem
}
}
@media(max-width:352px) {
#plat {
margin-top: 10px
}
}"),
fluidRow(
tags$div(
class = "container mt-5",
tags$div(
class = "d-lg-flex align-items-lg-center py-4",
tags$div(
class = "h3 text-muted",
"Top Cryptocurrency Prices"
)
),
tags$div(
id = "top",
tbl(df, col0, Name, nameicon)
)
))
)
# Server
server <- function(input, output, session) {
session$sendCustomMessage(type = "closeWindow", list(message = jscode))
}
# Run App
shinyApp(ui = ui, server = server)
在服务器中运行表
一般来说,我们需要将反应式数据框架传递给表格。因此,在shiny应用程序代码的服务器部分运行表格是很关键的。我们可以使用renderUI( )
和uiOutput( )
来完成这个任务。请看下面的演示。
library(shiny)
library(dplyr)
df <- data.frame(
col0 = c("fas fa-star", "01", "02"),
nameicon = c("https://www.freepnglogos.com/uploads/bitcoin-png/bitcoin-all-about-bitcoins-9.png",
"https://freepngimg.com/thumb/bitcoin/59549-cryptocurrency-money-bitcoin-gold-cash-free-photo-png-thumb.png",
"https://freepngimg.com/thumb/bitcoin/59526-cryptocurrency-badge-bitcoin-gold-png-file-hd-thumb.png"),
Name = c("Bitcoin", "Ripple", "Bitcoin cash"),
`Market cap` = c("$146,169,768.00", "$56,169,768.00", "$446,569,768.00"),
Price = c("$8,536.79", "$8,536.79", "$8,836.79"),
Volume = c("$7,576,878.89", "$7,576,878.89", "$7,576,878.89"),
Change = c("-1.22%", "-0.18%", "+1.21%"),
check.names = FALSE
)
jscode <- "var CONTROL_INTERVAL2 = setInterval(function(){
$('#mytable table tbody td:nth-child(6) b').each(function() {
const value = $(this).text().substr(0,1);
if ( value == '-') {
$(this).css('color', 'red');
}
else {
$(this).css('color', 'green');
}
});
clearInterval(CONTROL_INTERVAL2);
}, 500);"
tbl <- function(data, index, namecol, nameicon = NULL) {
temp <- list()
index <- deparse(substitute(index))
namecol <- deparse(substitute(namecol))
if(!missing(nameicon)) {
nameicon <- deparse(substitute(nameicon))
}
# Convert to Character
col_names <- names(data)
data[,col_names] <- lapply(data[,col_names] , as.character)
# Loop over Rows
for(i in 1:nrow(data)) {
col0 = data[i,index]
col1 = data[i,namecol]
icon = data[i,nameicon]
first2cols <- list(
tags$td(tags$div(
class = "d-flex mt-2 border-right",
tags$div(
class = "box p-2 rounded",
tags$span(
class = ifelse(substr(col0,1,2)=="fa", paste(col0, "fa-lg text-primary px-2"),
"text-primary px-2 font-weight-bold"),
ifelse(substr(col0,1,2)=="fa", '', col0)
)
)
)),
tags$td(tags$div(
class = "d-flex flex-column",
tags$div(
class = "text-muted",
namecol
),
if(!is.null(nameicon)) {
tags$div(
class = "d-flex align-items-center",
tags$div(tags$img(
src = icon,
alt = NA,
class = "icons"
)),
tags$b(
class = "pl-2",
col1
)
) } else {
tags$div(
tags$b(
col1
)
)
}
))
)
# Loop over Columns (ignoring index, name and icon columns)
temp.col <- list()
data2 <- data[!(names(data) %in% c(index, namecol, nameicon))]
for(j in 1:ncol(data2)) {
temp.col[[j]] <-
tags$td(tags$div(
class = "d-flex flex-column",
tags$div(
class = "text-muted",
colnames(data2)[j]
),
tags$div(tags$b(data2[i,j]))
))
}
temp[[i]] <- tags$tr(first2cols, temp.col)
}
tags$div(
class = "bg-white table-responsive",
tags$table(
class = "table",
tags$tbody(
temp
))
)
}
# Bootstrap 4
theme <- bslib::bs_theme(version = 4)
# UI
ui <- fluidPage(
theme = theme,
br(),
htmltools::htmlDependency(name = "font-awesome",
version = "5.13.0",
src = "www/shared/fontawesome",
package = "shiny",
stylesheet = c("css/all.min.css", "css/v4-shims.min.css")),
tags$script("
Shiny.addCustomMessageHandler('closeWindow', function(data) {
eval(data.message)
});"
),
tags$style("@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
font-size: 0.95rem
}
body {
background-color: #f3f3f3
}
#starred {
box-shadow: 3px 3px 10px #b5b5b5
}
.table div.text-muted {
font-size: 0.85rem;
font-weight: 600;
margin-bottom: 0.3rem;
margin-top: 0.3rem
}
.icons {
object-fit: contain;
width: 25px;
height: 25px;
border-radius: 50%
}
.graph img {
object-fit: contain;
width: 40px;
height: 50px;
transform: scale(2) rotateY(45deg)
}
.graph .dot {
width: 12px;
height: 12px;
border-radius: 50%;
border: 3px solid #fff;
position: absolute;
background-color: blue;
box-shadow: 1px 1px 1px #a5a5a5;
top: 25px
}
.graph .dot:after {
background-color: #fff;
content: '$9,999.00';
font-weight: 600;
font-size: 0.7rem;
position: absolute;
top: -25px;
left: -20px;
box-shadow: 1px 1px 2px #a5a5a5;
border-radius: 2px
}
.font-weight-bold {
font-size: 1.3rem
}
#ethereum {
transform: scale(2) rotateY(45deg) rotateX(180deg)
}
#ripple {
transform: scale(2) rotateY(10deg) rotateX(20deg)
}
#eos {
transform: scale(2) rotateY(50deg) rotateX(190deg)
}
.table tr td {
border: none
}
.red {
color: #ff2f2f;
font-weight: 700
}
.green {
color: #1cbb1c;
font-weight: 700
}
.labels,
.graph {
position: relative
}
.green-label {
background-color: #00b300;
color: #fff;
font-weight: 600;
font-size: 0.7rem
}
.orange-label {
background-color: #ffa500;
color: #fff;
font-weight: 600;
font-size: 0.7rem
}
.border-right {
transform: scale(0.6);
border-right: 1px solid black !important
}
.box {
transform: scale(1.5);
background-color: #dbe2ff
}
#top .table tbody tr {
border-bottom: 1px solid #ddd
}
#top .table tbody tr:last-child {
border: none
}
select {
background-color: inherit;
padding: 8px;
border-radius: 5px;
color: #444;
border: 1px solid #444;
outline-color: #00f
}
.text-white {
background-color: rgb(43, 159, 226);
border-radius: 50%;
font-size: 0.7rem;
font-weight: 700;
padding: 2px 3px
}
a:hover {
text-decoration: none
}
a:hover .text-white {
background-color: rgb(20, 92, 187)
}
::-webkit-scrollbar {
width: 10px;
height: 4px
}
::-webkit-scrollbar-thumb {
background: linear-gradient(45deg, #999, #777);
border-radius: 10px
}
@media(max-width:379px) {
.d-lg-flex .h3 {
font-size: 1.4rem
}
}
@media(max-width:352px) {
#plat {
margin-top: 10px
}
}"),
fluidRow(
tags$div(
class = "container mt-5",
tags$div(
class = "d-lg-flex align-items-lg-center py-4",
tags$div(
class = "h3 text-muted",
"Top Cryptocurrency Prices"
)
),
tags$div(
id = "top",
uiOutput('mytable')
)
))
)
# Server
server <- function(input, output, session) {
output$mytable <- renderUI({
tbl(df, col0, Name, nameicon)
})
session$sendCustomMessage(type = "closeWindow", list(message = jscode))
}
# Run App
shinyApp(ui = ui, server = server)