高速CSSスプライト出力環境を用意してみる【vagrant+glue】

#はじめに
複数の画像を一つにまとめてCSSで表示をコントロールする、いわゆるCSSスプライトといった手法は、
もはやデザイナーを含めフロントエンド制作に携わるものとしては、必須スキルとなってきているのではないでしょうか。

理屈さえ分かっていれば画像とCSSは手動でも作成できるわけですが、かなり面倒です。
修正要望のたび、いちいち手で調整していくなどあまりに過酷、正気の沙汰ではありません。

そこで今回は、簡単かつ自動的にCSSスプライトが作成できる環境を用意してみようと思います。
（多分）難しい知識もいらず、スプライトに特化した環境がさくっとできるので、
これまでスプライトを試したことのない方、もしくは他の方法でスプライトを実行している方でも、
一度お試しいただくと良いことがあるかもしれません:)。


#スプライトを実現する方法
スプライト画像を自動的に生成するには、主に以下の方法があるかと思います。

|方法|デメリット|
|:----|:----|
|webサービスを使う|ネット環境が必要。外部に画像をアップしなければならない |
|sass/compassといったプリプロセッサを使う|プリプロセッサの導入が必要。処理に比較的時間が掛かる|
|grunt/gulp といったタスクランナーを使う|↑と同じような理由|

それぞれ記述しているように、場合によってはデメリットが致命的なものとなってしまうこともあります。
そこで他にも何か良いものは無いかと探していた所、__glue__ というgreatなツールを見つけたのでこちらを使っていきたいと思います。


#glueを使うメリット

* スプライトに特化しているため処理が早い
* シンプルで分かりやすく、オプションで簡単に出力情報を制御できる
* sass/compassといった他ツールに依存しないため、手軽に導入できる（既存の環境に手を入れずに済む）


#スプライト出力環境の概要

1. vagrantで仮想サーバを用意（このスプライトのみに使用）
1. 仮想サーバ内に、スプライトの元になる各単体画像を格納
1. CUIでコマンドを叩くことで、「CSSファイル」「スプライト画像」が仮想サーバ内に自動出力
1. 出力先、出力ルールなどはオプションで、簡単かつある程度細かく制御可能
1. 生成されたCSS・画像を仮想サーバより取り出す

※ローカルにglueをインストールしても良いのですが、今回はvagrantを使ってみようと思います。
※vagrant, virtualBoxはあらかじめインストール済みとします

#インストールから実行までの手順
##主な流れ

* vagrantでサーバ環境を作成
* サーバにwebサーバをインストール
* サーバーにglueをインストール
* 実行する前準備
* コマンド実行

## vagrantでサーバ環境を作成

###baseBoxの追加
```
$ vagrant box add ubuntu14.04 https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box
```
boxにubuntuを追加します
※OSは何でも良いかと思いますが、ubuntuが一番簡単にインストールできたのでこちらを使ってみます

### 仮想サーバの初期設定

* Desktop/../glue/　などローカルの適当な場所にディレクトリを作成しておきます。
* cmd.exeなどCUIでそこまで移動し、仮想サーバの初期設定を行っていきます

```
$ cd ...glue/
$ vagrant init ubuntu14.04
```
* 作成されたVagrantfileを編集します
    * config.vm.network "private_network", ip: "192.168.33.10" のコメントアウト（#）を外す
* vagrantを起動します（vagrant up）
* winscpなどのsftpソフトで仮想サーバにアクセスできるか確認します
    * 192.168.33.10, ID: vagrant, PW: vagrant


## webサーバをインストール
格納場所および出力先を用意するために、webサーバを入れました。
※とりあえず場所の確保だけなので、その他設定はしていません

```
$ vagrant ssh
$ sudo apt-get install apache2
```

## glueのインストール

```
$ sudo apt-get install libjpeg62 libjpeg62-dev zlib1g-dev python-dev python-pip
$ sudo pip install glue
```

※[公式サイト](http://glue.readthedocs.org/en/latest/installation.html)では`python-pip`の指定はありませんでしたが、自分の環境ではエラーが出たのでインストールしています
また、`apt-get install glue-sprite` で簡単にglue-spriteというツールもインストールできますが、オプションがglueの方が充実していたのでglueの方を使いました

## 実行する前準備

```
$ sudo chown vagrant /var/www/html/
$ cd /var/www/html/
$ mkdir sprite
```

/var/www/html/をvagrantユーザに変更します。
spriteディレクトリを作成し、その中に元になる画像をsftpソフトなどでアップします。
※spriteという名称は何でも構いません

## コマンド実行

```
$ glue sprite output
```

あっという間に、outputディレクトリが作成され、sprite.cssとsprite.pngが中に出力されているかと思います。
後はsftpソフトなどで取り出し利用することができます。

__～ Fin ～__

# コマンドにオプションを付けて使いやすくする
コマンドにオプションを付けることで、より細かく制御することができます。
オプションは色々あるので、詳しくは、[公式サイト](http://glue.readthedocs.org/en/latest/options.html)を見ていただければと思いますが、
せっかくなので自分がよく使うコマンドを紹介したいと思います。

```
$ glue sprite --img=img --css=css --namespace=spr --sprite-namespace= --margin=10 --separator=__ --css-template=my_template.jinja
```

以下、順番に説明します。

|オプション|説明|
|:----|:----|
|--img=imgDir|./imgDir/にsprite.pngを出力します。|
|--css=cssDir|./cssDir/にsprite.cssを出力します。|
|--namespace=spr|cssのclass名の接頭辞になります。<br>デフォルトではspriteが付きます。<br>ここでは__spr__にしています。|
|--sprite-namespace=|cssのclass名の接頭辞の後に、格納ディレクトリ名が付きます。<br>ここでは__「空」__にしています。|
|↑|上記指定で、__.spr\_\_画像ファイル名__ というclassで出力されます。<br>何も設定しないと、この場合cssのclass名は__.sprite\_\_sprite\_\_画像ファイル名__となります。|
|--margin=10|スプライト内の各画像の隙間を設定します。<br>隙間を0にすると、ブラウザの拡大率によっては隣の画像の端が見えてしまうことがあるため設定しています|
|--separator=__|cssのclass名の各namespaceの区切りを指定します。<br>デフォルトでは - となります。<br>ここでは __（アンダースコア2つ） を指定しています。<br>キャメルケースにしたい場合は、 --separator=camelcaseと指定します。|
|--css-template=my_template.jinja|cssを独自のテンプレートに当てはめて出力します。<br>この場合、html/直下に、my_template.jinjaというファイルを配置しておきます。<br>テンプレートを使用することで、スタイルの細かい設定が可能になります。|

## my_template.jinjaのサンプル
試しに使っているjinjaファイルを下記に記述してみますので、何かの参考になれば幸いです。

```my_template.jinja
/* glue: {{ version }} hash: {{ hash }} */
{% for image in images %}.{{ image.label }}{{ image.pseudo }}{%- if not image.last %}, {%- endif %}{%- endfor %}{
  background-image:url('{{ sprite_path }}');
  background-repeat:no-repeat;
  display: inline-block;
  line-height: 2;
  overflow: hidden;
  height: 0;
}
{% for image in images %}
.{{ image.label }}{{ image.pseudo }}{
  background-position:{{ image.x ~ ('px' if image.x) }} {{ image.y ~ ('px' if image.y) }};
  padding-top: {{ image.height }}px;
  width:{{ image.width }}px;
}
{% endfor %}
```

__～ Fin ～__