JavaScriptのcanvasで縦書きを行う際の備忘録
canvas上に縦書きの文章を出力して画像化しようと考えてちょっとハマったので忘れないうちにメモしておきます。
結論から先に書くと、基本的にcanvasにはwriting-modeの設定が効くので、writing-mode:vertical-rl;を設定した後、fillRectで文字を描画し、90度回転させれば良いです。
しかし、なぜかcreateElementした場合は無理っぽい、という話です。
ちなみに説明するまでもない気もしますが、vertical-rlのrlはRight to Left、右から左という意味。
DIVタグで writing-mode を縦書き設定する例
<div style="writing-mode:vertical-rl;border:1px solid #cccccc;">
これは、縦書きのテストです。
</div>
実行結果ごく普通に問題ありません。
canvasタグで writing-mode を設定する例
<canvas id="canvas1" style="writing-mode:vertical-rl;border:1px solid #cccccc;"></canvas>
<script>
let canvas = document.getElementById('canvas1');
let ctx = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 300;
ctx.font = '20px Serif';
ctx.fillText('これは、縦書きのテストです。', 20, 20);
</script>
実行結果fillTextは横書きしか対応していませんが、writing-mode:vertical-rlが設定されると縦書きフォントが使用される模様。
canvasタグで writing-mode を設定した後、rotateした例
<canvas id="canvas2" style="writing-mode:vertical-rl;border:1px solid #cccccc;"></canvas>
<script>
let canvas2 = document.getElementById('canvas2');
let ctx2 = canvas2.getContext('2d');
canvas2.width = 300;
canvas2.height = 300;
ctx2.font = '20px Serif';
ctx2.save();
ctx2.translate(canvas2.width, 0);
ctx2.rotate(90 * Math.PI / 180);
ctx2.fillText('これは、縦書きのテストです。', 20, 20);
ctx2.restore();
</script>
実行結果問題なさそうに見えます。
canvasタグをcreateElementした場合、writing-modeが効かない
<div id="output"></div>
<script>
let canvas3 = document.createElement('canvas');
let ctx3 = canvas3.getContext('2d');
canvas3.style.writingMode = 'vertical-rl';
canvas3.style.border = '1px solid #cccccc';
canvas3.width = 300;
canvas3.height = 300;
ctx3.font = '20px Serif';
ctx3.save();
ctx3.translate(canvas3.width, 0);
ctx3.rotate(90 * Math.PI / 180);
ctx3.fillText('これは、縦書きのテストです。', 20, 20);
ctx3.restore();
document.getElementById('output').appendChild(canvas3);
</script>
実行結果謎い。
createElementでcanvasを作ったときだけ、どうしてもwriting-modeの指定が効きません。
webkitの指定じゃないといけないのかなー?と下記のようにsetPropertyの記述も試しましたが、同じ結果でした。
canvas3.style.setProperty('-webkit-writing-mode', 'vertical-rl');
canvas3.style.setProperty('-writing-mode', 'vertical-rl');
writing-modeの指定をした後にctx作らないといけないのかなー?とか、フォントの読み込み時間を待つ必要があるのかなー?とsetTimeoutで1秒以上遅延させてから書いたりもしましたが、いずれもダメ。
開発コンソールで確認する限り、createElementされたcanvasのstyleは正常に設定されているけれど、描画では反映されていないという結果でした。
何か自分が大きな勘違いをしている気がするのですが、とりあえず、createElementを使わず、最初からHTMLタグにcanvasが設置された状態なら、普通に縦書きできたので、ひとまずここに状況だけメモしておくことにしました。