ツールの適用範囲の設定を修正
実装テストで多くの画像を見ていると、ツールが動作しない画像に出会いました。 良く調べると画像URLの末尾が「photohito.com/photo/1234567/」といった「7桁」の数字でした。
「PHOTOHITO」の登録画像のナンバーは、桁数を決めていなかったのかも知れないと調べると、2008年に「photohito.com/photo/1/」で一番乗りをしている方が居ました。 という事は、これまでの動作ページのURL選択コードを変えないと。
これまでは以下の「8桁」に固定したコードです。
動作する正規表現の指定が手間取ったのですが、「1」以降「99999999」までの「ユーザー別写真リスト」の画面を、以下のコードで選別できました。
沢山の問題点を発見
マニュアル制作は大変しんどいのですが、それを通じて見落としていた問題を発見する事がよくあります。 おうよそ、自分のためだけにツールを作っていると、問題の洗い出しが適当になります。 他の人が使うと、予想もしない操作をする事があり、それに耐えるインターフェイスを作る事は大事です。 マニュアル制作で、不問にしていた使い難さや、プログラム動作の最悪のケースに目を向ける機会が増えます。
今回も、完成に近いと思っていたのに、幾つかダメな点が出て来ました。
「ユーザー別写真リスト」の早急なクリック
「サムネイルリスト」から「ユーザー別写真リスト」を開く際、若干のタイムラグがあります。 これは、メイン画像や個人のリスト画像を呼込む時間でしょう。
この瞬間に、ロード途中のメイン画像のあたりをクリックすると、前バージョンでは、サイト側ビューアが起動する事に気付きました。 これは、ツールのスクリプトが動作を始める一瞬前に、素の状態のメイン画像が存在して、それをクリックする事で本来のビューアを呼んでしまう様です。
この抑止のため、ページにデザインを適用する関数「com_env()」で、メイン画像に「pointer-events: none;」を指定してクリック操作を無効にして、主要スクリプトが働き出したら、自らこの指定を解除する方法で改善しました。
「サムネイルリスト」に戻ってしまう問題
サイト側ビューアの起動を抑止して、更に同様の「大急ぎ」の操作をテストすると、今度は「ユーザー別写真リスト」から直ぐに「サムネイルリスト」に戻ってしまう事が生じました。
本来メイン画像の周辺のクリックで「サムネイルリスト」に戻るのは正常ですが、メイン画像の位置をクリックしているので、想定外です。 これは、メイン画像が完全にロードされていない瞬間は、その背後の部分をクリックした事になるのか?
まぁ、もう「画像の周辺のクリック」の方式をやめようかと思ったのですが、これは便利なので...
色々試し、この機能のコードに「0.5sec」の読込み遅延を設定し、更に「Exifを上部表示」のボタンの実装を確認してから、初めて「サムネイルリスト」に戻る機能を有効にする様にしました。
しかも、このコードを殆ど全コードの最後に移動して、とにかく直ぐに機能しない様にしています。 色々な条件が関連する微妙なタイミングですが、この問題はほぼ抑え込めた様に思います。
サイト側のビューアを起動した時
メイン画像の「Ctrl+左Click」「Shift+左Click」で、別タブまたは別ウインドウでサイト側のビューアを使える様にしたのですが、これを行った「ユーザー別写真リスト」のタブは閉じないので目的通りの動作ですが、「サムネイルリスト」に遷移しているのに気付きました。
コードを弄っている間に、どこかで変わったでしょうのか? これは「ユーザー別写真リスト」のままで遷移しないでほしいのです。
で、コードを調べて、上記の太字の「!event.ctrlKey && !event.shiftKey」の条件を入てやると遷移を防げる事が判りました。 サイト側ビューアを起動する際に、「戻る」のコードが動作していたわけです。 これは簡単に改善しました。
「Exifパネル」の表示仕様を変更
「Exifパネル」を「Space」で開閉する操作は予想以上に便利で、「Lightbox」内だけではなく「ユーザー別写真リスト」の画面でも、この仕様を採り入れました。
「ユーザー別写真リスト」の初期表示は、毎回 Cookieを参照して「Exifパネル」を表示していました。 そのため、メイン画像が遅れて移動してスマートではありません。 そこで、必要時だけ「Space」キーを押して「Exifパネル」を上部に移動する仕様にして、 Cookie方式を止めました。 もっとも、「Exifを上部表示」のスイッチは、ツール起動のインジケーターの役目があるので残しています。
なお、Cookie方式の廃止で、「ユーザー別写真リスト」「Lightbox」で表示したパネルは、その画面を移動すると常にリセットされる仕様になりました。
SVG画像の利用
最近は普通に「svg画像」を使う様になりました。「Lightbox」を閉じる「✖」ボタンは、最初は通常のフォントを使っていましたが、マークが微妙に対称でないのが気になり、しまいに「svg画像」を作ってしまいました。 CSSでボタンをデザインした場合でもそれなりに文字数が必要ですから、「svg」は上手くすれば数100文字で綺麗なデザインが得られるので、止められません。
このツールでは、「✖」ボタンと「?」ボタンに使っています。
「PhotoHito Viewer」の扱い方
このツールの扱い方の詳細は、下のマニュアルページを参照ください。
「PhotoHito Viewer」を利用するには
このツールは Chrome / Edge / Firefox版の拡張機能「Tampermonkey」上で動作します。 以下に、このツールの導入手順を簡単に説明します。
❶「Tampermonkey」を導入します
◎ 使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。
既に「Tampermonkey」を導入している場合は、この手順 ❶ は不要です。
拡張機能の導入については、以下のページに簡単な説明があるので参照ください。
❷「Tampermonkey」にスクリプトを登録します
◎「Tampermonkey」の「+」マークの「新規スクリプト」タブを開きます。
◎「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
◎ 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。
〔 PhotoHito Viewer 〕 ver. 0.7
// ==UserScript== // @name PhotoHito Viewer // @namespace http://tampermonkey.net/ // @version 0.7 // @description 写真投稿サイトPHOTOHITO専用の画像検証ビュゥア // @author PHOTOHITO User // @match https://photohito.com/photo/* // @match https://photohito.com/lens/* // @match https://photohito.com/camera/* // @exclude https://photohito.com/photo/edit/* // @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\/\d{1,8}\/$/) || path.startsWith('/lens') || path.startsWith('/camera')){ let retry=0; let interval=setInterval(wait_target, 10); function wait_target(){ retry++; if(retry>20){ // リトライ制限 20回 0.2secまで clearInterval(interval); } let target=document.body; // 監視 target if(target){ clearInterval(interval); com_env(); }} function com_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; pointer-events: none; } '+ // 遷移抑止 '#photo_detail #photo_view a { margin: 0 auto !important; width: fit-content; '+ 'user-select: none; pointer-events: none; } '+ // 遷移抑止 '#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\/\d{1,8}\/$/)){ //「ユーザー別写真リスト」の画面 let box=0; // Lightbox の表示フラグ 非表示0 表示1 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(); exif_hide(); set_img(l_img); org_size(); }}); } box_env(); function box_env(){ let SVG_x= '<svg style="width: 48px; height: 48px;" viewBox="0 0 512 512">'+ '<path style="fill: #00000070;" d="M256 0C114.6 0 0 114.6 0 256c0 141.4 '+ '114.6 256 256 256C397.4 512 512 397.4 512 256C512 114.6 397.4 0 256 0z">'+ '</path><path d="M363.1 333.6l-29.6 29.6l-77.6-77.6l-77.5 '+ '77.6l-29.6-29.6l77.5-77.5l-77.5-77.5l29.6-29.6l77.5 77.5l77.6-77.5l29.6 '+ '29.6l-77.5 77.5L363.1 333.6z" style="fill: #fff;"></path></svg>'; let SVG_h= '<svg id="ph_h" height="24" width="24" viewBox="0 0 220 210">'+ '<path d="M89 22C71 25 54 33 41 46C7 81 11 142 50 171C58 177 68 182 78 '+ '185C90 188 103 189 115 187C126 185 137 181 146 175C155 169 163 162 169 '+ '153C190 123 189 80 166 52C147 30 118 18 89 22z" style="fill: #78909c;"></path>'+ '<path d="M67 77C73 75 78 72 84 70C94 66 114 67 109 83C106 91 98 95 93 '+ '101C86 109 83 116 83 126L111 126C112 114 122 108 129 100C137 90 141 76 '+ '135 64C127 45 101 45 84 48C80 49 71 50 68 54C67 56 67 59 67 61L67 77M85 '+ '143L85 166L110 166L110 143L85 143z" style="fill:#fff;"></path></svg>'; let lightbox= '<div id="lightbox">'+ '<div id="photo_sw"><p id="button_x">'+ SVG_x +'</p></div>'+ '<img id="box_img">'+ '<style>'+ '#photo_detail #photo_view { pointer-events:auto !important; } '+ // 遷移抑止を解除 '#photo_detail #photo_view a { pointer-events:auto !important; } '+ // 遷移抑止を解除 '#photo_detail #photo_award_regist { position: absolute; top: 20px; right: 15px; } '+ '@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 #button_x { opacity: 1; } '+ '#button_x { position: absolute; top: 20px; left: calc(50% - 24px); '+ 'cursor: pointer; opacity: 0; } '+ '#box_img { width: 98vw; height: 98vh; padding: 1vh 1vw; object-fit: contain; } '+ '</style></div>'+ '<div id="exif_sw">'+ 'Exifを上部表示'+ SVG_h + '<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; } '+ '#ph_h { margin: -8px -4px -6px 8px; cursor: pointer; }'+ '</style></div>'; if(!document.querySelector('#lightbox')){ document.body.insertAdjacentHTML('beforeend', lightbox); }} function exif_disp(n){ let style; if(n==0){ style= '<style id="exif_style">'+ '#sideInfo { position: absolute; top: 94px; left: calc(50vw + 220px); '; } if(n==1){ style= '<style id="exif_style">'+ '#sideInfo { position: fixed; top: 60px; right: 20px; z-index: 4000; '; } style+= 'padding: 6px 8px 0; width: 250px; background: #fff; } '+ '#photo_detail .wrapper:nth-child(3) { width: 1000px !important; } '+ '.notlogin_banner, #tag_area, #location_area, #btn_violation, '+ '#urlpaste_area { 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', style); }} function exif_hide(){ let exif_style=document.querySelector('#exif_style'); if(exif_style){ exif_style.remove(); }} function exif_turn(){ let exif_style=document.querySelector('#exif_style'); if(exif_style){ exif_style.remove(); } else{ if(box==0){ exif_disp(0); } else if(box==1){ exif_disp(1); }}} let exif_sw=document.querySelector('#exif_sw'); // Exifパネルの配置スイッチ if(exif_sw){ exif_sw.onclick=function(){ exif_turn(); }} 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'); box=1; }}}} 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 button_x=document.querySelector('#button_x'); if(button_x){ button_x.onclick=function(event){ event.stopImmediatePropagation(); close(); }} document.addEventListener('keydown', function(event){ if(box==1){ if(event.keyCode==27){ event.preventDefault(); close(); } else if(event.keyCode==32){ event.preventDefault(); exif_turn(); }} if(box==0){ if(event.keyCode==32){ event.preventDefault(); exif_turn(); }}}); 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_hide(); setTimeout(()=>{ lightbox.style.visibility='hidden'; box=0; }, 200); }} setTimeout(()=>{ let photo_side=document.querySelector('#photo_view'); if(photo_side){ photo_side.onclick=function(event){ // 画像周囲のクリックでタブ画面を閉じる if(!event.ctrlKey && !event.shiftKey){ if(exif_sw){ window.close(); }}}} }, 500); let help=document.querySelector('#ph_h'); if(help){ help.onclick=function(event){ event.stopImmediatePropagation(); let url='https://ameblo.jp/personwritep/entry-12774028982.html'; window.open(url, '_blank'); }} } //「ユーザー別写真リスト」の画面 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」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。