WEBサイトの画像ポップアップツール「Pictune」

2018年5月31日

Javascript Tool テクノロジー プログラミング

画像をリストアップする機能を作っていた時に、その画像のサムネイル一覧を表示し、それぞれのサムネイルをクリックしたら、本画像を拡大表示するという機能はGoogleImageをはじめ、たくさん世の中のサービスで使われていますが、それをWEBサイトに導入するためのツールを作ってみました。 Wordpressや、各種IDEのライブラリとしての提供もあるかもしれませんが、今回はJavascriptでタグを貼るだけで実装できる機能にこだわっています。  すでにLightBoxというライブラリがありますが、そちらを使った時に、カスタマイズ機能が乏しかったので、軽量かつカスタマイズ重視のツールを構築してみました。

色々な画像表示機能

GoogleImageでは、以下のような、ポップアップではなく、吹き出しが割り込み表示される方式です。 Pinterestは、画面遷移方式です。

ソースコード

基本的に下記のjsとcssの2ファイルで構成しています。 同じ階層に設置してjsだけを読み込めばいいようにしています。 (ファイル名は変更しないでね) ;(function(){ var $$ = function(options){ if(document.readyState === "complete"){ $$.prototype.start(); } else if(document.readyState === "interactive"){ this.setEvent(window,"DOMContentLoaded",$$.prototype.start); } else{ this.setEvent(window,"load",$$.prototype.start); } if(options){ $$.prototype.options = options; } }; $$.prototype.start = function(){ var pictune = document.getElementById("pictune"); if(pictune === null){ // css読み込み $$.prototype.getScriptPutCss(); // 画像検索 $$.prototype.setPicture(); // イベントセット $$.prototype.setEvent(window,"click" ,$$.prototype.clickImg); $$.prototype.setEvent(window,"scroll",$$.prototype.adjustSize); $$.prototype.setEvent(window,"resize",$$.prototype.adjustSize); } if(typeof $$.prototype.options !== "undefined" && typeof $$.prototype.options.flg === "undefined"){ $$.prototype.setCustom($$.prototype.options); // delete $$.prototype.options; $$.prototype.options.flg = true; } }; $$.prototype.getScriptPutCss = function(){ var ss = document.getElementsByTagName("script"); for(var i=0; i<ss.length; i++){ if(!ss[i].src){continue;} var ptn = new RegExp("(.+?)pictune.js$"); if(ss[i].src.match(ptn)){ var ln = document.createElement("link"); ln.rel = "stylesheet"; ln.href = RegExp.$1 + "pictune.css"; document.getElementsByTagName("head")[0].appendChild(ln); break; } } }; $$.prototype.setPicture = function(){ var elm = document.getElementById("pictune"); if(elm !== null){return;} var pictune = document.createElement("div"); pictune.id = "pictune"; document.body.appendChild(pictune); var loading = document.createElement("div"); loading.className = "pictune-loading"; pictune.appendChild(loading); var area = document.createElement("div"); area.className = "pictune-area"; pictune.appendChild(area); var close = document.createElement("div"); close.className = "pictune-close"; close.onclick = $$.prototype.viewToggle; area.appendChild(close); var img = new Image(); img.className = "picture"; area.appendChild(img); }; $$.prototype.viewToggle = function(){ var pictune = document.getElementById("pictune"); if(pictune === null){return;} var flg = $$.prototype.getStyle(pictune , "display"); if(flg === "block"){ pictune.style.setProperty("display","none",""); } else{ pictune.style.setProperty("display","block",""); } }; $$.prototype.viewPicture = function(){ var pictune = document.getElementById("pictune"); if(pictune === null){ $$.prototype.setPicture } }; $$.prototype.clickImg = function(e){ var target = e.target; var viewPath; if(target.getAttribute("data-pictune") !== null){ viewPath = target.getAttribute("data-pictune-src"); } if(target.parentNode && target.parentNode.tagName === "A"){ target.parentNode.href = "javascript:void(0)"; if(target.parentNode.getAttribute("data-pictune") !== null){ viewPath = target.parentNode.getAttribute("data-pictune-src"); } } else{ return; } // 画像表示 var img = document.querySelector("#pictune img"); img.src = viewPath; $$.prototype.adjustSize(); $$.prototype.viewToggle(); if(typeof $$.prototype.options !== "undefined" && typeof $$.prototype.options.click !== "undefined"){ $$.prototype.options.click(target); } }; // window.onscroll || window.onresize $$.prototype.adjustSize = function(){ var maxWidth = 0.9; // 90% var maxheight = 0.7; // 70% // base var pictune = document.getElementById("pictune"); var picture = pictune.querySelector(".pictune-area img.picture"); if(picture){ var w = (window.innerWidth * maxWidth); var h = (window.innerHeight * maxheight) picture.style.setProperty("max-width" , w + "px" , ""); picture.style.setProperty("max-height" , h + "px" , ""); } }; $$.prototype.setCustom = function(options){ // console.log(JSON.stringify(options)); if(typeof options.func !== "undefined"){ options.func(); } }; /********** //style値を取得 概要:対象項目のCSS値を取得 param:element 対象項目 **********/ $$.prototype.getStyle=function(e,s){ if(!s){return} //対象項目チェック; if(typeof(e)=='undefined' || e==null || !e){ e = $b; } //属性チェック; var d=''; if(typeof(e.currentStyle)!='undefined'){ d = e.currentStyle[$$.prototype.camelize(s)]; if(d=='medium'){ d = "0"; } } else if(typeof(document.defaultView)!='undefined'){ d = document.defaultView.getComputedStyle(e,'').getPropertyValue(s); } return d; }; //ハイフン区切りを大文字に変換する。 $$.prototype.camelize = function(v){ if(typeof(v)!='string'){return} return v.replace(/-([a-z])/g , function(m){return m.charAt(1).toUpperCase();}); }; $$.prototype.setEvent = function(target, mode, func){ if (target.addEventListener){target.addEventListener(mode, func, false)} else{target.attachEvent('on' + mode, function(){func.call(target , window.event)})} }; new $$; window.$$PICTUNE = $$; })(); #pictune{ position:fixed; top:0; left:0; margin:0; padding:0; border:0; width:100%; height:100%; background-color:rgba(0,0,0,0.8); display:none; text-align:center; } #pictune .pictune-area{ z-index:1; /* position:fixed; */ display:inline-block; /* top:100px; left:100px; */ margin:60px auto 0; padding:0; border:4px solid white; /* width:90%; height:70%; */ background-color:white; border-radius:8px; } #pictune .pictune-area img.picture{ z-index:1; max-width:98%; max-height:90%; display:block; margin:0 auto; padding:0; border-radius:8px; margin-top:-24px; } #pictune .pictune-close{ z-index:10; margin:0; padding:0; border:0; position:relative; top:-34px; left:0px; width:24px; height:24px; cursor:pointer; } #pictune .pictune-close:hover{ opacity:0.5; } #pictune .pictune-close:before, #pictune .pictune-close:after{ content:""; margin:0 auto; padding:0; border:0; position:absolute; top:14px; left:0; width:100%; height:4px; background-color:white; } #pictune .pictune-close:before{ transform:rotate(45deg); } #pictune .pictune-close:after{ transform:rotate(-45deg); }

使い方

IMGタグに属性を追加

対象ページの画像に以下の属性を追加してください。 <img src="hoge.jpg" data-pictune="images or ID" data-pictune-src="view.jpg"> data-pictune : このAttributeを元に画像クリックを判別します。 data-pictune-src : imgタグのsrc属性と同じでもいいですが、ここに入力された画像がポップアップ表示されます。

ライブラリタグを追加

書きScriptタグをWEBサイトに追加します。 <script src="pictune/pictune.js"></script> ※ライブラリのパスは任意に変更してください。

サンプルイメージ

画像にLIKEボタンをつけたようなサイトを構築する際に、LIKEカウント数も一緒にポップアップ表示させたい時などに利用できます。 このサンプルのようなカスタマイズを行うには、タグを設置する際に、以下のようなコードを書いています。 <script src="lib/js/pictune/pictune.js"></script> <script> new $$PICTUNE({ func:function(){ var pictune = document.querySelector("#pictune .pictune-area"); if(pictune){ var good = document.createElement("div"); good.className = "pictune-good"; good.innerHTML = "<span class='picture-good-count'></span>"; pictune.appendChild(good); var goodBtn = document.createElement("img"); goodBtn.className = "pictune-good-button"; goodBtn.src = "data/page/modules/good.svg"; goodBtn.onclick = function(e){ alert(e.target.getAttribute("data-id")); }; good.appendChild(goodBtn); } else{console.log("none");} }, click:function(img){ var goodNum = img.getAttribute("data-pictune-good"); var goodElm = document.querySelector("#pictune .picture-good-count"); goodElm.innerHTML = (goodNum) ? goodNum : 0; var goodBtn = document.querySelector("#pictune .pictune-good-button"); goodBtn.setAttribute("data-id" , img.getAttribute("data-pictune")); } }); </script> <style> #pictune .pictune-good { color:black; font-size:20px; text-align:center; line-height:30px; } #pictune .pictune-good:before { content:"\02665 "; font-size:30px; color:red; font-weight:bold; margin-right:10px; } #pictune .pictune-good-button{ margin-left:10px; width:24px; height:24px; display:inline-block; } </style> 簡単に解説すると、ライブラリを読み込んだタグの下にscriptタグで、下記のような構造を作っています。 new $$PICTUNE({ func:function(){ ※起動時に構造を操作する記述ができます。 }, click:function(img){ ※サムネイル画像をクリックした際にポップアップ表示する情報を書き換えられます。 ※引き渡し値のimgは、サムネイルが入るので、事前にimgタグの属性に情報を入れておくと便利です。 } }); その下のstyleタグは、新たな要素を追加した時の、スタイルを記載しています。 これでかなり柔軟なカスタマイズが可能になりますが、HTMLソースにスクリプトを書くのが気になる人は、別途jsファイルを構築して読み込むやり方でも可能です。

Githubで公開

今回のソースコードは、そのままGithubに掲載しているので、DLなどは最新版も含めてこちらから取得してください。 Pictune | Github 要望や、質問、その他ご意見などありましたら、コメント記載をしてください。

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。