クリックした場所を「等倍表示」する
「Lightbox」の最初の表示は「ウインドウサイズ」です。 これは画像の全体が表示さ
れるので、全体画像の任意の場所をクリックすると、その箇所を中心に「等倍表示」できれば、スクロールの必要が減ってとても俊敏に操作が出来ます。
PHOTOHITOの元データ画像の表示画面にはこの機能は無く、Photoshopなどでこの機能を知っていると、扱い難いなと思います。 今回はこの機能に着手しました。
当初、位置計算コードが複雑になり、誤差が出そうだと思われましたが、やってみると充分に使える機能になりました。「ウインドウサイズ」表示は、周囲に1%の余裕の枠を作っているので、最初はこれを補正したコードを作りました。 その後で余裕分を無視したコードを作って比較しましたが、全く違いが判りません。
採用したのは当然簡単な方の位置計算コードです。 説明はとても長くなるので省略します。 図を書いて、少しずつ詰めただけです。「object-fit」を使っているので、画像とコンテナ要素で縦横比が一致する境界の前後で、計算式が異なる点が肝です。
今回のバージョンで試すと判りますが、クリックした画像の場所が、かなり正確に画面の中央に拡大されます。 ただし、画像の周辺部の拡大は、それ以上スクロール出来ないので少しズレる事がありますが。
「Lightbox」の操作仕様の変更
クリックポイントを「等倍表示」する操作を採り入れたので、大幅に操作仕様を変更しました。「ウインドウザイズ」で画像を開くまでは同じです。
●「ウインドウザイズ」の画像で「等倍表示」したい場所を「左Click」すると、その場所を中心にした「等倍表示」に移行します。
●「等倍表示」の「Lightbox」内の任意の場所の「左Click」で「ウインドウザイズ」の表示戻る。
以降、「等倍表示」⇄「ウインドウザイズ」を繰り返す。
「Lightbox」を終了する方法
「等倍表示」「ウインドウザイズ」のどちらの画面でも、マウスポインターを上部に移動すると「✖」マークが出ます。
●「✖」マークを「左Click」すると「Lightbox」を終了し「ユーザー別写真リスト」の画面に戻ります。
●「等倍表示」「ウインドウザイズ」のどちらの画面でも、「ESC」キーを押す事でも、「ユーザー別写真リスト」の画面に戻れます。
この「Lightbox」を終了するボタンや「ESC」キーの操作は、「Chorme」の全画面表示の操作仕様を意図的に真似ました。 下は、全画面表示で「Lightbox」のスイッチを表示したところで、文字の太い方が「PhotoHito Viewer」のスイッチです。
紛らわしい様に見えまず、実際は操作に困るという事はありません。 デザインと操作を似せたので、だれでもすぐ理解できると思います。
「Exifデータ」を「Lightbox」内で参照可能に
●「等倍表示」「ウインドウザイズ」のどちらの画面でも「Space」キーを押すと、画面の右横に「Exifパネル」が表示されます。
▪ もういちど「Space」キーを押すと「Exifパネル」は非表示になります。
▪「Exifパネル」の「Lightbox」内の表示は、「Lightbox」を閉じると非表示にリセットされ、「ユーザー別写真リスト」での上部表示の設定とは独立しています。
ツールの適用画面の設定を修正
「 https://photohito.com/photo/* 」をツール適用先に設定していましたが、この「/photo/」のパスは、画像投稿等の画面も同じなので、それらのページのデザインを崩していました。
「Tampermonkey」の「@match指定」は細かな指定が出来ないので、「/photo/」のパスでの適用範囲を、以下のコードで選択する様に変更しました。
これは正規表現を使い、「/photo/12345678/」といった 8桁数のみの「ユーザー別写真リスト」の画面にだけマッチします。 これで、誤適用はなくなると思います。
「PhotoHito Viewer」の扱い方
基本的な扱い方は、下のページを参照ください。 ただし、バージョンごとに仕様を変更しているので、説明が一致しない点はツールの制作記事を参照ください。
「PhotoHito Viewer」を利用するには
このツールは Chrome / Edge / Firefox版の拡張機能「Tampermonkey」上で動作します。 以下に、このツールの導入手順を簡単に説明します。
❶「Tampermonkey」を導入します
◎ 使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。
既に「Tampermonkey」を導入している場合は、この手順 ❶ は不要です。
拡張機能の導入については、以下のページに簡単な説明があるので参照ください。
❷「Tampermonkey」にスクリプトを登録します
◎「Tampermonkey」の「+」マークの「新規スクリプト」タブを開きます。
◎「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
◎ 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。
〔 PhotoHito Viewer 〕 ver. 0.6
// ==UserScript== // @name PhotoHito Viewer // @namespace http://tampermonkey.net/ // @version 0.6 // @description 写真投稿サイトPHOTOHITO専用の画像検証ビューア // @author PHOTOHITO User // @match https://photohito.com/photo/* // @match https://photohito.com/lens/* // @match https://photohito.com/camera/* // @icon https://www.google.com/s2/favicons?sz=64&domain=photohito.com // @run-at document-start // @grant none // ==/UserScript== let path=location.pathname; if(path.match(/\/photo\/[0-9]{8}\/$/) || path.startsWith('/lens') || path.startsWith('/camera')){ let retry=0; let interval=setInterval(wait_target, 10); function wait_target(){ retry++; if(retry>10){ // リトライ制限 100回 0.1secまで clearInterval(interval); } let target=document.body; // 監視 target if(target){ clearInterval(interval); list_env(); }} function list_env(){ let style= '<style id="ph_v">'+ 'h1#logo { display: none; } '+ 'body .wrapper_full article #path { margin: 2px 15px 15px !important; } '+ '#user_header { margin: -14px 15px 0; } '+ 'body .wrapper article h1 { font-size: 120%; padding: 0 0 12px 40px; cursor: pointer; } '+ 'body .wrapper article h1 i { margin-top: -18px; } '+ '#photo_detail .wrapper article h1 { cursor: auto; } '+ 'body .wrapper_full article section { margin-right: 15px !important; } '+ 'body .wrapper_full aside { position: absolute; top: 184px; right: 0; '+ 'padding: 10px 20px; background: #fff; z-index: 10; display: none; } '+ 'body .wrapper_full aside .notlogin_banner, '+ 'body .wrapper_full aside .side_ad { display: none; } '+ 'section { display: flex; flex-direction: column; } '+ '.wrapper article h1 { order: -2; } '+ '#photo_list_search_form { width: 600px; order: -2; } '+ '#photo_list_sort {width: 320px; position: relative; top: -50px; left: 600px; order: -2; } '+ '.photo_list { order: 0; } '+ '#pagenate { padding: 7px 0; order: -1; margin: -50px 0 20px; background: #f8f8fa; } '+ '#photo_detail #photo_view { overflow: hidden; } '+ '#photo_detail #photo_view a { margin: 0 auto !important; width: fit-content; } '+ '#photo_detail #photo_view a:hover { box-shadow: 0 100vw 0 100vw #000; } '+ '.adBox-300-2, .ad_detail, .content_ad, '+ '#div-gpt-ad-p-300x250, #div-gpt-ad-p-side_300x250 { display: none; }'+ '</style>'; if(!document.querySelector('#ph_v')){ document.documentElement.insertAdjacentHTML('beforeend', style); }} } // 共通CSS window.addEventListener('DOMContentLoaded', function(){ let path=location.pathname; if(path.match(/\/photo\/[0-9]{8}\/$/)){ //「ユーザー別写真リスト」の画面 box_env(); exif_adupt(); let photo_side=document.querySelector('#photo_view'); if(photo_side){ photo_side.onclick=function(){ // 画像両サイドのクリックでウインドウを閉じる window.close(); }} function box_env(){ let lightbox= '<div id="lightbox">'+ '<div id="photo_sw"><p id="photo_link">✖</p></div>'+ '<img id="box_img">'+ '<style>'+ '@keyframes fadeIn { 0% {opacity: 0} 100% {opacity: 1}} '+ '.fin { animation: fadeIn .5s ease 0s 1 normal; animation-fill-mode: both; } '+ '@keyframes fadeOut { 0% {opacity: 1} 100% {opacity: 0}} '+ '.fout { animation: fadeOut .2s ease 0s 1 normal; animation-fill-mode: both; } '+ '#lightbox { position: fixed; top: 0; left: 0; z-index: 3000; '+ 'display: grid; place-items: center; '+ 'background: #000; width: 100vw; height: 100vh; overflow: auto; visibility: hidden; } '+ '#photo_sw { position: fixed; top: 0; width: 100%; height: 15%; } '+ '#photo_sw:hover #photo_link { opacity: 1; } '+ '#photo_link { position: absolute; top: 20px; left: calc(50% - 24px); height: 34px; '+ 'font: 22px/24px Meiryo; padding: 13px 15px 0; border-radius: 40px; '+ 'background: rgba(68, 68, 68, 0.7); color: #fff; cursor: pointer; opacity: 0; } '+ '#box_img { width: 98vw; height: 98vh; padding: 1vh 1vw; object-fit: contain; } '+ '</style></div>'+ '<div id="exif_sw">'+ 'Exifを上部表示'+ '<style>'+ '#exif_sw { position: absolute; top: 84px; right: 610px; font-size: 15px; '+ 'padding: 11px 10px 8px; border: solid 1px #999; border-radius: 2px; '+ 'background: #fff; cursor: pointer; }'+ '</style></div>'; if(!document.querySelector('#lightbox')){ document.body.insertAdjacentHTML('beforeend', lightbox); }} function exif_env(){ let ex_style= '<style id="exif_style">'+ '#photo_detail .wrapper:nth-child(3) { width: 1000px !important; } '+ '#photo_detail #photo_view a { margin: 0 260px 0 0 !important; width: fit-content; } '+ '#photo_detail #photo_view { display: flex; flex-wrap: wrap; justify-content: center; } '+ '#photo_detail #photo_view h1 { width: 100%; } '+ '#sideInfo { position: absolute;top: 94px; left: calc(50vw + 220px); '+ 'padding: 6px 8px 0; width: 250px; background: #fff; } '+ '#sideInfo.active { top: 0; z-index: 4000; } '+ '.notlogin_banner, #tag_area, #location_area, #btn_violation, #urlpaste_area { '+ 'display: none; } '+ '#photo_view_side { display: none; } '+ 'aside table { margin: 5px 0 0; } '+ 'aside tr { display: flex; flex-direction: column; } '+ 'aside th { padding: 0; font-size: 12px; } '+ 'aside td { padding: 0 0 5px; text-align: left; }'+ '</style>'; if(!document.querySelector('#exif_style')){ document.documentElement.insertAdjacentHTML('beforeend', ex_style); }} let exif_sw=document.querySelector('#exif_sw'); // Exifパネルの配置スイッチ if(exif_sw){ exif_sw.onclick=function(){ let exif_style=document.querySelector('#exif_style'); if(exif_style){ document.cookie='PHView_e=0; path=/; Max-Age=2592000'; // 30日有効 exif_style.remove(); } else{ document.cookie='PHView_e=1; path=/; Max-Age=2592000'; // 30日有効 exif_env(); }}} function exif_adupt(){ if(get_cookie('PHView_e')==1){ exif_env(); } else{ let exif_style=document.querySelector('#exif_style'); if(exif_style){ exif_style.remove(); }} let sideInfo=document.querySelector('#sideInfo'); if(sideInfo && sideInfo.classList.contains('active')){ sideInfo.classList.remove('active'); }} let img_link=document.querySelector('#photo_view a'); let l_img=document.querySelector('#photo_view img:last-child'); if(img_link && l_img){ img_link.addEventListener('mousedown', function(event){ if(!event.shiftKey && !event.ctrlKey){ event.preventDefault(); set_img(l_img); org_size(); }}); } function set_img(target){ let html_=document.querySelector('html'); let lightbox=document.querySelector('#lightbox'); let box_img=lightbox.querySelector('#box_img'); if(lightbox && box_img){ let img_url=target.getAttribute('src'); if(img_url){ let last=img_url.slice(-5); if(last=='l.jpg'){ let new_url=img_url.slice(0, -5) +'o.jpg'; box_img.src=new_url; html_.style.overflow='hidden'; lightbox.style.visibility='visible'; lightbox.classList.remove('fout'); lightbox.classList.add('fin'); }}}} function org_size(){ let lightbox=document.querySelector('#lightbox'); let box_img=lightbox.querySelector('#box_img'); let actal_x; // Actual Pixels表示スクロールx値 let actal_y; // Actual Pixels表示スクロールy値 lightbox.onclick=function(event){ event.stopImmediatePropagation(); if(!event.ctrlKey){ if(box_img.style.width!='auto'){ mag(event); let org='width: auto; height: auto; padding: 0;'; box_img.setAttribute('style', org); lightbox.scrollTo(actal_x, actal_y); } else{ let nor='width: 98vw; height: 98vh; padding: 1vh 1vw;'; box_img.setAttribute('style', nor); }} else{ close(); } function mag(event){ let lightbox=document.querySelector('#lightbox'); let box_img=document.querySelector('#box_img'); let nwidth=box_img.naturalWidth; let nhight=box_img.naturalHeight; let ratio=nwidth/nhight let top=event.offsetY; let left=event.offsetX; let ww=lightbox.clientWidth; let wh=lightbox.clientHeight; if(ww<wh*ratio){ let yp=ratio*(top - wh/2)/ww +1/2; actal_x=(nwidth*left)/ww - ww/2; actal_y=nhight*yp - wh/2; } else{ let xp=((left - ww/2)/wh)/ratio +1/2; actal_x=nwidth*xp - ww/2; actal_y=(nhight*top)/wh - wh/2; }}} } //org_size() let photo_link=document.querySelector('#photo_link'); if(photo_link){ photo_link.onclick=function(event){ event.stopImmediatePropagation(); close(); }} document.addEventListener('keydown', function(event){ if(event.keyCode==27){ close(); } else if(event.keyCode==32){ event.preventDefault(); show_exif(); }}); function close(){ let html_=document.querySelector('html'); let lightbox=document.querySelector('#lightbox'); if(lightbox){ html_.style.overflow='inherit'; lightbox.classList.remove('fin'); lightbox.classList.add('fout'); exif_adupt(); setTimeout(()=>{ lightbox.style.visibility='hidden'; }, 200); }} function show_exif(){ let lightbox=document.querySelector('#lightbox'); let sideInfo=document.querySelector('#sideInfo'); if(sideInfo && lightbox && lightbox.style.visibility=='visible'){ exif_env(); if(!sideInfo.classList.contains('active')){ sideInfo.classList.add('active'); } else{ sideInfo.classList.remove('active'); }}} function get_cookie(name){ let cookie_req=document.cookie.split('; ').find(row=>row.startsWith(name)); if(cookie_req){ if(cookie_req.split('=')[1]==null){ return 0; } else{ return cookie_req.split('=')[1]; }} if(!cookie_req){ return 0; }} } //「ユーザー別写真リスト」の画面 if(path.startsWith('/lens') || path.startsWith('/camera')){ //「サムネイルリスト」の画面 let plist_a=document.querySelectorAll('.photo_list .grid > a'); for(let k=0; k<plist_a.length; k++){ plist_a[k].setAttribute('target', '_blank'); } let title=document.querySelector('.wrapper article h1'); let aside=document.querySelector('.wrapper_full aside'); if(title && aside){ title.onclick=function(){ if(aside.style.display!='block'){ aside.style.display='block'; } else{ aside.style.display='none'; }}} } //「lens」「camera」の検索抽出画像の「サムネイルリスト」の画面 }); // main()
「PhotoHito Viewer」最新版について
旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。
●「PhotoHito Viewer」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。