【配布】AA/AAAモードをクライアント側で対応させるJavaScript【Blog/WordPress】
AA/AAAモードとは
AAはアスキー・アートの略です。AAモードはおーぷん2ちゃんねるの機能で、AAを通常の書き込みと区別して、キレイに等幅フォントで示すためのものです。等幅フォントでは通常の書き込みが読み難い反面、プロポーショナルフォントではAAがズレてしまう、行間も適切に見えないといった問題を解決してくれました。
AAAモードはこれを一定の時間で表示を切り替えることによって、AAでアニメーションを行わせるという機能です。
仕様
工事中。暇ができたら書き足す。
導入方法
JavaScript
以下をコピペして、aamode.jsの名前で保存してください。
document.addEventListener('DOMContentLoaded', function () {
//速度設定
const baseTime = 1000;
//速度設定に対するデフォルトの倍率
const defaultWait = 0.2;
//フォントサイズ設定
const fontSize=16;
//フォント色
const fontColor='#000';
//背景色
const bgColor='#fff';
//CSSで指定したフォントファミリ名
const fontFace ='aahub_light';
const targetClass = 't_b';
const aaMarker = /!AA\s*<br[^>]*>/;
const aaPreClass = 'aaview';
const aaaPreClass = 'aaaView';
const newLineRExp = /<br[^>]*>/g;
const aaaMarker = /@(AAA|aaa)/;
const aaaSplitter = '@@@';
let aaaFlag = false;
let postBodies = document.getElementsByClassName(targetClass);
for (let postBody of postBodies) {
if (aaMarker.test(postBody.innerHTML)) {
let aaPre = document.createElement('pre');
aaPre.setAttribute('class', aaPreClass);
let str = postBody.innerHTML.split(aaMarker);
postBody.innerHTML = str.shift();
while (0 < str.length) {
let lines = str.shift().replace(/\n/g, '').replace(newLineRExp, '\n').split('\n');
while (0 < lines.length) {
if (!aaaMarker.test(lines[0])) {
aaPre.innerHTML += lines.shift() + '\n';
} else {
let aaaPre = document.createElement('div');
aaaPre.setAttribute('class', aaaPreClass);
let aaaInterval = document.createElement('div');
aaaInterval.setAttribute('style', 'display:none');
aaaInterval.setAttribute('class', 'interval');
aaaInterval.textContent = lines.shift().replace(aaaMarker, '').replace(':', '');
let aaaContent = document.createElement('div');
aaaContent.setAttribute('style', 'display:none');
aaaContent.setAttribute('class', 'content');
aaaContent.textContent = lines.join('\n');
let aaaDisplay = document.createElement('canvas');
aaaDisplay.setAttribute('class', 'display');
aaaPre.appendChild(aaaInterval);
aaaPre.appendChild(aaaContent);
aaaPre.appendChild(aaaDisplay);
aaPre.appendChild(aaaPre);
aaaFlag = true;
lines = [];
continue;
}
}
postBody.appendChild(aaPre);
}
}
}
if (aaaFlag) {
const aaaDivs = document.getElementsByClassName(aaaPreClass);
for (let aaaDiv of aaaDivs) {
animateAaa(aaaDiv);
}
}
function animateAaa(aaaDiv) {
let interval = aaaDiv.getElementsByClassName('interval')[0].textContent;
if ('' == interval || 0 == interval) {
interval = baseTime * defaultWait;
} else {
interval = baseTime * parseFloat(interval);
}
const contents = aaaDiv.getElementsByClassName('content')[0].textContent.split(aaaSplitter + '\n');
const canvas =aaaDiv.getElementsByClassName('display')[0];
const ctx = canvas.getContext('2d');
ctx.font = fontSize + "px aahub_light,sans-serif";
let canvasSize = getCanvasSize(contents);
canvas.width=(canvasSize.x+4)*(fontSize/2);
ctx.width =canvas.width;
canvas.height=canvasSize.y*(fontSize+1)*1.1;
ctx.height= canvas.height;
let i = 0;
let max = contents.length;
setInterval(() => {
if (max == i) {
i = 0;
}
ctx.font = fontSize + "px aahub_light,sans-serif";
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle =bgColor;
ctx.fillRect(0,0,ctx.width,ctx.height);
showAA(ctx,contents[i]);
i = (i+1)|0;
}, interval);
function getCanvasSize(contents){
let size ={x:0,y:0};
contents.forEach(element => {
let lines =element.split('\n');
size.y = Math.max(lines.length,size.y);
for (let line of lines){
size.x = Math.max(line.length,size.x);
}
});
return size;
}
function showAA(ctx,content){
let lines = content.split('\n');
for(let i=0;i<lines.length;i=(i+1)|0){
ctx.fillStyle = fontColor;
ctx.font = fontSize + 'px '+ fontFace' +',sans-serif";
ctx.fillText(lines[i], fontSize/2, fontSize*(1.1*(2*i+3)/2));
}
}
}
});
はじめの5つをお好みに設定してください。6つ目のフォントファミリ名については、CSSの項で述べます。
CSS/HTML
ローカルで表示を確認したい方は以下をコピペし、index.htmlという名前で保存してください。
ブログ・WordPressでのご利用の場合は、CSSに当たる部分を抜き出してコピペし、ご利用のブログ・WordPressで記事表示に適用されるCSSの中に含めてください。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>AA&AAAmodeTest</title>
<script type="text/javascript" src="aamode.js"></script>
<!--ココでフォント指定-->
<style type="text/css">
<!--
@font-face {
font-family: "aahub_light";
src: url("./fonts/aahub_light.woff2") format("woff2");
font-display: swap;
}
.aaview {
font-family: aahub_light, sans-serif !important;
font-size: 16px !important;
line-height: 18px !important;
margin: auto;
padding: 0.5em;
white-space: pre;
border: dotted 2px #c7dce3 !important;
overflow-x: auto;
}
-->
</style>
</head>
<body>
<!--ここから下に「まとめくす」でコピーしたものを貼り付け-->
<p style="color:gray;text-align:right;">引用元: <a href="https://hayabusa.open2ch.net/test/read.cgi/livejupiter/1607385735/" target="_blank">なんでもAA</a></p><dl></dl><!-- Generated by まとめくす (https://2mtmex.com/) -->
<dl><dt >26: <span style="color: green; font-weight: bold;">名無しさん@おーぷん</span> <span style="color: gray;"> 20/12/08(火)09:47:34 ID:uwQ</span></dt>
<dd class="t_b" style="margin-bottom:4px;margin-top:2px;"> !AA<br /> \ はげって言ったやつだれだ・・・ /\ ノ<br /> \ /- ̄  ̄`ヽ<br /> (~) \ γ´⌒`ヽ /γ´ ヽ<br /> γ´⌒`ヽ \ (・ω・` ) /γ ヽ<br /> {i:i:i:i:i:i:i:i:} \ O┬O:::) / {i:i:i:i:i:i::i:i:i:i:i:i:i:i:i:::i:i:i:i:i:i:ii}<br /> ( ´・ω・)このセーター\ ◎┴し'-◎ / . (~):i:i:i:i::i:i:i:i:i::i:i:i:i::i:i:i:i:i:i:i}<br /> (:::::::::::::) しまむらで \ ∧∧∧∧/ γ´⌒`ヽ ::|<br /> し─J 買ったんだ。 < し > {i:i:i:i:i:i:i:i:}l⌒l l⌒l :::::|<br />_____________ < ま > (´・ω・`) ̄  ̄ ::::|<br /> /~~丶 < の む > (::::::::つ :::|<br /> \ ノ < 予 ら > ヽ__つ l⌒l l⌒l ::|<br /> γ-´ ̄ ̄ ̄ ̄``ヽ キング < 感 く > ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄<br />γ │しまむら < ! ん > (~) さむいね<br />{i:i:i:i:i:i:i:i::i:i:i:i:i:i:i::i::i:ii:i} くん/∨∨∨∨ γ´⌒`ヽ<br />{i:i:i:i:i:i:i:i::i:i:i:i:i:i:i::i::i::i:i} / \ {i:i:i:i:i:i:i:i:} うん、さむいね<br />/ ⌒ ヽ / \ ( ´・ω・) (~)<br />| ● ● | / (~) \ ( ) γ´⌒`ヽ<br />ヽ、 (__人__) ノ /γ´⌒`ヽユニクロ行ってくる\し─J {i:i:i:i:i:i:i:i:}<br /> /:::::::::::::::::::::::・:::::::::::/ {i:i:i:i:i:i:i:i:} _____\ (・ω・` )<br /> |::::::::::::::::::::::::・::::::/ ( ´・ω・`) | しまむら →| \ ( )<br /> ヽ、:::::::::::::::::::::/ (:::O┬O  ̄ ̄ || ̄ ̄ \ し─J<br /> | / ◎-ヽJ┴◎ キコキコ \<br /> |__丿/ \ </dd>
</dl>
<dl><dt >25: <span style="color: green; font-weight: bold;">名無しさん@おーぷん</span> <span style="color: gray;"> 20/10/17(土)17:41:28 ID:Wl9</span></dt>
<dd class="t_b" style="margin-bottom:4px;margin-top:2px;"> !AA<br />ズレてたから修正<br />@aaa:0<br /> / / / /<br /> _n_<br /> ///|ヾ \ / /<br /> ⌒⌒|⌒⌒<br />/ |∧_∧ / /<br /> |・ω・`)<br /> / Oと ) / /<br />、 しーJ ,.. ,. .。 _<br />@@@<br />/ / /<br /> _n_/<br /> ///|ヾ \ /<br /> ⌒⌒|⌒⌒/ /<br /> / |∧_∧ <br /> |・ω・`) /<br />/ Oと ) /<br />、 しーJ, 、,. 。<br />@@@<br /> / /<br /> _n_ /<br /> ///|ヾ \ <br /> ⌒⌒|⌒⌒ /<br />/ |∧_∧ <br /> |・ω・`) /<br /> / Oと ) /<br />。 、 しーJ., _._ 、,.<br />@@@<br /> / /<br /> _n_ <br /> ///|ヾ \ / /<br /> ⌒⌒|⌒⌒ <br /> / |∧_∧ / /<br /> |・ω・`) <br />/ Oと )/ /<br />_., しーJ。 、 _ _._<br />@@@<br />/ / /<br /> _n_ /<br /> ///|ヾ \ <br /> ⌒⌒|⌒⌒/ /<br />/ |∧_∧ /<br /> |・ω・`) /<br /> / Oと ) / /<br /> , ._ しーJ.,_ 。 .,. 、,. </dd>
</dl>
<dl><dt >3: <span style="color: green; font-weight: bold;">名無しさん@おーぷん</span> <span style="color: gray;"> 20/12/06(日)00:37:04 ID:b6x</span></dt>
<dd class="t_b" style="margin-bottom:4px;margin-top:2px;"> !AA<br />@aaa<br />い<br />@@@<br />いk<br />@@@<br />いき<br />@@@<br />いきs<br />@@@<br />いきす<br />@@@<br />いきすg<br />@@@<br />いきすぎ<br />@@@<br />いきすぎい<br />@@@<br />イキスギイ </dd>
<dt >19: <span style="color: green; font-weight: bold;">名無しさん@おーぷん</span> <span style="color: gray;"> 20/12/06(日)00:50:10 ID:qAn</span></dt>
<dd class="t_b" style="margin-bottom:4px;margin-top:2px;"> !AA<br />@AAA:0.1<br />る さ<br />@@@<br /> さと<br />@@@<br /> さとる<br />@@@<br />さとる<br />@@@<br />とる </dd>
</dl>
<!--ここまで。上の内容は削除してOK-->
</body>
</html>
上記では、AA表示に適したフォントを利用するため、こちらからaahub_lightをダウンロードし、利用するように記述してあります。ローカルで用いる場合はindex.htmlを置くフォルダの下に/fontsフォルダを作って置くか、同じフォルダに置いて上の記述の./fonts/を消すかして下さい。
使い方
index.htmlに書いた通り、まとめくすさんでレスを選んで出力したものを<body></body>の内部にコピペして、index.htmlをブラウザで開いてください。
おーぷんを利用する限りはAAAの更新速度の微調整は、HTML側の速度指定用の数値(!AAA:ここの数字)でしか変更できませんが、スクリプトを利用する場合はbaseTimeを自由に変更できますので、お好みの速度を作り出せることでしょう。
baseTimeはデフォルトで1000となっており、1000ミリ秒を表します。これに!AAAコマンドで指定した数値を掛けた秒数ごとに(ブラウザの能力が追いつく限りは)アニメーションの更新を行おうと努めます。コマンド指定が0.1ならば100ミリ秒、つまり0.1秒ごとです。baseTimeを1、コマンド指定を16にすれば0.016秒ごとの更新となり、秒間60フレームを少々上回るレートとなりますが、ブラウザ側がその速度を出せるかどうかは私にはわかりません。
工事中
以下、暇を見て必要な事項を書き足す予定。