画像トリミング
動物の毛を手入れする人のことをトリマーと言いますが、画像の周囲や映像の前後の不要部分を切り取って、必要な部分だけを抜き出すことをトリミング(trimming)と呼んでいます。
下に示した画像のように、ひとつひとつをパーツとみなし、集合写真のように一枚の画像に納め一括して管理すると画像の枚数を少なくすることができます。
個々の画像はサイズが一定でも異なっていても単独画像のように扱うことができます。よって、ここでは必要な部分だけを切り抜くテクニックについて語ります。
部分表示
大きな画像の一部を切り取って表示するには、CanvasのdrawImage関数が便利です。原画像の一部を拡大・縮小して描画できます。モダンブラウザならばCanvasサポートは万全です。その他にスタイルシート(CSS)のclip機能を使って画像を部分表示することができます。
Clipの使い方でHTMLコードをローカル環境ではいい感じの動作が得られたので、公開サーバーにアップロードしてみると毎回、期待を裏切られていました。よくあることですが今回はじっくり腰を据えて調査し、一定の結論が得られたので記録に残すことにしました。
動作環境を特定する
切り抜きをするとき、clip:rectを使うに当たりposition:relativeとposition:absoluteをセットで使います。このpositionプロパティの使い方に問題がありました。今回、部分表示するにはclip:rectを使わずに実現できました。失敗の核心と改良点を示します。
部分表示するとき、親要素にposition:relativeを、子要素にposition:absoluteを指定します。親要素でDIVにより領域を確定し、子要素にIMGで画像を指定した時に誤動作が起きることを突き止めました。
上左図の画像はサイズ100*100の画像を4つ集合したサイズ400*100の画像です。
1つの画像を切り抜いて表示するには親要素に100*100の領域を指定し、子要素に400*100を重ね合わせ、はみ出した3画像ぶん(黄色の背景)をoverflow:hiddenにすれば、1つの画像(ピンクの背景)を切り取ることができます。
重ね合わせると上右図のように子要素の画像が親要素のサイズに合わされてしまうことが誤動作の原因でした。これは試したモダンブラウザに共通して起きました。
子要素でwidthによりサイズを指定しても改善しません。ネット上のサンプルは子要素に画像ではなくテキストを表示する例がほとんどで、画像でない場合、期待した動作になります。
上の図で左のTEST6は誤動作例です。div要素でラップして画像要素を隠蔽すれば正常動作になると考え改訂した例を次に示します。
改良した内容と表示内容
子要素にはdiv要素で領域を確保し、画像は孫要素にしました。そして、absoluteによる働きかけは子要素にしたところ期待した動作が得られました。
たとえば、2番目の画像を切り抜くには、親要素の真上にくるようにleft属性により調整します。そして、overflow:hiddenによりはみ出し部を隠す指定を忘れずに設定します。
表示例は1週間の曜日画像を上図のように1つにし、日曜日から順に土曜日までを部分表示するものです。
動作コード
以下のコードで7行目のimg要素を6と8行目のDivにてposition:absoluteが有効に働くようにします。
<!DOCTYPE html> <!-- ※※※※※※※※ TEST7 ※※※※※※※※ --> <html> <body> <button onClick="if(myDay==0)ImageGuide();">開始、ここをクリック</button> ©TacM,2018 Ver0.03<BR> <DIV style="position:relative; width:120px; height:120px; overflow:hidden; border:0px solid pink;"> <Div id='week0' style="position:absolute; left:0px; top:0px; width:840px; weight:120px;"> <img id='week7' src="https://aidesign.lolipop.jp/wp-content/uploads/2018/06/positionRelative.png"> </Div> </DIV> <div id="imagemessage" style="margin-left:130px; margin-top:-110px; font-size:80px; color:green">準備中…</div> <script type="text/javascript" charset="Shift_JIS"> var myDay=0; function ImageGuide() { document.getElementById('week7').src = "https://aidesign.lolipop.jp/wp-content/uploads/2015/06/week8A.png"; document.getElementById('week0').style.left = (-myDay*120) + "px"; document.getElementById('imagemessage').innerHTML = '曜日(' + myDay + ')'; if(myDay++ < 6) setTimeout('ImageGuide()', 1000); else myDay=0; } </script> </body> </html>
動作例
©TacM,2018 Ver0.03
さいごに
スタイルシートでpositionを指定するとき、仕様書に沿った使い方をしても期待した動作になりませんでした。試行錯誤の結果、一ひねりして新しいことを追加して動作に漕ぎつけました。
clip:rectを使わずにoverflow:hiddenにより部分表示を実現できたことは大きな発見です。clip:rectを用いて思うように画像トリミングができない場合、当記事が参考になれば幸いです。