こんにちは、「ふ」です。
画像をクリックすると拡大表示する仕組みを作ってみましょう。簡単なJavaScriptで作ることができるので、ライブラリなどを取り入れる必要もありません。
webページ内の画像をクリックすると、拡大されて表示されます。
画像だけを目立たせたいので、画像以外の部分には半透明の黒を置いて、ページ本体はぼかすようにしましょう。
実はこれ、クリックされた画像要素を直接拡大しているわけではありません。画面いっぱいの<div>領域をページの上から被せているんです。
そこに大きな<img>領域を設け、クリックした画像のurlを渡すようにします。
今回作成するものでは、拡大時は画面の任意の場所を再度タップ/クリックすれば元の状態に戻るようにします。
一般のサイト閲覧中に別ウインドウが表示されたとき、小さな「閉じる」ボタンが添えられているのを見かけます。でもあれって、元に戻りたいときにその場所にカーソルを持っていく必要があり、ちょっと面倒ですよね。
タップ/クリック1つで拡大表示/元に戻すの切り替えができるため、「ウインドウを閉じるには?」となることもなく、ユーザにとっても使いやすいものになります。
それでは、要素を準備していきます。
<img 「「1class = "zoom"」」 src = "cyan.svg"> <img 「「1class = "zoom"」」 src = "magenta.svg"> <img 「「1class = "zoom"」」 src = "yellow.svg">
通常のページ部分において、「クリック → 拡大」をさせたい<img>要素には共通のclass名を付けておきます。ここでは「zoom」としました。
⬆︎のサンプルでは3つの画像を横並びにしていますが、ページの至る所に配置した画像でも問題ありません。
拡大したときの領域を作成し、webページの上に重ねましょう。
<div id = "zoomback"> <img id = "zoomimg" src = "cyan.svg"> </div>
拡大部分の<div>領域です。その中に<img>領域を設けます。
<img>のsrcは「" "」でも良いのですが、プレビューしやすいよう、テキトーな画像を入れておきました。
「「3/* 親要素をrelativeに */」」「「1 ..@1@ 」」 body { position:relative; } #zoomback { 「「3/* 絶対位置に配置 */」」「「1 ..@2@ 」」 position:absolute; top:0; 「「3/* 画面いっぱいに */」」「「1 ..@3@ 」」 width:100vw; height:100vh; 「「3/* 背景を少し透過 */」」「「1 ..@4@ 」」 background-color:rgba(0,0,0,0.8); 「「3/* 中のimgを中央揃え */」」「「1 ..@5@ 」」 display:flex; justify-content:center; align-items:center; } 「「3/* 拡大画像のサイズを調整 */」」「「1 ..@6@ 」」 #zoomimg { width:50%; }
@1@ 拡大領域はposition:absoluteで絶対位置に配置します。そのため、親要素にあたる部分をposition:relativeにしておきましょう。
@2@ 拡大領域を絶対位置に配置します。
@3@ そして領域を画面いっぱいに広げます。
@4@ 予定通り、背景色を少し透過した黒としています。
@5@ 拡大領域の中に配置された、画像「#zoomimg」。
これを上下左右中央にもっていきます。
@6@ 拡大画像のサイズを指定しましょう。ここはお好みで構いません。
現在の状態⬆︎です。
あくまで好みの問題なのですが、ちょっと<img>の部分が味気ないように思えます。ので、白い枠線を付けておきます。
.zoomback img { width:50%; 「「1border:solid 5px #fff;」」 }
拡大画像が際立ちました。
#zoomback { ・・・・ display:none; }
配置が確認できたら、拡大部分はdisplay:noneで「存在しないもの」にしておきましょう。
これで要素の準備は完了です。
※ 2023/03/19、読者様からコード内容についての指摘をいただき、修正しました。
ご指摘ありがとうございました。
それではJavaScriptを書いていきます。
「「3// 要素を取得」」「「1 ..@1@ 」」 const zoom = document.querySelectorAll(".zoom"); const zoomback = document.getElementById("zoomback"); const zoomimg = document.getElementById("zoomimg"); 「「3// 一括でイベントリスナ」」「「1 ..@2@ 」」 zoom.forEach(function(value) { bbvalue.addEventListener("click",kakudai); bb}); function kakudai(e) { 「「3// 拡大領域を表示」」「「1 ..@3@ 」」 zoomback.style.display = "flex"; 「「3// 押された画像のリンクを渡す」」「「1 ..@4@ 」」 zoomimg.setAttribute("src",e.target.getAttribute("src")); } 「「3// 元に戻すイベントリスナを指定」」「「1 ..@5@ 」」 zoomback.addEventListener("click",modosu); 「「3// 拡大領域を無きものに」」「「1 ..@6@ 」」 function modosu() { zoomback.style.display = "none"; }
@1@ 元の画像群、拡大領域、拡大された画像の3つを取得しておきます。
@2@ 元の画像群に、clickによるイベントリスナを追加します。
JavaScript上でforEachメソッドを使えば、<img>要素にいちいちonclick属性を記述する必要がないので楽ちんです。
@3@ @2@で呼び出される関数「kakudai」の処理です。
既定値では「display:none」としていた拡大領域を「display:flex」として表示させます。
@4@ ここで、クリックされた画像のurlを拡大画像に渡しています。
クリックされた画像要素は、「e.target」で取得することができます。
@5@ 今度は表示された拡大領域を元にもどすための処理です。
拡大領域にも、clickによるイベントリスナを追加。
@6@ @5@で呼び出される関数。
拡大領域のdisplay属性を「none」として消滅させることで、元のweb画面に戻しています。
結果⬆︎です。
各画像をクリックすると拡大表示され、再度画面のどこかをクリックすると元に戻ります。
予定通りできました....が、若干無機質な感じがします💧
「無機質」解消のため。
要素が拡大表示される際にアニメーションを加えて、動きを豊かにしてみます。
.deka { animation:deka 0.3s ease-out; } @keyframes deka { from { transform:scale(0); } }
大きさ0%の状態から徐々にでっかくなっていくアニメーション。
それを持ったclass「deka」を準備しておきます。
function kakudai(e) { zoomback.style.display = "flex"; zoomimg.setAttribute("src",e.target.src); 「「3// 「deka」クラスを付与」」「「1 ..@7@ 」」 zoomimg.classList.add("deka"); }
先ほどの画像がクリックされたときに呼び出される「kakudai(e)」に内容を追加します。
拡大画像にclass「deka」を付与しましょう。
function modosu() { zoomback.style.display = "none"; 「「3// 「deka」クラスを削除」」「「1 ..@8@ 」」 zoomimg.classList.remove("deka") }
また拡大領域が表示されているとき、クリックで呼び出される「modoru( )」。
このタイミングで、class「deka」を削除します。
画像が拡大表示される際に、アニメーションするようになりました。
動きを加えることで先ほどの「一瞬で切り替わってしまう」ものと比べ、「クリックした感触」のようなものをユーザに与えることができます。
最後までお読みくださり、ありがとうございました。
今回はクリックで画像拡大表示させる、というものを作ってみました。その上で、ユーザにも扱いやすくする仕組みを少し付け加えています。
・「閉じるボタン」を設けず、画面の任意の場所をタップすれば元の状態に戻れる。
・少しだけアニメーションを織り込んで、操作したときの感触を与える。
といったところです。
新しい仕組みをサイトに取り入れる際、「どのようにすればユーザにとって操作しやすいか?」という点にも気を配ってみましょう。そうすれば、発信する側と閲覧する側の双方にとって良い結果が得られるはずです。
そういった「ユーザに優しくするアイデア」についても今後記事にしていきたいと思います。参考にしてみてください。
ではまた〜 ♫
JavaScriptのforEachとは? 〜配列のループメソッドについて。
2022.03.24
HTML要素の一括編集にも。
JavaScriptのメソッドについて。〜関数との違いは?
2022.11.27
名前空間の独立とthisキーワード。
swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。