前段日子逛全球最大****网站时,发现一个名为shinyWidgets的shiny扩展包,主要集成了数据平台中常用的控件,不少挺炫酷且实用;此文从产品设计和代码开发双重角度梳理总结这个包的实用控件体系,对于数据产品交互设计和数据产品开发具备一定参考价值。
1. demo体验
对于调包侠来说,没有什么问题是无法用一行代码解决的;如果有,就先加一行安装包的代码。
# 装包
install.packages("shinyWidgets")
# 调包
shinyWidgets::shinyWidgetsGallery()
# enjoy, so easy ...
这个包的厉害之处在于,除了强大的组件本身,还提供了一个数据平台直接把核心组件展示出来,供用户一边体验,一边研究代码,显著地降低了学习成本。不过这个平台只展示了一部分的控件,想要系统学习,还是得钻研官方文档。
2. 实用控件
2.1 下拉框
下拉框主要是pickerInput
函数,其中不同的参数值可以实现不同的效果。
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 # 单选与多选的参数
)
2.1.4 搜索下拉框
pickerInput(
inputId = "Id084",
label = "Live search",
choices = attr(UScitiesD, "Labels"),
options = list(
`live-search` = TRUE) # 搜索的参数
)
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
)
同样的函数,如果把参数multiple
和range
都改成FALSE,则变成单日期筛选;如果把multiple
和range
都改成TRUE,则变成连续日期区间筛选。
2.4 单选框&复选框
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 复选框
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 复选按钮
其实从程序的角度来说,复选按钮和复选框没有本质区别,都是捕捉用户选中哪些的动作,返回对应的参数值传给后端。不过给人的体验不同:复选按钮较大,所以一般用来执行较大的逻辑转换,比如切换数据源、变更计算逻辑等;而复选框项小,所以一般只用于参数的切换。
checkboxGroupButtons(
inputId = "Id058",
label = "Label",
choices = c("A",
"B", "C", "D"),
justified = TRUE,
checkIcon = list(
yes = icon("ok",
lib = "glyphicon"))
)
2.7 数值筛选
单值筛选与数值区间筛选。
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()
对象自带一部分交互和搜索属性,但并不支持多维度联动筛选;以下示例中能支持这种功能,当用户在一个筛选框中确定了值之后,其他下拉框的取值范围就确定了。 R的数据是存在内存中的,当用户确定一个维度值后,可以快速筛选计算其他维度的取值范围。
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 折叠式控件包
文档里的函数名为dropdownButton
,结合交互效果,自己起了上面那个名称。对于高维数据分析(尽管不太多,但肯定有)场景,.将所有筛选维度直接平铺显然会影响用户体验;通过将相关性强的维度组合封装打包,既能使页面简洁,又能提升查询的效率和体验。
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()
函数里可以封装多个控件。