[SVG] viewBoxについての考察

## まずベースとなるサンプルを用意しておきます

200*200のサイズで、背景をグレイにして真ん中にオレンジの円をおきます。~~芸術的です。~~
左上に青い円も添えます。

```html
<svg width="200" height="200" viewBox="0 0 200 200" style="background: #ddd">
  <circle cx="100" cy="100" r="50" fill="orange" />
  <circle cx="0" cy="0" r="10" fill="blue" />
</svg>
```
![スクリーンショット 2015-10-06 21.11.38.png](https://qiita-image-store.s3.amazonaws.com/0/45822/3397be2e-e212-bcf0-11ec-070668cc9c4d.png)

## 基本的なこと

まず外側の`<svg width="200" height="200"`の部分の200*200がビューポート（描画エリア）のサイズです。

`viewBox="0 0 200 200"`が考察したいviewBoxですが、これの意味するところは。
「vievBox="x y width height"」

- x: 左上のx座標
- y: 左上のy座標
- width: 幅
- height: 高さ

と、書いたところで....分からないと思うので、以下事例を追って頂くのがよいと思います。



## まずは拡大してみる

`viewBox="0 0 100 100"`として、拡大します。

```html
<svg width="200" height="200" viewBox="0 0 100 100" style="background: #ddd">
  <circle cx="100" cy="100" r="50" fill="orange" />
  <circle cx="0" cy="0" r="10" fill="blue" />
</svg>
```

![スクリーンショット 2015-10-06 21.14.22.png](https://qiita-image-store.s3.amazonaws.com/0/45822/51b5c1a2-0457-d187-3669-eb6aa6fbb517.png)

## そのまま座標をずらし（数学で言う）第一象限を表示してみる

`viewBox="100 0 100 100"`という感じで、x座標を右に100ずらしました。

```html
<svg width="200" height="200" viewBox="100 0 100 100" style="background: #ddd">
  <circle cx="100" cy="100" r="50" fill="orange" />
  <circle cx="0" cy="0" r="10" fill="blue" />
</svg>
```

![スクリーンショット 2015-10-06 21.17.24.png](https://qiita-image-store.s3.amazonaws.com/0/45822/34e66f58-480f-8525-f454-eec672407fd5.png)


## では問題です。以下のソースはどうなるでしょうか？

`viewBox="0 0 100 200"`としました。xy座標は最初に戻しました。
ボックスが正方形ではありません。100*200の長方形です。外側の枠は変わらず200*200の正方形です。

```html
<svg width="200" height="200" viewBox="100 0 100 200" style="background: #ddd">
  <circle cx="100" cy="100" r="50" fill="orange" />
  <circle cx="0" cy="0" r="10" fill="blue" />
</svg>
```

どうなるのでしょうか？

僕は全然わかりませんでした。


## 正解と要因


上記の問題ですが、こうなります。

![スクリーンショット 2015-10-06 21.22.21.png](https://qiita-image-store.s3.amazonaws.com/0/45822/f69d1f91-7e2e-36dd-dbd4-d5c61189cb22.png)

僕は最初これでちんぷんかんぷんになりました。

なぜこうなるのかは、viewBoxと同じサイズ指定の枠を表示させることでわかりやすくなります。

```html
<svg width="200" height="200" viewBox="0 0 100 200" style="background: #ddd">
  <rect x="0" y="0" width="100" height="200" stroke="black" fill="none"/>
  <circle cx="100" cy="100" r="50" fill="orange" />
  <circle cx="0" cy="0" r="10" fill="blue" />
</svg>
```

![スクリーンショット 2015-10-07 20.31.57.png](https://qiita-image-store.s3.amazonaws.com/0/45822/af789903-0642-cd08-4e3e-e2c5e286e622.png)

真ん中に枠があります。こういうことですね。


## どういうことか？初期設定に依存しています。

ポイントは、ビューポートのエリアとviewBoxのエリアの縦横比がズレでいるとき、いったいどうなるのか？縦横比をキープするのか、それとも、どちらかに膨張したりするのか？ということが気になります。

その拡縮についての属性が、「preserveAspectRatio」という属性です。

デフォルトではこのようになっています。

```html
<svg width="200" height="200" viewBox="0 0 100 200" style="background: #ddd" preserveAspectRatio="xMinYMin meet">
  <rect x="0" y="0" width="100" height="200" stroke="black" fill="none"/>
  <circle cx="100" cy="100" r="50" fill="orange" />
  <circle cx="0" cy="0" r="10" fill="blue" />
</svg>
```

`preserveAspectRatio="xMidYMid meet"`←こいつです。

- xMidYMid: 均等な拡縮を強制し、xyのそれぞれ真ん中に配置。
- meet: 縦横比は維持し、veiwBoxを可能なかぎり大きく配置。

こんな感じです。なので、あえて均等を崩せば、以下のようにすることもできます。


```html
<svg width="200" height="200" viewBox="0 0 100 200" style="background: #ddd" preserveAspectRatio="none">
  <rect x="0" y="0" width="100" height="200" stroke="black" fill="none"/>
  <circle cx="100" cy="100" r="50" fill="orange" />
  <circle cx="0" cy="0" r="10" fill="blue" />
</svg>
```

![スクリーンショット 2015-10-07 20.58.43.png](https://qiita-image-store.s3.amazonaws.com/0/45822/c54db4d4-9a93-12fd-3932-e12c1708b400.png)

以上ありがとうございました。