プログ

’14修了無内定理系院卒の活動雑記||プー太郎ログ||プログラミング雑記

テキスト編集

ブラウザから画像を出力 - プログ

の続き.

進捗

f:id:triplog:20140518175209p:plain
昨日とほぼ同じ.

前置き

canvas はその名の通りキャンバスなので上に描き重ねるしかできない.これはテキストにおいても同様であり,「入力したテキストを消す」ということは無理である.これはペイントでテキストを入力している時のイメージに近い.そのため,以前は文字エリアで楽に出来たことも別手段を取る必要が出てくる.

テキストの表示

function init_text(){
  //canvasの探索
  var canvas = document.getElementById("srcImg");
  var context= canvas.getContext("2d");
  //フォントの指定
  context.font = "16px 'YasashisaAntique'";
  //縦書で表示
  tategaki(context, "ラーメン三銃士を連れてきたよ。", 197, 21, 8);
  //省略
}
//縦書にする関数.x:x座標 y:y座標 num:一列の文字数
function tategaki(context, text, x, y, num) {
  //1文字の幅を取得
  var lineHeight = context.measureText("あ").width;
  //各文字について処理
  Array.prototype.forEach.call(text,function(ch,i){
    //横に伸びる棒は縦棒に置き換え
    if(ch==='ー'||ch==='-'||ch==='―')
      context.fillText('|', x-lineHeight*Math.floor(i/num), y+lineHeight*(i%num));
    //横書きで左下にあるものは縦書きでは右上に
    else if(ch==='、'||ch===','||ch==='。'||ch==='.'||ch==='.'||ch===',')
      context.fillText(ch, x-lineHeight*(Math.floor(i/num)-0.6), y+lineHeight*(i%num-0.6));
    //通常のテキスト
    else
      //一文字ごとに描画位置を移動していく
      context.fillText(ch, x-lineHeight*Math.floor(i/num), y+lineHeight*(i%num));
  });
};

canvas に対し CSS で style で変更しても反映が見られないため,一文字ずつ位置をズラしながら描画する手法を取っている.参考にした手法は改行文字で改行していたが,枠が狭い&&改行入力をユーザに求めるのは面倒なため一定の文字数ごとに改行するよう変更している.font-face は CSS の方で登録しておくのは勿論のこと,事前に読み込んでおく必要があるので load イベントなどで呼び出すと読み込む前に呼び出そうとして失敗に終わる点に注意.今回はhtmlの中で一度利用しておくことで読み込む手法を取った(進捗画面の赤丸部分,ソースは省略).なお英数字に関しては,採用した YasashisaAntique がすべて全角のように扱うため,特別な処理はしないこととした.

参考
font プロパティ - Canvasリファレンス - HTML5.JP
HTML5 Canvas で縦書き対応してみた | TM Life
font = "スタイル・サイズ・種類"-Canvasリファレンス

テキストの反映

//テキストを吹き出しに書き込む
function inputText(text, id){
  var canvas = document.getElementById("srcImg");
  var context= canvas.getContext("2d");
  context.font = "16px 'YasashisaAntique'";

  //フォームごとに書き込み先を変更
  switch(id){
    case 0:
      tategaki(context, text, 197,  21, 8);
      break;
  //省略
  }
}
//画面を更新
function renewText(){
  //元画像を再配置で初期化
  init();
  //すべてのフォーム内容を書き込み
  for(var i=0;i<8;i++){
    var text = $('#edit>input:eq('+i+')').val();
    inputText(text,i);
  }
}
//キーが押されるごとに画面更新
$(window).keyup(function(){
  renewText();
});

前述した canvas の問題として入力したテキストだけを消すことはできないので,初期化し再配置することで実現する.逆に初期化は canvas の仕様のお陰で元画像を読み込むだけで済む.jQueryで「'#edit>input:eq('+i+')'」の様に指定できたことでかなりすっきり書けたように思える.また,以前 focus や blur でうまいこと逐次更新されないと嘆いていたが,keyup イベントをウィンドウ全体に適用することで実現できた.幸いな事に再配置処理にはほとんど時間がかからないため,入力内容は滞り無く反映される.ここらへんをいじっていた時に発覚した注意点として,jQueryを含むjsファイルを読み込むのはjQueryのリンクを読み込みより下に記述しないとうまく動作しない.

コマンド処理

function buttonClear(){
  $('#edit>input:lt(8)').val("");
  renewText();
}
function buttonOriginalize(){
  $('#edit>input:eq(0)').val("ラーメン三銃士を連れてきたよ。");
  //省略
  renewText();
}

ボタンを押すことで全消しor元ネタ通りに一新するコマンド.大したことやってないんだけどjQueryで簡単に記述できたので一応,jQueryすごく便利.ただよそから持ってきたコードは使ってないものが多いので統一感が無いのが玉に瑕.もしかしてなるべく使わないようにした方がいいのかな.