アメブロ記事の掲載画像を高精細に拡大表示する「Lightbox JS」

最近はデジタルカメラだけでなく、スマートフォンによる撮影画像も高品位な画像になって来ました。 ネットテクノロジーはこれらの伝送を可能とし、ブログ掲載画像も次第に高品な画像が増えて来ました。

 

しかし、掲載画像はブログページの読込み速度を遅らせるため、システムには色々と工夫がされています。 なにしろ、ブログ記事を制限 60000文字で埋めても、文字データは 60kBですが、画像は下の様なもの1個で 150kBを越えてしまいますから。

 

 

上の画像は、アップロード保存された画像は 150kB程度ですが、このページ上には 54kBの画像が表示されています。 ブログシステムは、ページ表示時に画像の間引き(圧縮)操作をして、ページ表示時の通信の負担を減らしているのです。 上の画像なら記事上で閲覧する分には、もっと圧縮しても良い位ですが、そこは現代の標準的なブログ閲覧を想定して、アメブロが適度と判断する圧縮率を設定している様です。

 

ただ、画像品位に拘るユーザーには、この圧縮操作は物足りなさを感じさせます。 アップロードされた高品位な画像も、品位を下げてしか見る事が出来ないのですから。

 

「Ameblo Lightbox JS」は、この問題を JavaScriptを使って改善します。 これは、高品位な画像の価値を知っているユーザーには、大変有効なツールです。 掲載画像をクリックした段階で元画像を呼出して表示するので、このツールの常駐でページ表示が遅くなる事はありません。 そして、元画像が高品位なら、元画像の品位の劣化を抑えて参照する事が可能になります。

 

 

 

 画像クリック時のコードの改善

アメブロの標準的な掲載画像の構成は、画像の「img要素」と、その「画像一覧」へのリンクが配置されます。 ユーザーがアメブロ編集画面で画像配置の操作をすると、自動的にこの構成で画像が掲載されます。

 

アメブロの掲載画像の90%以上はこの構成で、「Ameblo Lightbox JS」は、この構成に合致する掲載画像を拡大対象として制作しています。 ただし、その構成に合致しない「img要素」でも、できるだけ扱える様にしています。 多くのブログの中には、独自のスキンや画像配置時の作業などで、非標準の掲載構成を採っているブログがあるからです。

 

非標準の構成には様々の種類が有り得るので、全てを扱うのは無理ですが、ツール側が破たんしない範囲で、扱える条件を拡げる事はやぶさかではありません。 この様な多種の掲載構成への対応は、CSS版の「Lightbox」でも何度か経験した事ですが、それによってツールはより有効なものに熟成します。

 

 

イベント取得を「addEventListener」に改める 

「.onclick=function()」の書式を「.addEventListener('~', function()」の書式への変更したのが、今回の更新の主要点です。

 

クリック等のイベントを取得するリスナーを設定する点では、どちらの書式を使っても同じですが、「.onclick」の書式を使うと取得イベントが「左クリック」に限定されます。 一方「.addEventListener」は更に複雑な種類のイベントを取得する事が可能です。 クリック操作に関しては「click」「mousedown」「mouseup」などが使えるのですが、今回は「mousedown」が必要になりました。

 

問題となったブログでは、対象の「img要素」のクリックイベントを「onclick」で取得できません。 他のブログと子細に比較しても原因となるHTML上の違いを見つけられなかったのですが、何かの理由がある事は事実です。 このあたりの JavaScriptのメソッドの仕様は複雑です。

 

そこで、総当たりでメソッドを試すと、「.addEventListener('mousedown' ~」が使え、「.addEventListener('mouseup' ~」は2回目のクリック操作で使える事が判りました。 等価の「.addEventListener('click' ~」は、やはり動作しません。

 

この事から、「mousedown」でクリックイベントで取得した方が、より広い条件の掲載画像を拡大表示できるので、コードを改めました。 一歩だけ前進です。

 

 

 

 「画像一覧」個別表示画面で動作可能にしました

「画像一覧」の個別表示画面で動作をする様にしました。

 

 

この画面に到達するまでに、ブログページ上で「Lightbox JS」で拡大表示が可能でしょう。 しかし、この「画像一覧」画面には、隣のページや、もっと以前のページの画像が表示されます。 その様に表示された画像を詳細に確認したり、或いは元データを取得(後述)したりするには、その画像が掲載されたページを開き「Lightbox JS」で拡大する事が必要でした。 これは遠回りです。

 

その様な事が必要な場合は少ないですが、少しの再構成で済むので、「画像一覧」画面でこのツールが使える様にしました。 拡大対象は中央に表示された画像のみで、左クリックでブログページと同様に暗転拡大されます。もちろん、ウインドウ全体に、上の通常の画像よりも拡大されます。

 

 

 

 「Ameblo Lightbox JS」の概要

● 拡大表示の対象は、ブログ本文部分に掲載された「img要素」です。 また、このバージョンから「画像一覧」の個別表示画面でも動作する様にしました。

●「リンクカード」「Ameba Pick」のカバー画像、「Amebaスタンプ」「各種のバナー」「アメーバ絵文字」なども拡大表示します。

● 僅かの余裕を残して、ウインドウの全域に拡大表示します。 拡大時は、アメブロヘッダーやスクロールバーは非表示になります。

●「Lightbox」内の上部にマウスポインターを移動すると「Photo Storage(画像一覧)」を開くボタンが表示されます。

●「Lightbox」内の何処かをクリックすると、拡大表示前のページ表示に戻ります。

 

〔非対応の画像について〕

◎「ブログヘッダー」や「サイドバー」上の画像、「画像つき記事」のカバー画像などは、本文のエリアではないので非対応です。

◎ 本文中の「リブログカード」のカバー画像、「ツイッター」「インスタグラム」の埋め込み枠内の画像、本文下部のAD画像などは「iframe内」で非対応です。

◎ 非対応の画像をクリックすると、リンクがあればリンク先への遷移が生じます。

 

 

掲載画像の取得について 

このツールで拡大表示する画像は、アップロードされた元画像ですが、ブラウザウインドウ外にドラッグする事で、縮小処理されない画像を取得できます。(ただし、ファイル形式は全てJpegに変換され、この変換は抑止できません)

 

 

この機能は高品位画像の閲覧を目的とするもので、他ユーザーの掲載画像の扱いで、著作権上の問題を生じない注意が必要です。 この事は、高品位画像かどうかに関わらないでしょう。

 

また、今回のバージョンから、「ブログページ」だけではなく「画像一覧」画面でも「Lightbox JS」による拡大表示が可能になりました。 従って、「画像一覧」画面で拡大表示した画像のドラッグアウトも可能になっています。

 

 

 

「Ameblo Lightbox JS」を使用するには 

「Ameblo Lightbox JS」は Chrome/Edge/Firefox の拡張機能「Tampermonkey」上で動作します。

 

❶「Tampermonkey」を導入します

◎ 使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。

既に「Tampermonkey」を導入している場合は、この手順 ❶ は不要です。

拡張機能の導入については、以下のページに簡単な説明があるので参照ください。

 

 

❷「Tampermonkey」にスクリプトを登録します

◎「Tampermonkey」の「」マークの「新規スクリプト」タブを開きます。

 

 

 

◎「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。

 

〔コピー方法〕 軽量シンプルなツール「PreBox Button   」を使うと

  コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」

  の操作で、掲載コードのコピーが可能になります。

 

◎ 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。

 

 

〔 Ameblo Lightbox JS 〕 ver. 0.5

 

// ==UserScript==
// @name         Ameblo Lightbox JS
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  ブログ掲載画像の高精細な暗転拡大表示
// @author       Ameba Blog User
// @match        https://ameblo.jp/*
// @noframes
// @grant        none
// ==/UserScript==


let html_=document.querySelector('html');

let target=document.querySelector('head');
let monitor=new MutationObserver(catch_photo);
monitor.observe(target, { childList: true });

catch_photo();

function catch_photo(){
    let page_img=document.querySelectorAll('#entryBody img');
    if(page_img.length!=0){
        box_env1();

        for(let k=0; k<page_img.length; k++){
            if(page_img[k].parentNode.tagName=='A'){
                page_img[k].parentNode.style.opacity='1'; }}

        for(let k=0; k<page_img.length; k++){
            page_img[k].addEventListener('mousedown', function(event){
                if(event.shiftKey==false && event.ctrlKey==false){
                    event.preventDefault();
                    box_env2(page_img[k]);
                    set_img(page_img[k]);
                    to_storage(page_img[k]);
                    close(); }}); }}} // catch_photo()


let target_s=document.querySelector('body');
let monitor_s=new MutationObserver(catch_photo_s);
monitor_s.observe(target_s, { childList: true, subtree: true });

catch_photo_s();

function catch_photo_s(){
    let page_img=document.querySelectorAll('._1cWXMxGU img');
    if(page_img.length!=0){
        box_env1();

        for(let k=0; k<page_img.length; k++){
            page_img[k].addEventListener('mousedown', function(event){
                if(event.shiftKey==false && event.ctrlKey==false){
                    event.preventDefault();
                    box_env2(page_img[k]);
                    set_img(page_img[k]);
                    close(); }}); }}} // catch_photo_s()


function box_env1(){
    let body=document.querySelector('body');
    let 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; } '+
        '#photo_sw { position: absolute; width: 100%; height: 15%; } '+
        '#photo_sw:hover #photo_link { opacity: 1; } '+
        '#photo_link { position: absolute; top: 20px; left: 30px; opacity: 0; '+
        'font: bold 21px Meiryo; padding: 3px 12px 2px 10px; background: #fff; '+
        'color: #000; border: 2px solid #000; border-radius: 6px; cursor: pointer; } '+
        '#photo_link::before { content: "\\f00e"; font: 36px AmebaNewSymbols; '+
        'color: #000; padding-right: 6px; vertical-align: -9px; } '+
        '#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"><p id="photo_link">Photo Storage</p></div>'+
        '<img id="box_img">';
    if(!document.querySelector('#lightbox')){
        body.appendChild(box); }}


function box_env2(target_img){
    let photo_sw=document.querySelector('#photo_sw');
    if(target_img.parentNode.getAttribute('href')
       && target_img.parentNode.classList.contains('detailOn')){
        if(photo_sw){
            photo_sw.style.display='block'; }}
    else{
        if(photo_sw){
            photo_sw.style.display='none'; }}}


function set_img(target_img){
    let lightbox=document.querySelector('#lightbox');
    let box_img=lightbox.querySelector('#box_img');
    let img_url=target_img.getAttribute('src').split('?caw=');
    if(lightbox && img_url[0]!=''){
        html_.style.overflow='hidden';
        box_img.src=img_url[0];
        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 to_storage(target_img){
    let photo_link=document.querySelector('#photo_link');
    if(photo_link){
        photo_link.onclick=function(event){
            event.stopImmediatePropagation();
            location.href=target_img.parentNode.getAttribute('href'); }}}


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();
            html_.style.overflow='inherit';
            lightbox.classList.remove('fin');
            lightbox.classList.add('fout');
            setTimeout(()=>{
                lightbox.style.visibility='hidden';
                box_img.src='';
            }, 200); }}}


 

 

 

「Ameblo Lightbox JS」最新版について 

旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。

 

●「Ameblo Lightbox JS」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。