ShinyをCSSで拡張しようぜ! - Rでつくるウェブアプリケーション -
Shiny
先日、記事で「Shiny」というパッケージを用いたウェブアプリケーションの作成方法についてお話ししました。今回は、そんなウェブアプリケーションをCSS(cascading style sheets)で拡張しようじゃないか!というお話です。こちらの記事により詳しく書かれています(Shiny - Style your apps with CSS)が、自分の勉強用に作成しています。
CSSはご存知の通り、HTMLで書かれた構造をデザインするためのものです。ShinyのインターフェースがHTMLで書かれているため、オリジナルのCSSを作成することによって、Shinyの見栄えを奇麗にすることができます。CSSについて勉強したい人はコードアカデミーなどで調べればコースはいっぱいありますので、ここでは割愛。
ShinyのアプリケーションでCSSを取り込む方法は3つあります。
- wwwというディレクトリーの中にスタイルシートを入れる方法
- HTMLのヘッダーにCSSへのリンクを張る方法(これが一番自然?)
- styleをHTMLタグの中に直接書き込む(これは、ウェブだとあまり推奨されない)
これをそれぞれ解説していきます(今日は、時間の都合で最初の1つだけです)。まずは、一番最初のwwwのディレクトリーにいれる方法について。
wwwというディレクトリーの中にスタイルシートを入れる方法
まずは、イメージをみせるために、スタイルシートを用いない場合のデザインを示します。かなり簡素なデザインで、、、一面真っ白です。
それをスタイルシートを導入するだけで、こんな感じで変わります。
このようなウェブアプリケーションを作成するために必要なものを書いてきます。先日の記事でも書いたようにshiny appは、2つの要素からなります。アプリケーションを実際に動かすサーバー側と、表示するインターフェースです。これらのファイルは、次のようにつくりました。
#ui.R library(shiny) #define UI shinyUI( fluidPage( theme = "bootstrap.min.css", #wwwフォルダーの中のcssファイルを指定 headerPanel("New Application"), sidebarPanel( sliderInput("obs", "Number of observations:",min = 1, max = 1000, value = 500) ), mainPanel(plotOutput("distPlot")) ) )
#server.R library(shiny) #define server logic required to plot various variables against mpg shinyServer(function(input, output){ output$distPlot <- renderPlot(function(){ dist <- rnorm(input$obs) lim_x=c(min(dist),max(dist)) lim_y=c(0,0.5) hist(dist,xlim=lim_x,ylim=lim_y,probability=T) par(new=T) plot(density(dist),xlim=lim_x,ylim=lim_y,xlab="",ylab="",main="") }) })
そして、次にスタイルシートです。今回はブートストラップのCSSを利用しましょう。こちらからダウンロードすることができます。Bootswatch: Free themes for Bootstrap。ここから好きなテーマを選んで、ダウンロードします。そして、次のようにディレクトリーを構成します。ここでwwwフォルダーの中に入っているのが上のページからダウンロードしたbootstrap.min.cssです。
あとは、ターミナルから、このフォルダーのあるdirectryに移動して、以下のコマンドを実行すると、先ほどのようなCSSの反映されたshiny appが完成します!
R -e shiny::runApp('shiny_css')
ui.Rに書き込む方法
ちなみに、今回はthemeという関数でcssを参照しましたが、別の方法もあります。ui.Rの中に書き込むというものです。bootstrap.min.cssのファイルはwwwのフォルダーの中に入れっぱなしでOKです。で、ui.Rだけ以下のように書き換えてください。ここで、以下のコードを見ていただければわかるように、hrefのパスの中に"./www"のような記述は必要ありません。shinyではwwwというサブディレクトリは特別な意味を持つようです。
#ui.R library(shiny) #define UI shinyUI( fluidPage( tags$head( tags$link(rel="stylesheet",type="text/css",href="bootstrap.min.css") ), headerPanel("New Application"), sidebarPanel( sliderInput("obs", "Number of observations:",min = 1, max = 10000, value = 500) ), mainPanel(plotOutput("distPlot")) ) )
同様に、ターミナルからappを動かせば同じ結果が得られるはずです。