前段日子逛全球最大****網(wǎng)站時,發(fā)現(xiàn)一個名為shinyWidgets的shiny擴展包,主要集成了數(shù)據(jù)平臺中常用的控件,不少挺炫酷且實用;此文從產(chǎn)品設(shè)計和代碼開發(fā)雙重角度梳理總結(jié)這個包的實用控件體系,對于數(shù)據(jù)產(chǎn)品交互設(shè)計和數(shù)據(jù)產(chǎn)品開發(fā)具備一定參考價值。
1. demo體驗
對于調(diào)包俠來說,沒有什么問題是無法用一行代碼解決的;如果有,就先加一行安裝包的代碼。
# 裝包
install.packages("shinyWidgets")
# 調(diào)包
shinyWidgets::shinyWidgetsGallery()
# enjoy, so easy ...

這個包的厲害之處在于,除了強大的組件本身,還提供了一個數(shù)據(jù)平臺直接把核心組件展示出來,供用戶一邊體驗,一邊研究代碼,顯著地降低了學(xué)習成本。不過這個平臺只展示了一部分的控件,想要系統(tǒng)學(xué)習,還是得鉆研官方文檔。
2. 實用控件
2.1 下拉框
下拉框主要是pickerInput函數(shù),其中不同的參數(shù)值可以實現(xiàn)不同的效果。
2.1.1 普通單選下拉框
pickerInput(
inputId = "Id081",
label = "Default",
choices = c("a", "b", "c", "d")
)

2.1.2 分組下拉框
將枚舉值分組,更加清晰有條理,也更便于查找。
pickerInput(
inputId = "Id082",
label = "Options group",
choices = list(
lower = c("a", "b", "c", "d"),
upper = c("A",
"B", "C", "D"))
)

2.1.3 多選下拉框
pickerInput(
inputId = "Id083",
label = "Multiple",
choices = attr(UScitiesD, "Labels"),
multiple = TRUE # 單選與多選的參數(shù)
)

2.1.4 搜索下拉框
pickerInput(
inputId = "Id084",
label = "Live search",
choices = attr(UScitiesD, "Labels"),
options = list(
`live-search` = TRUE) # 搜索的參數(shù)
)

2.1.5 全選下拉框
pickerInput(
inputId = "Id094",
label = "Select/deselect all options",
choices = LETTERS,
options = list(
`actions-box` = TRUE),
multiple = TRUE
)

2.1.6 帶子標題的下拉框
下拉框每個標題帶子標題,可起來信息補充作用。
pickerInput(
inputId = "Id093",
label = "Subtext",
choices = rownames(mtcars),
choicesOpt = list(
subtext = paste("mpg",
mtcars$mpg,
sep = ": ")) # 子標題
)

2.1.7 帶圖標的下拉框
其實實用性不強,不過可視化效果更好了。
pickerInput(
inputId = "Id092",
label = "Glyphicon",
choices = c("glyphicon-cog", "glyphicon-play", "glyphicon-ok-sign",
"glyphicon-arrow-right", "glyphicon-euro", "glyphicon-music"),
choicesOpt = list(
icon = c("glyphicon-cog", "glyphicon-play",
"glyphicon-ok-sign", "glyphicon-arrow-right", "glyphicon-euro",
"glyphicon-music") # 指定每個標題的圖標
)
)

2.3 日期選擇器
2.3.1 離散日期篩選
airDatepickerInput(
inputId = "multiple",
label = "Select multiple dates:",
placeholder = "You can pick 5 dates",
multiple = 5, clearButton = TRUE
)

同樣的函數(shù),如果把參數(shù)multiple和range都改成FALSE,則變成單日期篩選;如果把multiple和range都改成TRUE,則變成連續(xù)日期區(qū)間篩選。
2.4 單選框&復(fù)選框
2.4.1 單選框

awesomeRadio(
inputId = "Id003",
label = "Radio with status",
choices = c("A", "B", "C"),
selected = "B",
status = "warning"
)

prettyRadioButtons(
inputId = "Id036",
label = "Choose:",
choices = c("Click me !", "Me !", "Or me !")
)
2.4.2 復(fù)選框

awesomeCheckboxGroup(
inputId = "Id001",
label = "Checkboxes with status",
choices = c("A", "B", "C"),
inline = TRUE,
status = "danger"
)

prettyCheckboxGroup(
inputId = "Id032",
label = "Choose:",
choices = c("Click me !", "Me !", "Or me !")
)
2.5 二元單選框
其實就是一個二元值的切換。

switchInput(
inputId = "Id015",
label = "My label",
labelWidth = "80px"
)

materialSwitch(
inputId = "Id077",
label = "Primary",
value = TRUE,
status = "primary"
)
2.6 復(fù)選按鈕
其實從程序的角度來說,復(fù)選按鈕和復(fù)選框沒有本質(zhì)區(qū)別,都是捕捉用戶選中哪些的動作,返回對應(yīng)的參數(shù)值傳給后端。不過給人的體驗不同:復(fù)選按鈕較大,所以一般用來執(zhí)行較大的邏輯轉(zhuǎn)換,比如切換數(shù)據(jù)源、變更計算邏輯等;而復(fù)選框項小,所以一般只用于參數(shù)的切換。

checkboxGroupButtons(
inputId = "Id058",
label = "Label",
choices = c("A",
"B", "C", "D"),
justified = TRUE,
checkIcon = list(
yes = icon("ok",
lib = "glyphicon"))
)
2.7 數(shù)值篩選
單值篩選與數(shù)值區(qū)間篩選。

noUiSliderInput(
inputId = "noui1",
min = 0, max = 100,
value = 20
),
noUiSliderInput(
inputId = "noui2", label = "Slider vertical:",
min = 0, max = 1000, step = 50,
value = c(100, 400), margin = 100,
orientation = "vertical",
width = "100px", height = "300px"
)
上面的交互方式是拖動,此外還有另一種交互方式,直接輸入——這個更加實用一點。

numericRangeInput(
inputId = "noui1", label = "Numeric Range Input:",
value = c(100, 400)
)
2.8 多維表單篩選
盡管DT::datatable()對象自帶一部分交互和搜索屬性,但并不支持多維度聯(lián)動篩選;以下示例中能支持這種功能,當用戶在一個篩選框中確定了值之后,其他下拉框的取值范圍就確定了。 R的數(shù)據(jù)是存在內(nèi)存中的,當用戶確定一個維度值后,可以快速篩選計算其他維度的取值范圍。

panel(
pickerGroupUI(
id = "my-filters",
params = list(
manufacturer = list(inputId = "manufacturer", title = "Manufacturer:"),
model = list(inputId = "model", title = "Model:"),
trans = list(inputId = "trans", title = "Trans:"),
class = list(inputId = "class", title = "Class:")
)
), status = "primary"
)
那么更進一步,每一個篩選維度也支持多選。

panel(
selectizeGroupUI(
id = "my-filters",
params = list(
manufacturer = list(inputId = "manufacturer", title = "Manufacturer:"),
model = list(inputId = "model", title = "Model:"),
trans = list(inputId = "trans", title = "Trans:"),
class = list(inputId = "class", title = "Class:")
)
), status = "primary"
)
2.9 折疊式控件包
文檔里的函數(shù)名為dropdownButton,結(jié)合交互效果,自己起了上面那個名稱。對于高維數(shù)據(jù)分析(盡管不太多,但肯定有)場景,.將所有篩選維度直接平鋪顯然會影響用戶體驗;通過將相關(guān)性強的維度組合封裝打包,既能使頁面簡潔,又能提升查詢的效率和體驗。

dropdownButton(
inputId = "mydropdown",
label = "Controls",
icon = icon("sliders"),
status = "primary",
circle = FALSE,
sliderInput(
inputId = "n",
label = "Number of observations",
min = 10, max = 100, value = 30
)
從示例代碼中可以看到,dropdownButton()函數(shù)里可以封裝多個控件。