Snap.svgで内側領域の塗り分けの設定(fill-rule)に気をつけようという話

Snap.svg、すごいですよね。
あれでアニメーション作るとめちゃ楽しいですね。

さて、遊んでいる時に、困ったことがあり、数十分作業が止まったので、それの解決方法をメモしておきます。

##環境
 - Snap.svg 0.5.1 (読み込んで使用)
 - Firefox 57.0.1 (表示用ブラウザ)
 - InkScape 0.92 (パス作成用)

#内側が思ったように塗り分けられなかった
##問題のPath図形
問題のPath図形は以下の様なものです。長いので、以後`省略`と書きます。
（パスが異常に長いのは、趣味垢用に作っていたものの流用なので許してください。）

```
m 208.90541,109.29049 
a 2.776174,1.2825703 56.427847 0 1 0.17457,2.82556 2.776174,1.2825703 56.427847 0 1 -2.63953,-1.92948 2.776174,1.2825703 56.427847 0 1 -0.17457,-2.82557 2.776174,1.2825703 56.427847 0 1 2.63953,1.92949 
z 
m -7.6781,-9.03334 
c -1.38619,7.72423 -0.87929,12.29629 2.92643,15.66947 3.63687,2.44904 6.89158,-0.27701 7.59069,-3.58952 l 7.31827,3.98818 -3.91191,-7.35347 c 4.18733,-0.94355 5.73619,-4.5737 3.68133,-7.54654 -3.13739,-3.778909 -8.23264,-4.527779 -15.63278,-3.116419 -0.0367,0.008 0.48808,-1.9531 0.48808,-1.9531 0.70114,-0.23214 2.17497,-0.7302 2.17431,-1.07625 -0.003,-0.31091 -2.15625,-0.73908 -2.15625,-0.73908 -0.4811,0.26621 -1.18982,1.43616 -1.95937,2.67939 -0.94574,-0.51419 -2.17534,-1.16488 -2.49479,-0.88413 -0.24015,0.24378 0.29808,1.47343 0.9046,2.45516 0,0 -2.71018,1.650499 -2.70297,1.926699 0.043,0.0607 0.41039,2.18349 0.72963,2.16888 0.32026,-0.006 0.9949,-1.77835 1.08578,-2.16491 0,0 2.00074,-0.47543 1.95888,-0.46435 
z 
m 10.86239,5.84155 
a 2.7761738,1.2825702 34.267371 0 0 2.82323,0.20883 2.7761738,1.2825702 34.267371 0 0 -1.89732,-2.66272 2.7761738,1.2825702 34.267371 0 0 -2.82323,-0.20885 2.7761738,1.2825702 34.267371 0 0 1.89732,2.66274 
z
```

InkScapeで以下のようなSVGファイルを作り、読み込みました。

```html:sample_risou.html
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="420px" height="297px" style="background-color:#B2243C"> <path
       id="path8443-6-3"
       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.29069689;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
       d="省略"
       inkscape:connector-curvature="0"
       inkscape:label="center_icon" /></svg>
```
すると、下のように表示されます。
![正しい写真.PNG](https://qiita-image-store.s3.amazonaws.com/0/220092/6471dbfa-059d-de63-bbb5-dbd3acb805d3.png)


##うまく行かなかったソース
```html:sample.html
  <script src="./snap.svg.js"></script>
  <svg id="p" version="1.1" xmlns="http://www.w3.org/2000/svg"
    width="420px" height="297px"
    style="background-color:#B2243C"> 
  </svg>
```
このSVGに以下のようなソースでパス図形を表示させます。

```js:sample.js
  Snap("#p").path(省略).attr({
    "fill":'#ffffff'
  })
```

で、`longpath`ですが、
これを作画してみると、以下のようになってしまいます。
![穴が一つしか空いていない写真.PNG](https://qiita-image-store.s3.amazonaws.com/0/220092/9e4ba65f-1bbf-cee7-99e5-752257cfcda9.png)


穴が一つしか空いていません。
これは大きな問題です。
#原因
InkScapeが生成したSVGファイルの、長ったらしいstyle属性の中身に原因がありました。

```
  opacity:1;
  fill:#ffffff;
  fill-opacity:1;
  fill-rule:evenodd;
  stroke:none;
  stroke-width:0.29069689;
  stroke-linecap:round;
  stroke-linejoin:miter;
  stroke-miterlimit:4;
  stroke-dasharray:none;
  stroke-dashoffset:0;
  stroke-opacity:1;
  paint-order:fill markers stroke
```
多くは大したことのないデータですが、問題はこれの

```
  fill-rule:evenodd;
```
です。
これをうまくいかなかったJavaScriptに、

```js:sample.js
  Snap("#p").path(省略).attr({
    "fill":'#ffffff',
    "fill-rule":"evenodd"
  });
```
このようにいれてやると、思った通りに表示されました。
##解説
そもそも、何故、一つのパス図形で、内側でくり抜かれるという表現ができるかというと、SVGが"内側"についてのルールを定めているからなんです。
そのルールを指定してあげるのが、この`fill-rule`でした。
[SVG仕様(日本語訳)の当該説明箇所](https://triple-underscore.github.io/SVG11/painting.html#FillRuleProperty)

自動生成で過剰に生成される長いソースの中に、とても重要な情報が含まれていることもあるので注意しよう、という話でした。