〽️preserveAspectRatio。 〽️alignment。 〽️meet/slice。 〽️実践してみる。 〽️お疲れ様でした。
⬆︎SVGついてのまとめページはこちら。
こんにちは、「ふ」です。
ここのところSVGアニメーションの記事では、画像を読み込んでのいろんなアニメーションを扱っていますが、SVG領域に対し縦横比の違う画像を貼ると、どのようになるのでしょうか。
縦横比4:3のSVG領域に、16:9の画像を配置してみます。
■ HTML
■ CSS
CSSでwidthだけ100%に指定しました。
結果がこちら。
画像がSVG領域の上部に揃えられ、下の部分が空いてしまっています。
本来ならこう⬆︎したいところ。高さいっぱいに表示して、SVG領域の形でトリミング。
実現するには、「preserveAspectRatio」という長〜い名前の属性を<image>に指定してやらなければいけません。
今回はこのpreserveAspectRatio属性の挙動と、それを理解することで画像をSVG領域にぴったりと配置する方法について紹介していきます。
preserveAspectRatioは、Aspect Ratio(見た目の比率)をpreserve(保存する、維持する)という意味です。
元画像の縦横比を保ったまま、領域にぴったりと収めるための指定を行います。
値の前半はalignment(照準)を指定し、後半は処理の内容を指定します。それぞれの内容について、詳しくみていきましょう。
alignment(照準)とは何のためにあるのでしょうか。
画像の縦横比を保ったまま拡大・縮小すると、元画像と領域はそもそも比率が違うので、必ず隙間もしくははみ出しが生じます。
そうすると「領域と元画像のどの部分を揃えてから、高さ若しくは幅を合わせるか」によって表示結果は変わってきます。
今、4:3の領域に16:9の元画像があります。
双方の左端を揃えた状態で、元画像の高さを領域いっぱいまで引き伸ばしてみます。
左端を揃えたまま高さを合わせると、画像の右側がはみ出す結果となりました。
今度は中央を揃えた状態で高さを合わせます。
そうすると画像の両側が均等にはみ出しました。
このように、「元画像と領域のどの部分を揃えてから処理を行うか」を指定するのが、「照準を指定する」という意味です。
値はx、y方向それぞれを指定します。
ここでいう「min/mid/max」は、座標的な意味での最小値、中間値、最大値を指します。
SVGの座標は左上を原点とし、右に向かってx軸、下に向かってy軸が伸びています。
仮に、
x : min
y : max
とすると、
元画像のxmin(左端)と領域のxmin(左端)、
元画像のymax(下端)と領域のymax(下端)
を揃えて照準とする、という意味に成増。
〜もう1つくらい例をあげてみます。
xmid
ymin
だと、
x方向は真ん中(中間値)、y方向は上端(最小値)で揃えられます。
イメージ掴めたでしょうか?
実際の表記はxの指定とyの指定を一撃で表現します。例えば「x-mid-y-max」であれば、
のように記述します。
一見キャメルケースが複雑に感じるかもですが、
x - mid - y - max
と分解してみれば納得できますね。
指定値の後半部分は処理方法を記述します。値はmeetもしくはsliceのいずれかから選択します。
meetは、「元画像の長いほうを領域に合わせる」処理です。
領域が4:3、元画像が16:9で、領域よりも横長の元画像に「meet」を施した場合。
元画像の長いほう(ここでは横方向)を領域にフィットさせるので、縦方向に隙間が生じました。
今度は領域4:3、元画像はスマホ画面のような9:16のもので試してみます。
この場合「元画像の長いほう」は、縦方向ですね。
縦成分が揃えられて、横方向に隙間ができました。
「meet」を施すと、領域内に元画像の全体を収めることができます。が、領域との縦横比が異なる場合には隙間が生じます。
いっぽうsliceは「元画像の短いほうを領域に合わせる」処理で、そして領域からはみ出した部分はカットされます。
「meet」のはじめに使った領域4:3、元画像が16:9で、領域よりも横長の元画像。これに「slice」を施してみます。
元画像の短いほう = 縦方向が領域に揃えられ、はみ出た部分はカットされました。
「meet」のときと同じく、領域は4:3のまま、縦長9:16の元画像で「slice」を試してみます。
短い方の「横幅」が揃えられてはみ出し分がカットされました。
「slice」は領域に余計な空白を作らずに収めることができます。ただしはみ出した分はカットされてしまうので、照準を指定するときには配慮が必要です。
では実際に、「照準」と「処理」を合わせて使ってみましょう。
4:3の領域に16:9の画像を配置するケースを考えます。
imageにおけるpreserveAspectRatio属性は、image自体の矩形に対して働きます。
従ってSVG領域の内部に、imageの表示領域を明確に指定してやる必要があります。
■ CSS
ここでは親要素の<svg>領域と同じにするため、予め指定していたwidthに加え、heightも100%に指定しました(位置に関しては初期値の(0,0)のままで良いので省略しています)。
現在の状態です‥ん?
元画像がすでに横いっぱいに広がり、上下に隙間ができています。
実はimageの矩形を定義した時点で、preserveAspectRatioの初期値である、
が適用されているんです。
実際の処理は瞬時に行われるのですが、あえて分解して見てみましょう。
「xMidYMid」ということは、縦横中心を照準に取っています。
「meet」で元画像の広いほう、即ち横幅を領域にフィット。
これが「xMidYMid meet」の結果です。
次は「slice」してみます。属性値を改めて記述する事で、初期値から変更します。
また動きを分解してみます。
照準は縦横ともに中心をそろえて・・
幅の狭いほう(縦方向)が領域に合わせられました。水平方向にはみ出た部分はカット。
これが通常の「中央トリミング」と言えますね。
普通じゃないっぽいのもやってみます。照準を「xMaxYMax」としてみました。
この状態でmeet/sliceを試してみます。
「meet」を施すと、xMaxYMax(右下)を照準に横幅が広げられました。
元画像自体は領域の下部に接しています。
「slice」では、右下を照準に高さがフィットされ、左にはみ出た部分がカットされました。元画像の右寄りにトリミングされた形ですね。
「照準」と「処理」を分解して考えれば、結果をある程度予測してのコーディングが可能です。
みなさんも色々試して、感触をつかんでくださいね。
最後までお読みいただき、ありがとうございました。
今回は「preserveAspectRatio」という、たった1つの属性について長々と紹介させていただきました。属性の名前からして長いですね💧
preserveAspectRatioについては「ふ」も、はじめは理解に苦しみました。
そのこともあり、「徹底解説」を目指して記事を書かせていただいた次第です。お役に立てれば幸いです。
扨(さて)SVG領域で画像を操るアニメーション、試してみたい事がまだまだあります。
調査完了次第、発信していきますのでまたお会いしましょう。ではまた〜 ♬
HTMLで画像を重ねる、便利な方法。
2021.01.20
positionやz-index指定なし。
SVGアニメーション01、画面内にフェードインさせる方法。
2020.05.10
〽️ 新シリーズはじめました。
ページめくりアニメーション 作り方。
2021.02.02
画像を読み込むだけで実装。
swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。