画像に設定されたリンクを調べるコード
前バージョンから、画像に設定されたリンクを「Lightbox」内にボタン化して表示する機能を採り入れました。
新しい「 Linked Page」のボタンは、「Amebaスタンプ」「各種のバナー」やユーザーがHTMLで設定した「リンク付き画像」など、一般的なリンク設定がある画像を「Lightbox」に表示した場合に、そのリンクを受け継ぐボタンです。 これは「Click」モードで、画像に設定されたリンクを押し難くなる問題を改善します。
前バージョンでは、対象画像の親要素が「a要素」のシンプルな構成の「リンク付き画像」しか扱えなかったのですが、今回は「リンクカード」「ピックカード」などの複雑な構成の場合にも対応しました。
とても有難い「closest()」メソッド
下は、ブログページ上で画像(img要素)にリンク(a要素)が設定された「リンク付き画像」の例で、HTML構造を模式化した図です。
❶ 一番シンプルな構成で、「img要素」を「a要素」で囲っています。 画像をクリックすると「a要素」をクリックした事になり、リンク先へ移動したり表示したりするという、「リンク付き画像」の基本の構造です。
❷ 画像に簡単な文字などを添え、それを「a要素」で囲ったもの。 バナー等に良く見られる構成です。 外側を「p要素」や「div要素」が囲っている場合が多く、これは文書に挿入時に、エディターが自動的に付加する様です。
❸「リンクカード」「ピックカード」などは、情報を付帯させた複雑なHTML構成になります。 しかし、クリックでリンクを機能させるために、カード全体が「a要素」で囲まれている点は、❶ ❷と同じです。
ここで、画像に設定された「a要素」を取得するには、❶ ❷の場合は「img要素」の親要素を取得して、それが「a要素」なら取得するコードで済みます。
ところが ❸の場合は、プログラムは幾つもの場合に分岐したコードが必要です。 対象の「img要素」の親を取得 →「a要素」ならそれを取得、「a要素」でなければ更にその親要素を取得 →「a要素」ならそれを取得、「a要素」でなければ更にその親要素を取得 → → という具合に、延々と「a要素」が出て来るまで続けるわけです。
しかし、この難儀な操作を「closest()」というメソッドを使うと、いとも簡単に解決できました。 以下が実際のコードです。
コードの説明
「'A'」というのは HTML上の「a要素」の事で、「target_img」は「Lightbox」に表示した対象の画像です。 初行の意味は、「target_img」の親要素、更にその親要素と、先祖の要素を順に調べて、「a要素」があれば取得せよという内容です。
取得された「a要素」を変数「link」に代入し、2行目で「link」が取得されたら「~~~」と次の指示を実行させています。「Lightbox」に表示した画像にリンクが設定されていない場合もありますが、その場合は「closest()」が「null」を返し「~~~」以下は実行されません。
「closest()」メソッドのおかけで、2行で「a要素」探しが可能になりました。
「リンク付き画像」に共通して使える
このコードは、対象の「target_img」を指定すれば、そのリンク設定の「a要素」を取得します。 これは、通常の掲載「画像」も、「バナー」も「リンクカード」も、なんでもかんでもです。
ここから、「Photo Storage」や「Linked Page」を生成するコードを、以下の様に纏める事ができました。
▪「cont」は、リンクボタンをブログページ以外で表示させないための制御値です。
▪「photo_link」はリンクボタンそのものですが、ボタン上の表示や、ボタンに設定するリンクは、ボタンを表示する度に書換えられます。
▪ 対象画像を包む「a要素」を「closest('A');」で取得し、それが「掲載画像」か、それ以外の「リンク付き画像」かを調べて、リンクボタンのデザインを変えています。
▪ 対象画像にリンクが設定されていれば、リンクボタンにそのリンクを設定。
▪ 最後の2行は、リンクボタンのクリックで「Lightbox」を閉じるコードが機能しない様にしています。 閉じるコードが実行されると、リンクが働かなくなります。
以上のコードで、ブログページ上の殆どの「リンク付き画像」に対して「Lightbox」内にリンクボタンを表示できる様になりました。
なお、リンクを扱えない画像は、「iframe」で構成されたリンクです。 これに類するのは、「リブログカード」、「ツイッター」「インスタグラム」などの埋め込み、「各種のAD」などです。
アメーバランキングを対象ページに追加
アメーバランキングは、自分の趣味に合うブログを見つける事に利用できます。 そして 70近いジャンルでは、ブログの掲載画像でランキング表示が構成されています。
このランキングページでも「Ameblo Lightbox JS」を利用可能にしました。 ランキング表示のサムネイルから、個別ブログを開かずに元画像を見る事が出来ます。
「Ameblo Lightbox JS」の仕様
● 拡大表示の対象は、アメーバブログとアメーバニュースに掲載された「img要素」(画像)です。 それらを「Ctrl+左クリック」すると「Lightbox」内に表示します。
ただしブログページでは、「Ctrl+」「Click」のモードにより操作が変わります。
●「リンクカード」「Ameba Pick」のカバー画像、「Amebaスタンプ」「各種のバナー」「アメーバ絵文字」なども拡大表示します。
● リンクが「img要素」に設定されている場合は、クリックで通常通り機能します。 また「Shift+左クリック」すると、リンク先が別ウインドウに表示されます。
● 拡大表示前の通常の表示に戻るには、「Lightbox」内を左クリックします。
●「Lightbox」内の上部にマウスポインターを移動すると「 Photo Storage」のボタンが表示され、これを左クリックすると画像一覧ページへ移動できます。
●「Lightbox」内上部の「Ctrl+」「Click」は、ブログページでの起動仕様(モード)の表示です。 これを押すごとに「Lightbox」の起動仕様が変わります。
●「Lightbox」内上部の「◪」は、背景色の変更ボタンです。 これを押すごとに、Lightboxの背景色の白/黒が変わります。
● 画像一覧ページでも「Ameblo Lightbox JS」は機能します。
● ブログページ上の画像の左クリックで画像一覧を開いた場合は、画像表示枠内を左クリックすると、元のページ表示に戻れます。 これはブラウザの「 戻る」を押すのと同様の機能です。
●「Lightbox」内を「Ctrl+左クリック」すると、スクロール拡大表示になります。
● スクロール拡大は、縦スクロールと横スクロールの場合があり、これは画像とウインドウの縦横比によって、縦/横が自動的に判別されます。
● スクロール拡大(縦)の場合は「拡大率」と「+」「-」ボタンが表示され、拡大率を「20%~90%」の範囲で調節できます。
●「Lightbox」の「背景色」、スクロール拡大(縦)の「拡大率」は、各ブログごとに Cookieに登録され、次回にそのブログを開いた時に再現されます。
〔非対応の画像について〕
◎「ブログヘッダーの画像」「ブログ背景の画像」などは、「img要素」ではないので非対応です。
◎ 本文中の「リブログカード」のカバー画像、「ツイッター」「インスタグラム」の埋め込み枠内の画像、本文下部のAD画像などは「iframe内」で非対応です。
◎ 非対応の画像を「Ctrl+左クリック」すると、リンクが設定されている場合は、通常は他のタブにリンク先が開きます。
「Ameblo Lightbox JS」 ver. 1.9 を使用するには
「Ameblo Lightbox JS」は Chrome/Edge/Firefox の拡張機能「Tampermonkey」上で動作します。
❶「Tampermonkey」を導入します
◎ 使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。
既に「Tampermonkey」を導入している場合は、この手順 ❶ は不要です。
拡張機能の導入については、以下のページに簡単な説明があるので参照ください。
❷「Tampermonkey」にスクリプトを登録します
◎「Tampermonkey」の「+」マークの「新規スクリプト」タブを開きます。
◎「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
◎ 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。
◎ 複数の「Ameblo Lightbox JS」のバージョンを「Tampermonkey」に登録する事は問題ありませんが、ONとするのは1つに限ります。 複数を同時にONとすると正常な動作が保証されません。
〔 Ameblo Lightbox JS 〕 ver. 1.9
// ==UserScript==
// @name Ameblo Lightbox JS
// @namespace http://tampermonkey.net/
// @version 1.9
// @description ブログ掲載画像の高精細な暗転拡大表示
// @author Ameba Blog User
// @match https://ameblo.jp/*
// @match https://news.ameba.jp/*
// @match https://blogger.ameba.jp/*
// @noframes
// @grant none
// ==/UserScript==
let disp_mode=0; // 拡張ディスプレイモードの判別
let back_color; // Lightbox背景色
let comic_w; // スクロール拡大(縦)の最大幅
let with_cact; // ブログ画面でのLightboxの起動方法
let html_=document.querySelector('html');
let target=document.querySelector('body');
let monitor=new MutationObserver(catch_photo);
monitor.observe(target, { childList: true, subtree: true });
catch_photo();
function catch_photo(){
monitor.disconnect();
box_env0();
box_env1(); // Lightbox背景色設定
let page_img=document.querySelectorAll('img');
for(let k=0; k<page_img.length; k++){
if(page_img[k].parentNode.tagName=='A'){
page_img[k].parentNode.style.opacity='1'; } // ホバーの薄化表示を無効化
let style=window.getComputedStyle(page_img[k]);
if(style.getPropertyValue('pointer-events')=='none'){
page_img[k].style.pointerEvents='auto'; }} // クリック防止指定を無効化
let path=location.pathname; // 現在のパス名
let host=window.location.host; // 現在のホスト名(サブドメインを含む)
if(path.split('/').slice(-1)[0].startsWith('image')){ // 画像一覧画面の場合
let page_img=document.querySelectorAll('img');
for(let k=0; k<page_img.length; k++){
page_img[k].addEventListener('mousedown', function(event){
event.preventDefault();
event.stopImmediatePropagation();
light_box(event, 1, page_img[k]); }); }}
else if(host=='news.ameba.jp'){ // アメーバニュースの場合
let page_img=document.querySelectorAll('img');
for(let k=0; k<page_img.length; k++){
page_img[k].addEventListener('mousedown', function(event){
event.preventDefault();
event.stopImmediatePropagation();
light_box(event, 2, page_img[k]); }); }}
else{ // ブログ画面の場合 Lightboxの起動方法を指定
let page_img;
if(with_cact==0){
page_img=document.querySelectorAll('img'); }
else{
page_img=document.querySelectorAll('#entryBody img'); }
for(let k=0; k<page_img.length; k++){
page_img[k].addEventListener('mousedown', function(event){
event.preventDefault();
event.stopImmediatePropagation();
light_box(event, 0, page_img[k]); }); }}
function light_box(event, type, img){
if(type==0){ // ブログページ用
if((event.ctrlKey==true && with_cact==0) ||
(event.shiftKey==false && event.ctrlKey==false && with_cact==1)){
box_env2(img, 1);
set_img(img);
close(); }}
if(type==1){ // 画像一覧画面用
if(event.ctrlKey==true){
box_env2(img, 0);
set_img(img);
close(); }}
if(type==2){ // アメーバニュース用
if(event.ctrlKey==true){
box_env2(img, 1);
set_img(img);
close(); }}}
monitor.observe(target, { childList: true, subtree: true });
let img_frame=document.querySelector('._3-g1Ourp ._2F4CsxZ2');
if(img_frame){
img_frame.onclick=function(e){
e.stopImmediatePropagation();
history.back(); }} // 画像一覧の画像表示枠のクリックで遷移元画面に
path=location.pathname; // 現在のパス名
if(path.split('/').slice(-1)[0]=='imagelist.html'){
setTimeout(()=>{
if(document.querySelector('._3EX8xkUG ._3tinH7Ew')
&& !document.querySelector('._2z3jgBXG')){
location.reload();
}}, 2000); } // 2sec待っても画像リストが取得できない時はリロード
} // catch_photo()
function box_env0(){
let body=document.querySelector('body');
let css=
'@import url("https://use.fontawesome.com/releases/v5.0.6/css/all.css"); '+
'@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; visibility: hidden; '+
'background: black; width: 100vw; height: 100vh; text-align: center; } '+
'#photo_sw { position: fixed; width: 100%; height: 15%; } '+
'#photo_sw:hover #photo_link { opacity: 1; } '+
'#photo_link { position: absolute; top: 24px; left: 30px; text-decoration: none; '+
'font: bold 21px Meiryo; padding: 3px 12px 0; color: #000; background: #fff; '+
'border: 2px solid #000; border-radius: 6px; cursor: pointer; opacity: 0; } '+
'#photo_sw:hover .bc { opacity: 1; } '+
'.bc { position: absolute; top: 24px; right: 24px; height: 24px; overflow: hidden; '+
'font: normal 24px/26px Meiryo; border-radius: 4px; cursor: pointer; opacity: 0; '+
'margin: 0; box-sizing: content-box; } '+
'#ws { right: 230px; line-height: 28px; padding: 0 5px; } '+
'#wp { right: 195px; font-weight: bold; } #wm { right: 165px; font-weight: bold; } '+
'#ac { right: 70px; line-height: 28px; padding: 0 5px; } '+
'#box_img { width: 96vw; height: 96vh; padding: 2vh 2vw; object-fit: contain; } ';
let style=document.createElement('style');
style.setAttribute('id', 'light_style');
style.textContent=css;
if(!document.querySelector('#light_style')){
body.appendChild(style); }
let box=document.createElement('div');
box.setAttribute('id', 'lightbox');
box.innerHTML=
'<div id="photo_sw">'+
'<a id="photo_link"></a>'+
'<p id="ac" class="bc"></p>'+
'<p id="ws" class="bc"></p>'+
'<p id="wp" class="bc">+</p><p id="wm" class="bc">-</p>'+
'<p id="bow" class="bc">◤</p></div>'+
'<img id="box_img">';
if(!document.querySelector('#lightbox')){
body.appendChild(box); }} // box_env0()
function box_env1(){
with_cact=get_localst('Lightbox_cact');
if(with_cact!=0 && with_cact!=1){
with_cact=0; }
localStorage.setItem('Lightbox_cact', with_cact); // ローカルストレージの更新
back_color=get_cookie('Lightbox_back');
if(back_color!='black' && back_color!='white'){
back_color='black'; }
document.cookie='Lightbox_back='+back_color+'; Max-Age=2592000'; // Cookieの更新
comic_w=get_cookie('Lightbox_comic_w');
if(isNaN(comic_w) || comic_w<20 || comic_w>90){
comic_w=90; }
document.cookie='Lightbox_comic_w='+comic_w+'; Max-Age=2592000'; // Cookieの更新
ctrl_act();
b_or_w();
icon_color();
disp_wpm(disp_mode);
comic_width(); } // box_env1()
function ctrl_act(){
let ac=document.querySelector('#ac');
if(ac){
if(with_cact==0){
ac.textContent='Ctrl+'; }
else{
ac.textContent='Click'; }
ac.onclick=function(event){
event.stopImmediatePropagation();
if(with_cact==0){
with_cact=1;
ac.textContent='Click'; }
else{
with_cact=0;
ac.textContent='Ctrl+'; }
localStorage.setItem('Lightbox_cact', with_cact); // ローカルストレージの更新
location.reload();
}}}
function b_or_w(){
let lightbox=document.querySelector('#lightbox');
lightbox.style.background=back_color; // 背景色をCookieから指定
let bow=document.querySelector('#bow');
if(bow){
bow.onclick=function(event){
event.stopImmediatePropagation();
if(lightbox.style.backgroundColor!='white'){
lightbox.style.backgroundColor='white';
back_color='white'; }
else{
lightbox.style.backgroundColor='black';
back_color='black'; }
icon_color();
document.cookie='Lightbox_back='+back_color+'; Max-Age=2592000'; // Cookieの更新
}}}
function icon_color(){
let bc=document.querySelectorAll('#photo_sw .bc');
for(let k=0; k<bc.length; k++){
if(back_color=='black'){
bc[k].style.color='white';
bc[k].style.background='#000';
bc[k].style.border='2px solid #fff'; }
else{
bc[k].style.color='black';
bc[k].style.background='#fff';
bc[k].style.border='2px solid #000'; }}}
function comic_width(){
let ws=document.querySelector('#ws');
if(ws){
ws.textContent=comic_w; }
let wp=document.querySelector('#wp');
if(wp){
wp.onclick=function(event){
event.stopImmediatePropagation();
if(comic_w<81){
comic_w=Number(comic_w) +10; }
let box_img=document.querySelector('#box_img');
if(box_img){
box_img.style.width=comic_w+'vw'; }
ws.textContent=comic_w;
document.cookie='Lightbox_comic_w='+comic_w+'; Max-Age=2592000'; // Cookieの更新
}}
let wm=document.querySelector('#wm');
if(wm){
wm.onclick=function(event){
event.stopImmediatePropagation();
if(comic_w>29){
comic_w=Number(comic_w) -10; }
let box_img=document.querySelector('#box_img');
if(box_img){
box_img.style.width=comic_w+'vw'; }
ws.textContent=comic_w;
document.cookie='Lightbox_comic_w='+comic_w+'; Max-Age=2592000'; // Cookieの更新
}}}
function disp_wpm(n){
let wp=document.querySelector('#wp');
if(wp){
if(n==0){
wp.style.visibility='hidden'; }
else{
wp.style.visibility='visible'; }}
let wm=document.querySelector('#wm');
if(wm){
if(n==0){
wm.style.visibility='hidden'; }
else{
wm.style.visibility='visible'; }}
let ws=document.querySelector('#ws');
if(ws){
if(n==0){
ws.style.visibility='hidden'; }
else{
ws.style.visibility='visible'; }}}
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; }}
function get_localst(name){
if(!localStorage.getItem(name)){
return 0; }
else{
return localStorage.getItem(name); }}
function box_env2(target_img, cont){
let photo_link=document.querySelector('#photo_link');
if(photo_link){
let link=target_img.closest('A');
if(link && cont==1){
if(link.classList.contains('detailOn')){
photo_link.innerHTML='<i class="fas fa-camera"></i> Photo Storage'; }
else{
photo_link.innerHTML='<i class="fas fa-link"></i> Linked Page'; }
photo_link.setAttribute('href', link.getAttribute('href')); // リンクのコピー
photo_link.style.visibility='visible'; }
else{
photo_link.style.visibility='hidden'; }
photo_link.onclick=function(event){
event.stopImmediatePropagation(); }}}
function hide_photo_link(){
let photo_link=document.querySelector('#photo_link');
if(photo_link){
photo_link.style.visibility='hidden'; }}
function set_img(target_img){
let lightbox=document.querySelector('#lightbox');
let box_img=lightbox.querySelector('#box_img');
let img_src=target_img.getAttribute('src');
let img_url;
if(img_src.indexOf('?caw=')!==-1){
img_url=img_src.split('?caw=')[0]; }
else if(img_src.indexOf('?cat=')!==-1){
img_url=img_src.split('?cat=')[0]; }
else {
img_url=img_src; }
if(lightbox && img_url!=''){
html_.style.overflow='hidden';
box_img.src=img_url;
lightbox.style.visibility='visible';
zoom_reset(lightbox);
lightbox.classList.remove('fout');
lightbox.classList.add('fin'); }}
function zoom_reset(l_box){
let body=document.querySelector('body');
let zoom_f=window.getComputedStyle(body).getPropertyValue('zoom');
if(zoom_f || zoom_f!=1){ // bodyで拡大ツールによるのzoom指定がある場合
l_box.style.zoom=1/zoom_f; }}
function close(){
let html_=document.querySelector('html');
let lightbox=document.querySelector('#lightbox');
let box_img=lightbox.querySelector('#box_img');
if(lightbox){
lightbox.onclick=function(event){
event.preventDefault();
let i_width=box_img.naturalWidth;
let i_height=box_img.naturalHeight;
let w_width= window.innerWidth;
let w_height= window.innerHeight;
if(!event.ctrlKey){
html_.style.overflow='inherit';
lightbox.classList.remove('fin');
lightbox.classList.add('fout');
lightbox.style.overflow='hidden'; // overflowのリセット
box_img.style.height='96vh';
box_img.style.width='96vw';
box_img.style.padding='2vh 2vw';
setTimeout(()=>{
lightbox.style.visibility='hidden';
box_img.src='';
}, 200);
hide_photo_link(); // 画像一覧へのリンクを無効化
disp_mode=0; // 拡張ディスプレイモード リセット
disp_wpm(disp_mode); }
if(event.ctrlKey){
if(i_width*w_height/w_width/i_height>1.1){ // 画像とウインドウを比較:横長
lightbox.style.overflowX='scroll';
lightbox.style.overflowY='hidden';
box_img.style.height='90vh';
box_img.style.width='auto';
box_img.style.padding='4vh 2vw'; }
else { // 画像とウインドウを比較:縦長
disp_mode=1; // 拡張ディスプレイモード 縦長
disp_wpm(disp_mode);
lightbox.style.overflowX='hidden';
lightbox.style.overflowY='auto';
box_img.style.height='auto';
box_img.style.width=comic_w +'vw';
box_img.style.padding='2vh 5vw'; }}
}}}
「Ameblo Lightbox JS」最新版について
旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。
●「Ameblo Lightbox JS」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。




