人様に勧める自信がだんだん無くなるツール
アメブロ公式スキンの基本フォントサイズは、時代に合わせて拡大されて来ました。
2004年当初の「レトロタイプスキン」は「12px」でしたが、これは現在も使っている方が居られます。 その後に「旧タイプスキン」の「14px」、更に「新タイプスキン」で「16px」になりました。 この拡大は、ユーザーが使用するPCモニターの高精細化に合わせて、実表示の文字サイズを大きくする必要があったからです。(高精細モニターではフォントはより小さく表示されるため)
「RemPage」ツール(旧名 Remember My Page)は、文字が小さく読みづらいブログを、自動的に読み易く拡大して表示する目的で制作したものです。(ブラウザの拡大機能はドメインごとに拡大率を記憶できますが、アメーバ内は全て「ameblo.jp」のドメインで、ブログ個別の拡大率を記憶できません。)
このツールは、先ずページの文字サイズを判定して、自動で読み易い拡大をします。 しかし、独自のアレンジを施したページでは、自動判定が通用しない場合があるので、その場合はこちらで拡大率を設定して記憶させる事が出来ます。
問題点が多い
この機能、完璧に動作するならとても良い機能ですが、残念な事に幾つも問題を抱えています。 最初に直面したのは、画面拡大機能で使い易い「zoom」プロパティが、 Chromeは対応するが Firefoxでは使えない事です。 これで、Firefox版は現在も実験版の域を出ません。 ページ表示上の問題があり、実用的とはとても言えなません。
Chrome版の方は一応は使えるますが、長く使っていると「なんだかな」の問題に時々気付きます。 今回は、やたら「スクリプトエラー」を吐いていました。 実害の程度は不明ですが、エラー元を調べると前バージョンの更新が原因でした。
144行のコードで、ページに拡大率を設定する「styleタグ」を、「remove」で削除しては生成する「更新」タイプにしています。
このコードはページ読込みで各種のパーツが生成される度に、不必要に「styleタグ」を更新し、以下のエラーが多発します。 内容はページがどんどん変化しているので「MutationObserver」は処理を飛ばしますというもの。
DevToolsのエラー表示は下の様に、このエラーだらけです。 飛ばされたのはこのツールの拡大処理で、不要な拡大処理を強いていた結果です。
これがページ表示の足を引っ張る程度は不明ですが、errorは無いにこした事はありません。
で、コードを修正して、ページ読込み時は「styleタグ」は1回生成するだけに改めました。「更新型」のコードは、拡大率の設定の際に必要で、ユーザー設定時のみ「更新型」となる様に改めました。
これで今回のエラー増産は、あっさり改善しています。
勧められるツールなのか?
正直な所、このツールは色々と問題を引き起こし易いと感じています。「zoom」プロパティを使うページの拡大表示は、ブラウザの「ページ拡大表示」とは異なります。 例えば、要素の位置(x, y)を取得する場合、「zoom」表下では取得値に補正が必要ですが、ブラウザ拡大の場合は不要です。
そういった問題がいつも生じるわけでは有りませんが、「zoom」「transform」などのどれを使っても、ページ全体の拡大・縮小表示は厄介な作業と感じます。 もし、ブラウザ拡大機能を拡張機能のレベルで利用できたら、もっと万能のツールを作れると思います。 しかし、私は現在のところは、「Tampermonkey」を使う、ユーザースクリプトのツール制作を基本にしていますので。
という事で、「RemPage For Chrome」を利用する場合は、不完全な部分があるかもしれないツールと考えて扱ってください。
「RemPage For Chrome」の扱い方
「RemPage For Chrome」の扱い方は以下のページに纏めています。
「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.4
// ==UserScript== // @name RemPage For Chrome // @namespace http://tampermonkey.net/ // @version 3.4 // @description ブログページ拡大表示をブログ単位で記録・固定(zoom使用) // @author Ameba Blog User // @match https://ameblo.jp/* // @exclude https://ameblo.jp/*/image* // @run-at document-start // @noframes // @grant none // ==/UserScript== let remember_data={}; // ブログ登録データ let remember_id=[]; let remember_zoom=[]; let z_button; let user_id; let zoom_value; let zoom_auto=0; let edit_mode=0; reg_set(); function reg_set(){ let read_json=localStorage.getItem('remember_zoom'); // ローカルストレージ 保存名 remember_data=JSON.parse(read_json); if(remember_data==null){ remember_data=[['user', '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(); setTimeout(()=>{ center(); }, 100); let target0=document.querySelector('head'); // 監視 target let monitor0=new MutationObserver(do_zoom); monitor0.observe(target0, { childList: true }); // 監視開始 let target1=document.querySelector('#announcer'); // 監視 target if(target1){ let monitor1=new MutationObserver(path_change); monitor1.observe(target1, { childList: true }); } // 監視開始 } // zoom_startup() function do_zoom(){ zoom_reset(); center(); backup_set(); } 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が取得出来ない場合 ch_zoom(zoom_value); // Chrome場合 拡大実行 } // zoom_reset() zoom値の選択と拡大実行 function ch_zoom(val){ // Chrome用のページ拡大コードを生成 let style; if(val!=1){ style= '<style id=chzoom>body { zoom: '+ val +' } '+ '#ambHeader, footer, .ReactModalPortal { zoom: '+ 1/val +' } '+ '._20TD20u0, ._HQiG1eoZ { display: none } '; } else{ style= '<style id=chzoom>'+ '._20TD20u0, ._HQiG1eoZ { display: none } '; } style+= '#ambHeader img[alt="Ameba"] { filter: contrast(6) hue-rotate(90deg); '; if(zoom_auto==0){ // 未登録 zoom 無し style+= 'box-shadow: none; padding-left: 0 }</style>'; } else if(zoom_auto==1){ // 未登録 auto zoom style+= 'box-shadow: -10px 0 0 #e98200; padding-left: 5px }</style>'; } else if(zoom_auto==2){ // 登録有 manual zoom style+= 'box-shadow: -10px 0 0 #7aff00; padding-left: 5px }</style>'; } else if(zoom_auto==3){ // 登録有 100% zoom style+= 'box-shadow: -10px 0 0 #9c27b0; padding-left: 5px }</style>'; } if(!document.querySelector('#chzoom')){ document.documentElement.insertAdjacentHTML('beforeend', style); } } // ch_zoom() function center(){ // 記事本文を中央に配置 let ht=document.documentElement.scrollTop; 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; let scrooll_step=v_center - window_w/2 if(ht<10){ // 縦スクロール後は動作しない if(scrooll_step>10 || scrooll_step<-10){ scrollBy(scrooll_step, 0 ); }}}} function backup_set(){ z_button=document.querySelector('#ambHeader img[alt="Ameba"]'); if(z_button){ z_button.onclick=function(event){ // Amebaアイコンのクリック event.preventDefault(); // クリックしてもホームに飛ばさない backup(); }}} function backup(){ edit_mode=1; disp_panel(); let z_panel=document.querySelector('#z_panel'); if(z_panel){ let z_close=z_panel.querySelector('#z_close'); z_close.onclick=function(){ edit_mode=0; zoom_reset(); z_panel.remove(); } let z_num=z_panel.querySelector('#z_num'); 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){ remove_style(); ch_zoom(z_num.value/100); }} z_num.onchange=function(event){ event.stopPropagation(); event.stopImmediatePropagation(); if(edit_mode==1){ if(z_num.value<80){ z_num.value=80; } else if(z_num.value>200){ z_num.value=200; } remove_style(); 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; remove_style(); do_zoom(); 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; remove_style(); do_zoom(); 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); a_elem.download='remember_zoom.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(file_reader.result.slice(0, 15)=='[["user","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'; } } // if(z_panel) } // backup() function remove_style(){ if(document.querySelector('#chzoom')){ document.querySelector('#chzoom').remove(); }} function disp_panel(){ 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>'+ '<style>'+ 'html { overflow: hidden; } '+ '#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; } '+ '</style></div>'; if(!document.querySelector('#z_panel')){ document.querySelector('#ambHeader div:first-child') .insertAdjacentHTML('beforeend', z_div); } } // disp_panel() function path_change(){ // zoomの設定中にページ変更をした場合の error抑止 if(edit_mode==1){ edit_mode=0; let z_panel=document.querySelector('#z_panel'); if(z_panel){ z_panel.remove(); }} } // path_change()
〔追記〕2023.04
「secret.ameba.jp」のサブドメイン廃止に伴い、上記コードを修正しました。
ver. 3.3 ➔ ver. 3.4 に更新しています。
「RemPage For Chrome」最新版について
旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。
●「RemPage For Chrome」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。