入力したテキストを画像に変換する

アスキーアートの画像化 テキスト画像生成ツール

Canvas Text to PNG

Canvasで文字描画

WxH: x autoWidth:
X,Y: x SCALE X,Y: x
FontSize: font: bold: color:
textAlign: textBaseLine: taegaki:
  • Input (ここにテキストを入力してください)

  • Canvas

    canvas
  • PNG (DL)

    canvasText.png
view source

JavaScript

$(function(){
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');

  var e = {};
  e.textarea = $('#textarea');
  e.canvas = $('#canvas');
  e.a = $('#imgLink');
  e.img = $('#img');

  var o = [];
  //o.fontFamily = 'MS PGothic';

  function readyEvent(){
    //イベント監視
    $('input').on('change', function(){
      //resizeCanvas();
    });
    $('input,select,textarea').each(function(){
      var name = $(this).attr('name');
      var type = $(this).attr('type');
      var val = $(this).val();
      e[name] = $(this);
      o[name] = val;
      if(type === 'checkbox'){
        o[name] = $(this).prop('checked');
      }
      console.log(o[name]);
    });
    $('input,select,textarea').on('change', function(){
      var name = $(this).attr('name');
      var type = $(this).attr('type');
      var val = $(this).val();
      o[name] = val;
      if(type === 'checkbox'){
        o[name] = $(this).prop('checked');
      }
      if($(this).hasClass('css')){
        var hash = {};
        hash[name] = val;
        e.textarea.css(hash);
      }
      console.log(o);
    });

    $('input[name="w"]').on('focus', function(){
      $('[name="isAutoWidth"]').prop('checked', false).change();
    });
    $('.css').on('change', function(){
      var name = $(this).attr('name');
      var val = $(this).val();
    });

    $('#clear').click(function(){
      ctx.clearRect(o.x, o.y, o.w, o.h);
      drawWhite();
      toPng();
    });
    $('#overlay').click(function(){
      drawText(o.text);
      toPng();
    });
    $('#reload').click(function(){
      var text = e.textarea.val();
      ctx.clearRect(o.x, o.y, o.w, o.h);
      drawText();
      toPng();
    });

    e.isAutoWidth.prop('checked', true).change();
  }
  readyEvent();
  console.log(o);
  resizeCanvas();

  //画像変換
  function toPng(){
    var url = canvas.toDataURL();

    //圧縮 canvastool.pngencoder.min.js
    var encoder = new CanvasTool.PngEncoder(
        canvas,
        {
/*
            bitDepth: 8,
            colourType: CanvasTool.PngEncoder.ColourType.INDEXED_COLOR
*/
        }
    );
    var png = encoder.convert();
    url = 'data:image/png;base64,' + window.btoa(png);


    var link = url.replace('image/png', 'application/octet-stream');
    e.a.attr({'href': link, 'download': 'text-' + o.text.substr(0,9) + '.png'});
    e.img.attr({'src': url});
  }

  //サイズ変更
  function resizeCanvas(){
    e.w.val(o.w).change();
    e.h.val(o.h).change();
    canvas.width = o.w;
    canvas.height = o.h;
    fontSize = o.fontSize || 9;
    ctx = canvas.getContext('2d');

    var attr = {
      width: o.w,
      height:o.h
    };
    e.textarea.css(attr);
    e.canvas.css(attr);
    e.img.css(attr);
  }

  //テキスト描画
  function drawText() {
    ctx.beginPath();
    textList = o.text.split('\n');
    //自動サイズ変更チェック
    console.log(o.isAutoWidth);
    if(o.isAutoWidth){
      autoResize(textList);
    }
    resizeCanvas();
    setFontStyle();

    //ctx.fillText(text, x, y, 200);
    //UnToDo:自動改行はめんどくさい
    //ctx.measureText(v).height は存在しない 
    var lineHeight = 2;
    o.text.split('').forEach(function(v){
      if(ctx.measureText(v).width > lineHeight){
        lineHeight = ctx.measureText(v).width;
        console.log(lineHeight);
      }
    });


    var xAlign = {
      'left' : 0,
      'center' : o.w/2 - o.textLength/2,
      'right' : o.w - o.textLength,
    };
    var textX = xAlign[o.textAlign] || 0;

    ctx.scale(o.scaleX, o.scaleY);
    if(o.Tategaki){
      tategaki(ctx, o.text, 0,0)
    } else {
      textList.forEach(function(text, i) {
        ctx.fillText(o.text, o.x + textX, o.y+lineHeight*i);
        ctx.scale(o.scaleX, o.scaleY);
      });
    }


  }
    
  var tategaki = function(context, text) {
    var textList = o.text.split('\n');
    var lineHeight = context.measureText("あ").width;
    textList.forEach(function(elm, i) {
      Array.prototype.forEach.call(elm, function(ch, j) {
        context.fillText(ch, o.x-lineHeight*i, o.y+lineHeight*j);
      });
    });
  };

  //自動サイズ変更
  function autoResize(){
    console.log('????');
    var maxLineText = 0;
    var maxLength = 0;
    var textList = o.text.split('\n');
    textList.forEach(function(text, i) {
      var textListWidth = ctx.measureText(text).width;
      if(textListWidth > maxLineText){
        maxLineText = textListWidth;
      }
      if(o.text.length > maxLength){
        maxLength = o.text.length;
      }
    });
    o.textLength = maxLength;
    console.log(maxLineText);
    o.w = Math.ceil(maxLineText);
    o.h = textList.length * fontSize;
    if(o.isTategaki){
      o.w = Math.ceil(o.fontSize);
      o.h = Math.ceil(o.fontSize) * maxLength;
    }
    o.w *= o.scaleX;
    o.h *= o.scaleY;
    console.log([o.w, o.h]);
  }

  function setFontStyle(){
    ctx.fillStyle = o.color;  
    var fontWeight =  o.isBold ? 'bold' : 'normal';
    var font = fontWeight + ' '+ o.fontSize + 'px' + ' ' + '"' + o.fontFamily + '"';//"MS ゴシック"
    console.log(font);
    ctx.font = font
    ctx.textAlign = o.textAlign;
    ctx.textBaseline = o.textBaseline;
  }

  function drawWhite(){
    ctx.fillStyle = "rgba(255, 255, 255, 1)";
    ctx.fillRect (o.x, o.y, o.w, o.h);
  }

});

CSS

@font-face {
  font-family: 'pixelmplus12';
  src :url('/font/PixelMplus12-Bold.ttf') format('truetype');
/*
  src:
   url('font/pixelmplus12-bold-webfont.eot') format('eot'),
   url('font/pixelmplus12-bold-webfont.ttf') format('truetype'),
   url('font/pixelmplus12-bold-webfont.woff') format('woff'),
   url('font/pixelmplus12-bold-webfont.woff2') format('woff2'),
   url('font/pixelmplus12-bold-webfont.svg') format('svg');
*/
}

@font-face {
  font-family: 'Noto JP Black';
  font-style: normal;
  font-weight: 400;
  src: url(/fonts/NotoSansJP-Black.otf) format('opentype');
}
@font-face {
  font-family: 'Noto JP Thin';
  font-style: normal;
  font-weight: 100;
  src: url(/fonts/NotoSansJP-Thin-Windows.otf) format('opentype');
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 100;
  src: url(/fonts/Roboto-Black.ttf) format('truetype');
}
@font-face {
  font-family: 'MPlus';
  font-style: normal;
  font-weight: 100;
  src: url(/fonts/mplus-1c-black.ttf) format('truetype');
}
@font-face {
  font-family: 'Yourself';
  font-style: normal;
  src: url(/fonts/Yourself.ttf) format('truetype');
}
@font-face {
  font-family: 'zephyreg';
  font-style: normal;
  src: url(/fonts/zephyreg.ttf) format('truetype');
}


#inputArea{
  margin:8px 0;
}

#inputArea input{
  margin:4px 0;
}

input[type="number"]{
  width:40px;
}
input[type="text"]{
  width:60px;
}

canvas,
textarea,
#img{
  min-width:12px;
  min-height:12px;
  /*
  width:200px;
  height:200px;
  */
  border:1px solid #999999;
  font-size:12px;
}

textarea{
  min-height:28px;
  min-width:120px;
  background-color:#eeeeee;
  box-sizing:border-box;
}
#textarea{
  width:80%;
  height:40px;
}
#reload{
  width:160px;
  height:32px;
}

.hori:after{
  display:block;
  content:"";
  clear:both;
}
.hori li{
  min-width:200px;
  float:left;
}

HTML

ページのソースを表示 : Ctrl+U , DevTools : F12

view-source:https://hi0a.com/demo/-js/js-canvas-text/

ABOUT

hi0a.com 「ひまアプリ」は無料で遊べるミニゲームや便利ツールを公開しています。

プログラミング言語の動作デモやWEBデザイン、ソースコード、フロントエンド等の開発者のための技術を公開しています。

必要な機能の関数をコピペ利用したり勉強に活用できます。

プログラムの動作サンプル結果は画面上部に出力表示されています。

環境:最新のブラウザ GoogleChrome / Windows / Android / iPhone 等の端末で動作確認しています。

画像素材や音素材は半分自作でフリー素材配布サイトも利用しています。LINK参照。

動く便利なものが好きなだけで技術自体に興味はないのでコードは汚いです。

途中放置や実験状態、仕様変更、API廃止等で動かないページもあります。