今までSVGファイルをプログラムで出力するときはimgタグにサイズは書かず、CSSで横幅だけ指定して大きさを調整していました。ですがGoogleの掲げるCLS対策でimgタグにはwidthとheight属性を設定した方がよい、ということになって話が変わってきました。
PHPではgetimagesize()を使えばPNGやJPEGのようなビットマップ画像のサイズは簡単に取得できますが、残念ながらSVGには対応していません。
縦横のサイズ(または縦横比)が分からないと、widthとheightを正しく指定できないのでCLS対策ができません。
「これは困った!」ということでいろいろ調べて見つけたSVGの幅と高さを取得する方法をご紹介します。
SVGの大きさはどうやって決まる?
そもそもSVGはベクターデータなので絶対的な大きさはありません。しかし、大きさを指定する属性は持っています。それを使えば良いのですが、使うSVGがどのようにサイズを指定しているかを調べる必要があります。ここではそれを3つに分類しています。
width・hegiht属性を持っているviewBox属性のみ持っているwidth・height・viewBox属性を持っていない
それぞれで大きさを取得する方法が変わってきます。
width・height属性を持っている場合
SVGがwidth・height属性を持っている場合、SVGファイルをXMLファイルとして読み込み、widthとheight属性を取り出します。コードは次のようになります。
<?php
$svg_xml = simplexml_load_string($img_url);
$xml_attributes = $svg_xml->attributes();
$width = (string) $xml_attributes->width;
$height = (string) $xml_attributes->height;
?>
<img src="<?php echo $img_url; ?>" width="<?php echo $width; ?>" height="<?php echo $height; ?>" >simplexml_load_string()はXMLファイルを読み込んでPHPオブジェクトにしてくれます。そこから幅と高さのデータを取り出しています。
この例ではそのままimgタグに使っていますが、もしデフォルトのサイズから拡大・縮小している場合はそれに合わせて$widthと$heightを計算しなおしましょう。
viewBox属性のみ持っている場合
次はwidthとheight属性を持たずviewBoxが指定されている場合です。私がよく使うAffinity Designerで出力したSVGはこのタイプでした。illustratorではwidthとheight属性があるようです。
<?php
$svg_xml = simplexml_load_file($img_url);
list($originX, $originY, $relWidth, $relHeight) = explode(' ', $svg_xml['viewBox']);
$width=300; // 指定したい画像の幅
$height = $width * $relHeight / $relWidth;
?>
<img src="<?php echo $img_url; ?>" width="<?php echo $width; ?>" height="<?php echo $height; ?>" >先ほどと同じくSVGファイルをXMLとして読み込んでからviewBox属性を取り出します。
viewBox属性には<svg viewBox="0 0 218 52">のようにスペース区切りで4つの数字が設定されています。このコードでは
explode()を使ってスペース区切りで分割list()を使って各変数に代入
として各数値を取得しています。
viewBox属性の4つの数字のうち、後ろの2つが画像の幅と高さになります。
上記のソースではここで取得した幅と高さを使って300px幅に合わせた高さを計算しています。このように縦か横のどちらかが決まればサイズを指定することができます。
厳密にいうと、上記の方法では画像の実際の大きさを取得できない可能性があります。viewBoxで取得できるサイズは画像の大きさではなく画像の描画エリアのサイズだからです。
通常は画像がピッタリ収まるサイズのviewBoxになっていることがほとんどだと思いますが、もし画像より大きめのviewBoxが設定されていた場合(余白が大きい画像と同じ)、意図しないサイズになる可能性があります。
その場合はviewBoxの値を調整する必要があるかもしれません。
width・height・viewBox属性を持っていない
私はこういうファイルに今までお目にかかったことはないですが、この場合は簡単にサイズを取得することができません。画像の頂点を全て取得して最大値を探せばサイズを計算できそうですがプログラムを組むのは大変そうです。
探せばサイズを計算するライブラリとかありそうですが、Affinity Designのようなグラフィックソフトで保存し直すのが手っ取り早いと思います。そういうソフトがない場合は、
- ChromeなどのWebブラウザでサイズ指定なしで表示
- デベロッパーツールで大きさを確認
- その数値をSVGファイルに書き込む
という流れで修正すれば対応できそうです。
いかがだったでしょうか?
今回、この記事のためにSVGのことを結構しらべましたが、なかなか奥が深いですね。Web画像として使うならviewBoxだけを指定がベストなことは分かりました。
ちなみにAffinity Designer ではSVGの書き出し設定の中に「viewBoxを設定する」というオプションがありました。Webで使うならこの設定にチェックは必須ですね。
- この記事のコードは下記サイトのものを参考にさせてもらいました。
How do you get the width and height of an SVG picture in PHP? – Stack Overflow
viewBoxについては下記のページを見るとイメージしやすくなると思います。
SVGのviewBoxをわかりやすく紐解く|NEWS|株式会社INDETAIL(インディテール)- viewBoxの指定についてもっと深く知りたい場合は下記の記事が参考になります。
【SVG】SVGのwidth・height属性はどう考えるとしっくりくる? | LUCKLOG viewBoxとwidth・heightの指定のどちらが使い勝手が良いかについてはこの記事に詳しいです。基本はviewBoxのみの方が良さそうですね。
viewBox属性でSVGをレスポンシブ対応させる | Free Style
コメント
この記事へのコメントはありません。