gulp.spritesmithをレスポンシブに対応させる

※注意
この記事で紹介しているのは
[gulp-spritesmith](https://www.npmjs.com/package/gulp-spritesmith)
ではなくて
[gulp.spritesmith](https://www.npmjs.com/package/gulp.spritesmith)
です。
紛らわしいので、間違えないようにご注意を。

## sprite化は面倒くさい
既存のサイトでレスポンス速度向上のために、一部の画像をsprite化する運びになった。
自分で作成するのはだるいし、工数もかかるのでgulpを使って自動化できないかと思って、前に見た記憶を辿りながらたどり着いたのが
[gulp.spritesmith](https://www.npmjs.com/package/gulp.spritesmith)
↑これ

sprite化したい画像を特定のディレクトリにポコポコ投げ入れて、taskを回すとsprite画像を作成してくれて、sassとかstylusとかlessとかに変数を吐き出してくれる。

こういう便利なものを作成してくれる人には頭が上がらない。
感謝....圧倒的感謝!

## 使い方

### まずはinstall

```
$ yarn add gulp.spritesmith -D
```

### taskを追加

```javascript:gulpfile.js
gulp.task('sprite', () => {
	// pathの設定は適宜変えてくだしあ
	const spriteData = gulp.src('/path/to/sprite/*.png') // スプライト化したい画像を入れるディレクトリ
	.pipe(spritesmit({
		imgName			: '/path/to/img/contents-sprite.png', // sprite画像の名前
		imgpath			: '/path/to/img/contents-sprite.png', // sprite画像のpath
		cssName			: 'sprite.scss', // スプライト用のcssの名前
		cssFormat		: 'scss', // ファイルのフォーマット
		padding			: 5	// 画像のpadding
	}));
	spriteData.img.pipe(gulp.dest('./dest/path/to/sprite')); 			 // スプライト画像の出力先
	spriteData.css.pipe(gulp.dest('./src/path/scss/')); // スプライト用の scss ファイルの出力先
});
```

### 実行
実行すると、指定したパスの場所に`contents-sprite.png`っていうsprite化したい画像がひとまとまりになったファイルと、変数が格納されている`sprite.scss`っているscssファイルが作成される。

変数名は基本的に画像ファイルの名前に沿って作成される模様。
レスポンシブ対応とか考えてない場合は、そのまま`@import`するなりなんなりして、仕様すれば使えるはず。

## レスポンシブ対応したい
このままでも仕様は出来るが、当たり前だが画像が等倍で表示されてしまう。
要素の'width'や'height'に対して目一杯画像を広げたいので、それ用のmixinを作成する。

作成される変数の中身はこんな感じ。

```sass:sprite.scss
$sprite-image-name: 'sprite-image';
$sprite-image-x: 445px;
$sprite-image-y: 45px;
$sprite-image-offset-x: -445px;
$sprite-image-offset-y: -45px;
$sprite-image-width: 10px;
$sprite-image-height: 20px;
$sprite-image-total-width: 459px;
$sprite-image-total-height: 391px;
$sprite-image-image: '/path/to/contents-sprite.png';
$sprite-image: (445px, 45px, -445px, -45px, 10px, 20px, 459px, 391px, '/path/to/contents-sprite.png', 'sprite-image', );

// ~ 中略 ~

@mixin sprite-width($sprite) {
  width: nth($sprite, 5);
}

@mixin sprite-height($sprite) {
  height: nth($sprite, 6);
}

@mixin sprite-position($sprite) {
  $sprite-offset-x: nth($sprite, 3);
  $sprite-offset-y: nth($sprite, 4);
  background-position: $sprite-offset-x  $sprite-offset-y;
}

@mixin sprite-image($sprite) {
  $sprite-image: nth($sprite, 9);
  background-image: url(#{$sprite-image});
}

@mixin sprite($sprite) {
  @include sprite-image($sprite);
  @include sprite-position($sprite);
  @include sprite-width($sprite);
  @include sprite-height($sprite);
}

@mixin sprites($sprites) {
  @each $sprite in $sprites {
    $sprite-name: nth($sprite, 10);
    .#{$sprite-name} {
      @include sprite($sprite);
    }
  }
}

```

### レスポンシブ対応させるためのmixinを作成する


```sass:_sprite-responsive.scss
@charset "UTF-8";

// 変数が入っているscssをimport
@mixin sprite-responsive($sprite){
	$sheet-w	: nth($sprite, 7);
	$sheet-h	: nth($sprite, 8);
	$sprite-w	: nth($sprite, 5);
	$sprite-h	: nth($sprite, 6);
	$offset-x	: nth($sprite, 1);
	$offset-y	: nth($sprite, 2);
	$bg-path	: nth($sprite, 9);

	// テキストを隠す
	white-space: nowrap;
	text-indent: 100%;
	overflow: hidden;
	font-size: 0;
	
	background-image: url($bg-path);
	background-size: ($sheet-w / $sprite-w * 100 + 0%) ($sheet-h / $sprite-h * 100+ 0%);
	background-position: ($offset-x / ($sheet-w - $sprite-w) * 100 + 0%) ($offset-y / ($sheet-h - $sprite-h) * 100 + 0%);

	&:after{
		content: '';
		display: block;
		padding-top: ($sprite-h / $sprite-w * 100 + 0%);
	}

}
```

`nth($sprite, number)` で`$sprite`のリストにアクセスしている。
(この機能知らなかった...)

参考:
[HAIL2U.NET](https://hail2u.net/blog/coding/sass-lists.html)
[sassのnth()関数](http://sass-lang.com/documentation/Sass/Script/Functions.html#nth-instance_method)

`background-image`とかで演算式の後に`+ 0%`と記述しているのは単位を%にするため。
(他に良い方法が見つからなかった orz)



で、あとはこのファイルの以下に`@include`して書いていく感じ。

```sass:_sprite-responsive.scss

i.sprite{
	@include sprite-responsive($sprite-image);
	display: inline-block;
	width: 6px;
	height: 12px;
}
```

これで指定した`width`と`height`の中にちょうど良く収まってくれる...はず。

修正等があれば、書き直します。