Chrome / Edge 専用の「Remember My Page」
「Remember My Page」はブログページの読込み時に、ページに適当な拡大表示を行います。 拡大率は、ユーザー登録があればその拡大率、登録が無ければ、記事のフォントサイズから計算した拡大率が適用されます。 公式スキンの基準フォントサイズがまちまちなので、ページの表示を自動的に拡大して読み易くする目的で、このツールを制作しました。
ただ、このツールは色々と困難な部分があります。 Chromeと Firefoxでは、拡大に利用するCSSコードや、登録データのファイル記録コードが異なり、両ブラウザに対応すると条件分岐が増えます。 対象外のFirefoxを後に対象に加えましたが、今回、ページ拡大を少しでも高速化するために、分離する事にしました。
「Remember My Page」は、拡大操作の困難さから、人様にお勧めできたものかという気が常に付きまといます。 でも、私自身はこれを常用して、少しずつ最適化を進めています。 もし、文字サイズの不均一に困っていたら、一度試してみてください。
「RemPage For Chrome」
「Chrome専用」のツール名は「RemPage For Chrome」としました。 バージョンはこれまでの数を桁上げして「ver. 3.0」としています。
起動タイミングは最も速い「@run-at document-start」を使い、このタイミングでエラーが出ない様に、コードの各所で修正をしました。 当然、拡大適用の実行は起動強化コードを導入しています。
ローカルストレージの登録データは、ページ構成後ではなく、ページ読込みの開始時に読込み、極力高速化を図っています。
また、適用速度とは無関係ですが、操作パネルの生成に「insertAdjacentHTML」を使い、旧コードを刷新してコンパクトにしました。
◎ 通常記事の操作パネル
◎アメンバー記事の操作パネル
「RemPage For Chrome」の扱い方
「RemPage For Chrome」は、常駐型のツールです。「Tampermonkey」にこのツールを登録して、常にONにしておく使い方をします。 このツールは、ユーザーがアメーバブログの色々なブログページを開いた時から動作をはじめます。
このツールの動作は、アメブロヘッダー左端のアメーバアイコンの色が、デフォルトから変化する事で判ります。(色の区別は後で纏めています)
❶ ユーザー指定の拡大率があるブログページの場合は、その指定に従って、ページを自動的に拡大(あるいは縮小)表示します。
❷ ユーザー指定の拡大率が無いブログページの場合で、フォントサイズが「16px」のブログページは「自動拡大」は動作せず、デフォルト(100%)で表示されます。
❸ ユーザー指定の拡大率が無いブログページの場合で、フォントサイズが「14px」のブログページは「自動拡大」が動作します。 これは 14pxのフォントを 16px相当のサイズに表示する 114% の拡大です。
❹ 上記❸の「自動拡大」で対応出来ない特殊なページでは、ユーザー自身の最適な拡大率をマニュアル設定できます。 アメーバアイコンを左クリックすると、このツールの設定メニューが表示されます。
(注意)ブラウザの本来の拡大機能で「100%」以外の値が設定されている場合、上記の紺色の「Basic拡大率」が数秒間表示されます。(Chrome版のみの機能)
この様な表示をするのは、ブラウザ拡大とツール拡大が相乗されると、ユーザーは混乱して、不適当な設定をする可能性があるからです。 ブラウザのデフォルト拡大率を「100%」に設定して、「RemPage For Chrome」で拡大表示を行うのが、お勧めの扱い方です。
❺ 上記❸❹に類する例のひとつになりますが、自動拡大で却って見難くなる場合に、敢えて「100%」を設定する事が可能です。 これは「Reset」や「無指定」ではなくツール拡大率「100%」の指定です。
ツールのメニュー の操作について
❶「×」ボタン: メニューを閉じるボタンです。「Set」を押さずにメニューを閉じた場合は、設定は登録されずに、メニューを開く前の状態に戻ります。
❷「拡大率」入力枠: マウスホイールの「⇅」操作で 5%単位で増減し、同時に画面が拡大・縮小します。 入力枠をクリックしてキャレットを入れると「⇧ ⇩」のキー操作で設定ができ、また手入力で1%単位の拡大率指定も可能です。
❸「Set」ボタン:「拡大率」入力枠の値に応じて、ページが拡大縮小表示されますが、これは仮の表示です。「Set」ボタンを押す事で、その値が登録されて実際のページに反映します。 押さなければ、登録は以前の状態のままです。
❹「Reset」ボタン: 現在のページに設定された拡大率の登録を削除して、設定メニューを閉じます。 ページは標準の表示状態になり、条件によっては自動拡縮が機能する場合もあります。
❺「Export」ボタン: 多数のページで「マニュアル登録」した拡大率のデータを、ファイルに出力してバックアップする事が出来ます。 ファイルは、ダウンロードフォルダーに「remember_zoom(n).json」という名で保存されます。
❻「Import」ボタン: 自分の閲覧環境に最適な拡大率の設定は、バックアップファイルから再現する事が出来ます。 PCが複数ある場合は、バックアップファイルを通じて、環境を統一できます。
「登録表示マーク」と「アメーバアイコン」
Amebaアイコンが本来の緑色で表示される場合は、「RemPage For Chrome」がOFFになっている場合や、何かの理由で無効になっている場合です。
「RemPage For Chrome」が有効の場合は、Amebaアイコンは青色の表示です。 この色の場合は、拡大率の調整や登録をするメニューを開く事が出来ます。
下は「登録表示マーク」の表示がなく、画面は拡大のないデフォルトの表示です。
下は登録があり、画面に拡大が実行されている場合です。 拡大率が登録されているページでは、青色の「登録表示マーク」が表示されます。
下は「100%」の拡大率の登録がある場合です。 拡大率「100%」の登録の場合だけ「登録表示マーク」は赤色になります。 これは、自動拡大の対象となるページで、敢えて等倍表示を指定した場合の状態です。
下は「14px」タイプのページで、「自動拡大」が実行されている場合です。 ページの拡大率の登録をしなくても、このタイプのページは自動拡大機能で拡大表示します。
操作は使ってみると簡単 です
このツールの操作を難しく考える必要はなく、次の要領だけ覚えると快適です。
❶ アメーバのブログページを表示する際は、特別に必要な場合は別として、
基本的にブラウザ本来の拡大機能を使用しない様にします。
❷ 閲覧上で拡大が必要と思ったページで、それが何度も訪れるページなら、
このツールで拡大率を調節してセットします。
例えば、スキン指定のフォントが小さくて読み難いとか、ページに独自のフォントサイズ指定がされている場合や、閲覧ユーザー側の理由で少し拡大したい場合など、アメブロのページごとに細かく拡大率を指定できます。
その拡大指定はブログページ毎に記録され、再びそのページを開く度に自動的に再現されます。 拡大率の登録は、いつでも変更や解除が出来ます。
アメンバーページの拡大表示に対応
アメンバーページは、ユーザーのスキン設定とは無関係に一律で「16px」のフォントサイズが指定されます。 このため「RemPage For Chrome」を使う必要は一般には無いのですが、コアな利用法にも対応できる様に考えました。 扱いは一般ページと同様ですが、バックアップは「remember_zoom_am(n).json」というファイル名になります。
「RemPage For Chrome」を使うには
このツールは、Chrome / Edge で動作を確認しています。
( Firefoxは、For Firefox版を使用してください)
❶「Tampermonkey」を導入します
◎ 使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。
既に「Tampermonkey」を導入している場合は、この手順 ❶ は不要です。
拡張機能の導入については、以下のページに簡単な説明があるので参照ください。
❷「Tampermonkey」にスクリプトを登録します
◎「Tampermonkey」の「+」マークの「新規スクリプト」タブを開きます。
◎「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。
〔コピー方法〕 軽量シンプルなツール「PreBox Button 」を使うと
コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」
の操作で、掲載コードのコピーが可能になります。
◎ 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。
〔 RemPage For Chrome 〕ver. 3.0
// ==UserScript== // @name RemPage For Chrome // @namespace http://tampermonkey.net/ // @version 3.0 // @description ブログページのブラウザ拡大率をユーザー単位で記録・固定(zoom / transform 使用) // @author Ameba Blog User // @match https://ameblo.jp/* // @match https://secret.ameba.jp/* // @exclude https://ameblo.jp/*/image* // @run-at document-start // @noframes // @grant none // ==/UserScript== let remember_data={}; // ブログ登録データ let remember_id=[]; let remember_zoom=[]; // let iine_lock=0; let z_button; let user_id; let zoom_value; let zoom_auto=0; let edit_mode=0; let am=0; if(document.domain=='secret.ameba.jp'){ am=1; } reg_set(); function reg_set(){ let read_json=localStorage.getItem('remember_zoom'); // ローカルストレージ 保存名 remember_data=JSON.parse(read_json); if(remember_data==null){ if(am==0){ remember_data=[['user', 'zoom']]; } // 一般ブログ記事データ else if(am==1){ remember_data=[['u_am', 'zoom']]; }} // アメンバー記事データ remember_id=[]; // 配列をリセット remember_zoom=[]; // 配列をリセット for(let k=0; k<remember_data.length; k++){ remember_id[k]=remember_data[k][0]; remember_zoom[k]=remember_data[k][1]; }} let retry=0; let interval=setInterval(wait_target, 1); function wait_target(){ retry++; if(retry>100){ // リトライ制限 100回 0.1secまで clearInterval(interval); } let target=document.body; // 監視 target if(target){ clearInterval(interval); zoom_startup(); }} function zoom_startup(){ do_zoom(); let target0=document.querySelector('head'); // 監視 target let monitor0=new MutationObserver(do_zoom); monitor0.observe(target0, { childList: true }); // 監視開始 let target1=document.querySelector('head'); // 監視 target if(target1){ let monitor1=new MutationObserver(path_change); monitor1.observe(target1, { childList: true }); } // 監視開始 } // zoom_startup() function do_zoom(){ zoom_reset(); center(); set_value(); } //do_zoom() function zoom_reset(){ user_id=document.location.pathname.split("/")[1]; // ユーザーIDを取得 if(remember_id.indexOf(user_id)!=-1){ zoom_value=remember_zoom[remember_id.indexOf(user_id)]; if(zoom_value==1){ zoom_auto=3; } // 登録有 100% zoom を適用 else { zoom_auto=2; }} // 登録有 manual zoom を適用 else{ let entryBody=document.querySelector('#entryBody'); if(entryBody){ if(getComputedStyle(entryBody, null).fontSize=='14px'){ // 未登録14px型 zoom_auto=1; // 未登録 auto zoom を適用 zoom_value=1.14; } else{ zoom_auto=0; // 未登録 zoom 無し zoom_value=1; }} else{ zoom_auto=0; // 未登録 zoom 無し zoom_value=1; }} // entryBodyが取得出来ない場合 let z_num=document.querySelector('#z_num'); if(z_num){ z_num.value=Math.round(zoom_value*100); } // 拡大率表示を更新 button_show(zoom_auto); ch_zoom(zoom_value); // Chrome場合 拡大実行 } // zoom_reset() 開いた画面にzoom値を設定して拡大 function ch_zoom(zoom_val){ // Chrome用のページ拡大コード if(document.body){ document.body.style.zoom=zoom_val; } // bodyにzoom指定 let ambHeader=document.querySelector('#ambHeader'); if(ambHeader){ ambHeader.style.zoom=1/zoom_val; } let footer=document.querySelector('footer'); if(footer){ footer.style.zoom=1/zoom_val; } let footer1=document.querySelector('._20TD20u0'); if(footer1){ footer1.style.display='none'; } let footer2=document.querySelector('._HQiG1eoZ'); if(footer2){ footer2.style.display='none'; } let modal=document.querySelectorAll('.ReactModalPortal'); for(let k=0; k<modal.length; k++){ modal[k].style.zoom=1/zoom_val; }} // モーダル画面のzoomリセット function center(){ // 記事本文を中央に配置 let main_a=document.querySelector('#main'); if(main_a){ let cr_left=main_a.getBoundingClientRect().left; let cr_width=main_a.getBoundingClientRect().width; let center_p=cr_left + cr_width/2; let v_center=center_p*zoom_value; let window_w=document.documentElement.clientWidth; scrollBy(v_center - window_w/2, 0 ); }} function button_show(n){ // ボタン色表示をコントロール if(am==0){ z_button=document.querySelector('#ambHeader img[alt="Ameba"]'); } else if(am==1){ z_button=document.querySelector('.-ameblo-cmnhf-logo'); } if(z_button){ if(n==0){ // 未登録 zoom 無し z_button.style.filter='contrast(6) hue-rotate(90deg)'; z_button.style.boxShadow='none'; z_button.style.paddingLeft='0'; } else if(n==1){ // 未登録 auto zoom z_button.style.filter='contrast(6) hue-rotate(90deg)'; z_button.style.boxShadow='-10px 0 0 0 #e98200'; z_button.style.paddingLeft='5px'; } else if(n==2){ // 登録有 manual zoom z_button.style.filter='contrast(6) hue-rotate(90deg)'; z_button.style.boxShadow='-10px 0 0 0 #7aff00'; z_button.style.paddingLeft='5px'; } else if(n==3){ // 登録有 100% zoom z_button.style.filter='contrast(6) hue-rotate(90deg)'; z_button.style.boxShadow='-10px 0 0 0 #9c27b0'; z_button.style.paddingLeft='5px'; }}} function set_value(){ if(am==0){ z_button=document.querySelector('#ambHeader img[alt="Ameba"]'); } else if(am==1){ z_button=document.querySelector('.-ameblo-cmnhf-logo'); } if(z_button){ z_button.onclick=function(event){ // Amebaアイコンのクリック event.preventDefault(); // クリックしてもホームに飛ばさない backup(); }}} function backup(){ edit_mode=1; let win_html=document.documentElement; win_html.style.overflow='hidden'; // ウインドウのスクロールを抑止 let z_div= '<div id="z_panel">'+ '<input id="z_close" type="submit" value="×">'+ '<input id="z_num" type="number" step="5" min="80" max="200">'+ '<input id="z_set" type="submit" value="Set">'+ '<input id="z_reset" type="submit" value="Reset">'+ '<input id="z_exp" type="submit" value="Export">'+ '<input id="z_imp" type="submit" value="Import">'+ '<input id="z_file" type="file">'+ '<span id="z_mag"></span>'; let z_style= '<style>'+ '#z_panel { position: absolute; top: 7px; left: 0; z-index: 0; '+ 'color: #333; background: #fff; padding: 5px 0 5px 15px; width: 400px; } '+ '#z_panel ::-webkit-inner-spin-button { -webkit-appearance: none; } '+ '#z_panel > * { font: normal 15px Arial; padding: 2px; height: 24px; } '+ '#z_close { font-weight: bold; width: 14px; padding: 2px 0; margin-right: 15px; } '+ '#z_num { width: 36px; padding: 1.5px 0 0 8px; height: 18.8px; '+ 'box-sizing: content-box; } '+ '#z_set { margin-left: 4px; } '+ '#z_reset { margin-left: 4px; } '+ '#z_exp { margin: 0 4px 0 15px; } '+ '#z_imp { margin-right: 15px; } '+ '#z_file { display: none; } '+ '#z_mag { color: #fff; background: #0288d1; padding: 3px 4px; '+ 'border: thin solid #888; border-radius: 3px; transition: 2s; } '; if(am==1){ z_style += '#z_panel { top: 0; padding: 3px 0 2px 15px; } '; } let z_div_style=z_div + z_style +'</style></div>'; if(am==0){ if(!document.querySelector('#z_panel')){ document.querySelector('#ambHeader div:first-child') .insertAdjacentHTML('beforeend', z_div_style); }} else if(am==1){ if(!document.querySelector('#z_panel')){ document.querySelector('#ambHeaderLeft') .insertAdjacentHTML('beforeend', z_div_style); }} let z_panel=document.querySelector('#z_panel'); let z_close=z_panel.querySelector('#z_close'); z_close.onclick=function(){ edit_mode=0; zoom_reset(); win_html.style.overflow='auto'; // ウインドウのスクロールを再開 z_panel.remove(); } let z_num=z_panel.querySelector('#z_num'); if(remember_id.indexOf(user_id)!=-1){ zoom_value=remember_zoom[remember_id.indexOf(user_id)]; } else{ if(zoom_auto==1){ zoom_value=1.14; } else{ zoom_value=1; }} z_num.value=Math.round(zoom_value*100); document.onwheel=function(event){ // マスウホイールで設定 event.stopPropagation(); event.stopImmediatePropagation(); if(event.deltaY<0 && edit_mode==1){ z_num.stepUp(); } else if(event.deltaY>0 && edit_mode==1){ z_num.stepDown(); } if(edit_mode==1){ ch_zoom(z_num.value/100); }} let z_set=z_panel.querySelector('#z_set'); z_set.onclick=function(){ let zoom_set=z_num.value/100; // 登録するzoom倍率 if(remember_id.indexOf(user_id)==-1){ // 未登録のIDの場合 remember_data.push([user_id, zoom_set]); // 等倍も登録する let write_json=JSON.stringify(remember_data); localStorage.setItem('remember_zoom', write_json); } else if(remember_id.indexOf(user_id)!=-1){ // 既登録のIDの場合 remember_data.splice(remember_id.indexOf(user_id), 1); // 一旦は登録削除 remember_data.push([user_id, zoom_set]); // 登録値を更新して追加 let write_json=JSON.stringify(remember_data); localStorage.setItem('remember_zoom', write_json); } reg_set(); edit_mode=0; do_zoom(); win_html.style.overflow='auto'; // ウインドウのスクロールを再開 z_panel.remove(); } let z_reset=z_panel.querySelector('#z_reset'); z_reset.onclick=function(){ if(remember_id.indexOf(user_id)==-1){ ; } // 未登録のIDの場合 else if(remember_id.indexOf(user_id)!=-1){ // 既登録のIDの場合 remember_data.splice(remember_id.indexOf(user_id), 1); // Resetは登録削除 let write_json=JSON.stringify(remember_data); localStorage.setItem('remember_zoom', write_json); } reg_set(); edit_mode=0; do_zoom(); win_html.style.overflow='auto'; // ウインドウのスクロールを再開 z_panel.remove(); } let z_exp=z_panel.querySelector('#z_exp'); z_exp.onclick=function(){ let write_json=JSON.stringify(remember_data); let blob=new Blob([write_json], {type: 'application/json'}); try{ let a_elem=document.createElement('a'); a_elem.href=URL.createObjectURL(blob); document.body.appendChild(a_elem); if(am==0){ a_elem.download='remember_zoom.json'; } // 保存ファイル名(一般ブログ記事) else if(am==1){ a_elem.download='remember_zoom_am.json'; } // 保存ファイル名(アメンバー記事) a_elem.click(); URL.revokeObjectURL(a_elem.href); alert("✅ ファイルを保存しました\n"+ " ダウンロードフォルダーを確認してください"); } catch(e){ alert("❌ ファイル保存時にエラーが発生しました\n"+ " ダウンロードフォルダーを確認してください"); }} let z_imp=z_panel.querySelector('#z_imp'); let z_file=z_panel.querySelector('#z_file'); z_imp.onclick=function(){ z_file.click(); } z_file.addEventListener("change" , function(){ if(!(z_file.value)) return; // ファイルが選択されない場合 let file_list=z_file.files; if(!file_list) return; // ファイルリストが選択されない場合 let file=file_list[0]; if(!file) return; // ファイルが無い場合 let file_reader=new FileReader(); file_reader.readAsText(file); file_reader.onload=function(){ if((am==0 && file_reader.result.slice(0, 15)=='[["user","zoom"') || (am==1 && file_reader.result.slice(0, 15)=='[["u_am","zoom"')){ // ファイルデータの確認 remember_data=JSON.parse(file_reader.result); // 読出してストレージを上書きする let write_json=JSON.stringify(remember_data); localStorage.setItem('remember_zoom', write_json); // ローカルストレージ 保存名 reg_set(); zoom_reset(); // 画面の拡大表示をリセット alert("✅ 拡大率の登録データを読込みました\n"+ " 読込んだファイル名: " + file.name); } else{ alert("❌ Remember My Page の Exportファイルではありません\n"+ " Importファイルは 「remember_zoom ... 」の名前です"); }}}); let z_mag=z_panel.querySelector('#z_mag'); let chrome_value=Math.round(((window.outerWidth - 16) / window.innerWidth)*100); if(chrome_value!=100){ z_mag.innerHTML='Basic ' + chrome_value + '%'; z_panel.style.zIndex='2'; setTimeout(()=>{ z_mag.style.opacity='0'; }, 3000); setTimeout(()=>{ z_mag.style.display='none'; z_panel.style.zIndex='0'; }, 6000); } else{ z_mag.style.display='none'; } } // backup() function path_change(){ // zoomの設定中にページ変更をした場合 let win_html=document.documentElement; let z_panel=document.querySelector('#z_panel'); if(edit_mode==1 && !z_panel){ edit_mode=0; win_html.style.overflow='auto'; // ウインドウのスクロールを再開 do_zoom(); } // 画面の拡大表示をリセット else if(edit_mode==1 && z_panel){ let z_num=document.querySelector('#z_num'); if(remember_id.indexOf(user_id)!=-1){ zoom_value=remember_zoom[remember_id.indexOf(user_id)]; } else{ if(zoom_auto==1){ zoom_value=1.14; } else{ zoom_value=1; }} z_num.value=Math.round(zoom_value*100); } // 拡大値表示をリセット } // path_change()
「RemPage For Chrome」最新版について
旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。
●「RemPage For Chrome」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。