9 スライス

9-Slice Scaling別名:9 パッチ、ナインスライス、9 分割拡大

概要

UI の枠やボタンの画像を縦横 3 つずつ、計 9 つの領域に分けて拡大する方法。四隅は元の大きさのまま描き、辺は一方向にだけ、中央は縦横に伸ばす。角の丸みや枠線の太さを保ったまま、1 枚の画像を好きな大きさで使える。

デモ

デモを読み込んでいます
左は画像全体を単純に拡大、右は 9 スライスで拡大しています。スライダーか、パネル右下の角のドラッグで大きさを変えられます。境界の位置を小さくして角の丸みにかかるようにすると、右側でも角が崩れます。

使われる場面

  • ゲームやアプリの UI

    ダイアログの枠、ボタン、体力ゲージの枠を、1 枚の小さな画像から任意の大きさで作る。表示する内容に合わせて枠を伸び縮みさせられる。

  • 画面の大きさや言語の違いへの対応

    画面の解像度や縦横比が変わっても、同じ画像で枠を描ける。翻訳で文字列の長さが変わるボタンにも対応しやすい。

  • 吹き出しとメッセージウィンドウ

    会話の吹き出しを、台詞の長さに合わせて広げる。吹き出しのしっぽは、別の画像として重ねることが多い。

  • Web の枠線

    CSS の border-image は、画像を 9 つに分けて要素の枠に使う仕組みで、9 スライスと同じ考え方である。

判断基準

こういうときこうする
角が丸い、または角や枠に装飾がある UI 画像を、いろいろな大きさで使う9 スライスを使う。大きさごとに画像を用意する必要がなくなる。
境界の位置を決める角の丸みや装飾が四隅の領域に収まるように置く。辺の領域には、伸ばしても見た目が変わらない一様な部分だけを残す。
辺や中央に模様がある伸ばすと模様も引き伸ばされる。辺と中央を伸ばす代わりに繰り返して敷き詰める設定を使うか、模様を別の画像として重ねる。
四隅の大きさの合計より小さく表示することがある四隅どうしが重なって崩れる。最小の大きさを決めておくか、四隅ごと縮小する。
角も装飾もない、単純な四角形の枠9 スライスは不要で、塗りと線の描画で足りる。

こう見えたら

指示の例

  • ボタンを横に伸ばしたら、角の丸みと左右の枠線がゆがんだ。枠の画像を 9 スライスで拡大して

  • 9 スライスにしたのに、角の丸みの一部が伸びている。境界の位置を内側にずらして、角の丸み全体が四隅に収まるようにして

  • 枠の辺の模様が引き伸ばされている。辺は伸ばさずに、繰り返して敷き詰める設定にして

  • 小さく表示すると、角どうしが重なって崩れる。枠の最小の大きさを、四隅の合計より大きくして

詳細

伸ばしてよい部分と、伸ばしてはいけない部分

画像を単純に拡大すると、画像の中のすべてが同じ比率で伸びる。横長に伸ばせば、丸い角は横長の楕円になり、左右の枠線は上下の枠線より太くなる。UI の枠では、角の形と枠線の太さはそのまま保ち、内側の領域だけを広げたい。

9 スライスは、画像を縦と横それぞれ 2 本の境界線で 9 つの領域に分け、領域ごとに伸ばし方を変える。

  • 四隅:伸ばさない。元の大きさのまま描く。
  • 上下の辺:横方向にだけ伸ばす。
  • 左右の辺:縦方向にだけ伸ばす。
  • 中央:縦と横の両方に伸ばす。

伸ばす量の計算

元の画像の幅を WW、左右の境界の位置を端からそれぞれ ll と rr、表示したい幅を W′W' とする。四隅の幅 ll と rr は変えないので、伸ばすのは中央の区間だけで、その拡大率は次のようになる。

sx=W′−l−rW−l−rs_x = \frac{W' - l - r}{W - l - r}

縦方向も同じように、上下の境界の位置から拡大率を求める。実装では、元の画像と表示先のそれぞれで横と縦の区切りの位置を 4 つずつ求め、9 つの領域を一つずつ描く。

// 元画像の区切りと、表示先(幅 W2、高さ H2)の区切り
const xs = [0, left, W - right, W], xd = [0, left, W2 - right, W2];
const ys = [0, top, H - bottom, H], yd = [0, top, H2 - bottom, H2];
for (let j = 0; j < 3; j++) {
  for (let i = 0; i < 3; i++) {
    ctx.drawImage(img,
      xs[i], ys[j], xs[i + 1] - xs[i], ys[j + 1] - ys[j],        // 元画像の領域
      x + xd[i], y + yd[j], xd[i + 1] - xd[i], yd[j + 1] - yd[j]); // 表示先の領域
  }
}

見分け方と落とし穴

9 スライスで描いた枠は、大きさが変わっても角の丸みと枠線の太さが変わらない。単純に拡大した枠は、横に伸ばすと左右の枠線が太くなり、角の飾りが楕円につぶれる。

境界の位置は、角の丸みや装飾が四隅の領域に収まるように決める必要がある。境界が丸みにかかっていると、丸みの一部が辺の領域に入って一方向に伸び、角が崩れる。デモで境界の位置を小さくすると、この崩れ方が見える。

辺と中央は伸ばされるので、そこにある模様は引き伸ばされる。また、画像を拡大するときの補間で、境界の隣の領域の色が混ざり、つなぎ目に細い線が出ることがある。複数の画像を 1 枚にまとめて使う場合は、各画像のまわりに余白を取っておくと防げる。

関連