質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

テキストエリアに入力した文字をcanvasに展開した際に一定の幅で改行させたいです

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,017

aDGDy02001

score 17

前提・実現したいこと

http://www.chaordic.co.jp/memorandum/2016/09/addText2img.html

上記jQueryプラグインを使い、
テキストエリアに入力した文字を、img画像と合成し、
1つの画像として出力させています。

実現したいこととしては、
テキストエリアに入力した文字を、
一定の幅で折り返すようにさせたいです。

現状ですと、
テキストエリア入力時に、改行を入れないと文字が改行されず、
延々と続く形になり、画像外にはみ出しています。

問題が発生するまでの流れ・手順

http://ninoha.com/?p=60

上記ページを参考に入力した文字をcanvasに配置する際に、
文字を折り返すことが可能なところまでは調べたのですが、
実際にソースコードのどの部分が入力した文字に該当するのかわからず、
行き詰まっている状態です。

該当のソースコード

(function($){

    $.fn.addText2img = function(options) {

        var _opt = $.extend({
            text: 'sample',
            textset:{
                fillStyle: '#000',
                font: "14px 'arial'",
                textAlign: 'left',
                textBaseline: 'top',
                x: 10,
                y: 10,
                lineHeight: 5
            }
        }, options);

        /*
         * 改行してテキスト描画
         */
        var lineFeed_fillText = function(_obj){
            var lines = _obj.text.split('\n');
            var lh    = _obj.context.measureText("あ").width + _obj.lineHeight;
            lines.forEach(function(line, i){
                _obj.context.fillText(line, _obj.x, _obj.y + lh * i);
            });
        };

        var i = 0;

        /*
         * Main
         */
        return this.each(function(){

            $this = $(this);

            // 作業用キャンバスを作成
            i++;
            $('body').append('<canvas style="display:none;"></canvas>');
            var $canvas = $('canvas')[i - 1];

            /*
             * 画像設定
             */
            var img = new Image();
            img.src = $this.attr('src');

            /*
             * 画像に文字を合成して画像として出力する
             */
            var drawImg = function(){

                // 画像のロード判定
                if (!img.complete){
                    setTimeout(drawImg, 500);
                    return;
                }

                // 画像をキャンバスに書き出し
                $canvas.width  = img.width;
                $canvas.height = img.height;
                var cvs2d = $canvas.getContext("2d");
                cvs2d.drawImage(img, 0, 0);

                // キャンバスのテキスト設定
                cvs2d.fillStyle    = _opt.textset.fillStyle;
                cvs2d.font         = _opt.textset.font;
                cvs2d.textAlign    = _opt.textset.textAlign;
                cvs2d.textBaseline = _opt.textset.textBaseline;

                // キャンバスに改行されたテキストを描画
                lineFeed_fillText({
                    context: cvs2d,
                    text: _opt.text,
                    x: _opt.textset.x,
                    y: _opt.textset.y,
                    lineHeight: _opt.textset.lineHeight
                });

                // キャンバスを画像として書き出し
                $this.attr("src", $canvas.toDataURL());

            }

            drawImg();

        });
    };
})( jQuery );
<script>
$(function(){

    var n = 0;
    var loc = [{top:380,left:750},{top:380,left:750},{top:380,left:750},{top:380,left:750},{top:380,left:750},{top:380,left:750}];
    var size = "16px";

    /* サムネのクリック */
    $(".select_chara li").click(function(){
        $(".select_chara li").removeClass("active");
        $(this).addClass("active");
    });

    $(".select_chara li").click(function(){
        var path = $(this).children("img").attr('src');
        path = path.replace( /-thumb/g , "");

        $('.addText').attr('src', path);
        n = $(this).children("img").data("thumb");
        $('#text1').show();
        $('#make').show();

        var path2 = $(this).children("img").attr('src');
        path2 = path2.replace( /thumb/g , "result");

        $('.resultImg').attr('src', path2);
        n = $(this).children("img").data("thumb");

        $('#result').hide();
    });

    /* ジェネレート */
    $("#make").click(function(){
        var textset = {
            fillStyle: '#000',
            font: size + " '",
            textAlign: 'left',
            textBaseline: 'top',
            x: loc[n].left,
            y: loc[n].top,
            lineHeight: 5
        };

        var text1 = $('#text1').val();
        $('.resultImg').addText2img({
            text: text1,
            textset: textset
        });

        $('#fukidashi').hide();
        $('#make').hide();
        $('#result').show();
    });

});

</script>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2019/02/05 14:20

    「何」が「どのように」わからないのか、コードのどの部分で詰まっているのかなどを、出ているエラーなどと併せて、具体的に記述されたほうが回答を得られやすいと思います。

    キャンセル

回答 1

checkベストアンサー

+1

>実際にソースコードのどの部分が入力した文字に該当するのか
lineFeed_fillText内の、_obj.textが入力された文字列のようですね。

var lineFeed_fillText = function(_obj){
    // 文字列を改行文字で分割
    var lines = _obj.text.split('\n');

    // 各行の縦位置を調整するための処理、なぜ幅(width)が使われているのかは不明
    var lh    = _obj.context.measureText("あ").width + _obj.lineHeight;

    lines.forEach(function(line, i){
        // 分割された文字列を印字
        _obj.context.fillText(line, _obj.x, _obj.y + lh * i); 
    });

文字列の折り返し方は、参考に挙げているサイトのmultilineTextを呼び出せばよいと思います。といっても、「文字列の配列の各要素を配列に」とか頭がこんがらがってしまうかもしれないので書いてしまうと、

/*
lines.forEach(function(line, i){
    // 分割された文字列を印字
    _obj.context.fillText(line, _obj.x, _obj.y + lh * i); 
});
*/
// ↑削除 ↓追加
var lineNumber = 0;
lines.forEach(function(line, i){
    // 改行で分割された文字列をさらに等幅に分割
    var monospacedLines = multilineText(_obj.context, line, width/*任意の幅*/);
    monospacedLines.forEach(function(monospacedLine, i){
        // 等幅文字列を印字
        _obj.context.fillText(monospacedLine, _obj.x, _obj.y + lh * lineNumber++); 
    });
});


こんな感じではないかと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/06 16:32

    ありがとうございます。記述の意味は理解できました。
    ただ実際に指定した横幅で、入力した文字列を折り返すようにまでは未だ至ってない状態です…。

    もしくは10文字程度で強制的に改行を入れるようにできないか、ひとまずやってみます。

    キャンセル

  • 2019/02/06 17:47

    ありがとうございます!追記いただいたソースで、理想の形に実装できました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る