本日の話題は、Shiny
のタブのアイコンを動的に切り替えて表示する方法です。
タブにアイコンを表示することは標準機能として簡単にできますが、そのアイコンを動的に切り替える方法がいまいちわからなかったので
調査した結果をメモします。
上記の画像でクリップのアイコンをプログラムで切り替える方法です。
例によってややマニアックな話題ですが、このブログは自分が必要と思って調べた話題をメモ的に残しているので
こういった話題が多くなりますがご了承ください。
tabPanelへのアイコンを表示する方法の基本を確認
Shiny
のダッシュボードのタブにアイコンを表示することは標準の機能を使えば簡単に実現できます。
使い方は、以下のマニュアルを始めいろいろなブログなどで確認できます。
ではこの基本形を参考プログラムを以下に示しました。
この例では、見やすくするためにダッシュボードのBodyを切り出しています。基本はtabPanel
の中で`icon’の種類を指定するだけです。
library(shiny) library(shinydashboard) dbBody = dashboardBody( tabsetPanel(id = "tbID", tabPanel(value = "tab1", title = "Sample", icon = icon("flag"), #contents br(), "This is sample tab!" ) ) ) ) ui = { dashboardPage( dashboardHeader(), dashboardSidebar(), dbBody ) } server <- function(input, output) { } shinyApp(ui, server)
プログラムを実行するとタブに旗のアイコンが表示されます。このアイコンの種類を変えるには、
font awesomeかgryphiconsのアイコンを指定する必要があります。そのあたりの詳細はここを参照してください。
※なおtabsetPanel
のid=
やtabPanel
のvalue=
は省略することも可能です。
プログラムからタブを指定して表示させる場合などにはこれらのIDを一意の名称で指定しておく必要があります。
アイコンの動的な変更
さてここで本日の話題のタブのアイコンを動的に切り替える方法についてです。
結論から言えば、ポイントは、タブのタイトル部分をuiOutput
で表示することです。
まずは以下のサンプルプログラムを参照ください。
library(shiny) library(shinydashboard) library(shinyWidgets) tabImage = data.frame( val = c("clip", "caution", "crown") ) tabImage$img = c( sprintf("<img src='./clip.png' width=20px><div class='tbicn'>%s</div></img>", tabImage$val[1]), sprintf("<img src='./caution.png' width=20px><div class='tbicn'>%s</div></img>", tabImage$val[2]), sprintf("<img src='./crown.png' width=20px><div class='tbicn'>%s</div></img>", tabImage$val[3]) ) dbBody = dashboardBody( tags$head(tags$style(" .tbicn{ display: inline; vertical-align: middle; padding-left: 10px; }")), tabsetPanel(id = "tbID", tabPanel(value = "tab1", title = uiOutput("title_panel"), fluidRow( column(width=3, pickerInput("tabImg", label="Mark", choices = tabImage$val, choicesOpt = list(content = tabImage$img)) ), column(width=9, textAreaInput("inputTextInd1", height = "2.6em", label = "", placeholder = "comments here on this trial") ) ) ) ) ) ui = { dashboardPage( dashboardHeader(), dashboardSidebar(), dbBody ) } server = function(input, output) { output$title_panel = renderUI({ switch(input$tabImg, "clip" = tagList("Trial ",img(src="./clip.png", width="20px", height="20px")), "caution" = tagList("Trial ",img(src="./caution.png", width="20px", height="20px")), "crown" = tagList("Trial ",img(src="./crown.png", width="20px", height="20px"))) }) } shinyApp(ui, server)
このプログラムを走らせると以下のような画面になります。
このプログラムでは3つのアイコン(画像)を使っていますが(clip, caution, crown)、
この画像は自身の環境に合わせて正しいフォルダーの所在と画像名を指定してください。
R-Shinyのプロジェクトで管理している場合には、作法に従ってプログラムがある階層と同じところにwww
ホルダーを作ってその中に画像を入れてください。そのうえで画像の場所は、img src="./clip.png"
のように./画像名
ですね。
tabPanelへの表示
tabPanel
への表示は比較的簡単です。
プログラムの44から48行目でタブに表示する画像を作り、
プログラムの22行目title = uiOutput("title_panel"),
で表示しています。
表示する内容はtagList
で文字(”Trial”)と画像(img)を並べて表示しています。
プルダウンによる選択リストへの画像の表示
続いてどの画像を表示するかの選択側のプログラムですが、この選択にはshinywidget
のpickerInput
を利用しています。
一般的にはプルダウンでの選択にはselectInput
を使いますが、これを利用して選択肢に画像を表示させる方法が調べた限りややこしそうだったので、
shinywidget
の作者によるこの回答や
このサイトを参考にpickerInput
を利用して作成しました。
プログラムの4−6行目にtabImage$val
にプルダウンの選択肢を入れて、プログラムの7−11行目でtabImage$img
でそれぞれの選択肢に対する
画像をセットしています。それを利用してプログラムの25−27行目でpickerInput
で表示させています。
このpickerInput
のなかでchoicesOpt
の部分が画像表示の肝になっています。このあたりは上記のサイトを参考にとりあえず動くサンプルは作成していますが、本来はもう少し具体的にchoicesOpt
の詳細を調査して他の手法などについても検討したいところです。ところが、どうも調査が甘いのかselectInput
のchoicesOpt
の使い方に関する詳細がわかるサイトがあまり見つかりませんでした。
とりあえず以下のサイトにはいくつか有効なサンプルが掲載されていますので参考になるかと思われますのでメモしておきます。また、詳しくわかったらこのブログにUPしたいと思います。
なお、プログラム14−19行目はリスト画面でテキストとアイコンを並べて表示するためにセットしています。
tbicn
のクラスではインライン表示をするように指定しています。もしこの部分がないと文字とアイコンが
縦並びに出力されますので、そちらがお好みの場合にはこの部分をコメントアウトしてください。
さらなる拡張
この例ではタブが一つの例ですが、実際のプログラムでは複数のタブを持つことが多いかと思います。その場合には、
tabPanel
のvalue
が重複しないように設定したり、uiOutput("title_panel")
のidをタブごとにtitle_panel1
, title_panel2
のように
変更して一意に設定しておく必要があるのでご注意ください。