Как да създадете динамично текстово поле за рисуване в html canvas

Нямам идея как да внедря динамично поле за рисуване на текст.

По принцип ето примерния резултат:

въведете описание на изображението тук

Забележка:

Кутията трябва да е отпред, ако има друг обект в платното.

Актуализация

Ето моят код досега:

MouseDown(){
//if first mousedown
     X1 = tempX; //tempX is for current positon
     Y1 = tempY;
     if (Input.style.display === "none") {
        Input.value = "";
        Input.style.top = tempX + 'px';
        Input.style.left = tempY + 'px';
        Input.size = 1;
        Input.style.display = "block";
        Draw();
        }
}

Draw(){
    var userInput = Input.value;
    rectangledText(X1, Y1, 150, userInput, 12, 'verdana'); //code by markE
}

 function rectangledText(x, y, width, text, fontsize, fontface) { //code by markE
        self.TextWidth = ctx.measureText(Text).width;
        var height = wrapText(x, y, text, fontsize, fontface, width)

        ctx.strokeRect(x, y, width, height);

    }


    function wrapText(x, y, text, fontsize, fontface, maxwidth) {
        var startingY = y;
        var words = text.split(' ');
        var line = '';
        var space = '';
        var lineHeight = fontsize * 1.286;
        ctx.font = fontsize + "px " + fontface;
        ctx.textAlign = 'left';
        ctx.textBaseline = 'top'
        for (var n = 0; n < words.length; n++) {
            var testLine = line + space + words[n];
            space = ' ';
            if (ctx.measureText(testLine).width > maxwidth) {
                ctx.fillText(line, x, y);
                line = words[n] + ' ';
                y += lineHeight;
                space = '';
            } else {
                line = testLine;
            }
        }
        ctx.fillText(line, x, y);
        return (y + lineHeight - startingY);
    }

И примерен резултат с обяснение:въведете описание на изображението тук

Проблемът е как мога да направя първия правоъгълник с мишката и текста да бъдат обвити с помощта на Input.style


person Believer    schedule 18.11.2015    source източник
comment
Искате ли да покажете текст в правоъгълник или искате да въведете текст?   -  person markE    schedule 18.11.2015
comment
@markE потребителят трябва да въведе текст в динамичния правоъгълник и той също може да бъде показан в правоъгълника   -  person Believer    schedule 18.11.2015
comment
Съгласен съм с @markE, това не е брилянтна идея, но имаше този въпрос с решение за почти същия проблем: stackoverflow.com /q/29504481/3702797   -  person Kaiido    schedule 18.11.2015
comment
@Кайидо. да, често се задават вариации на този въпрос. Свързахте се с отговор, който добре рисува обвития текст върху платно въз основа на вход от input-type=text. В този въпрос OP изглежда също иска входният елемент да бъде позициониран върху платното по време на въвеждане на данни. Ако не се уморявах (тук е 1:30 сутринта), щях да редактирам отговора си по-долу, за да позиционирам въвеждането върху платното и след това да начертая обвития текст, след като потребителят приключи с въвеждането. Наздраве и лека нощ!   -  person markE    schedule 18.11.2015
comment
@markE, скрит вход би бил възможен със свързания отговор, но няма да го направя и за OP :-) Гласувано за и лека нощ!   -  person Kaiido    schedule 18.11.2015
comment
какво е ОП? ако нямате нищо против. хаха   -  person Believer    schedule 18.11.2015
comment
вземете го, ще се опитам да го направя и да го разбера. Ще публикувам актуализации относно моето решение, ако заседна. Благодаря :)   -  person Believer    schedule 18.11.2015
comment
@нов потребител1. Хей! OP означава оригинален плакат. Това изобщо не е отрицателно - това е просто бърз начин да се каже питащият. :-)   -  person markE    schedule 18.11.2015
comment
OP изглежда също иска елементът за въвеждане да бъде позициониран върху платното по време на въвеждане на данни и едновременно да позиционира входа върху платното и след това да начертае обвития текст, след като потребителят приключи с въвеждането. са точната спецификация, която търся.   -  person Believer    schedule 19.11.2015
comment
@markE Чудя се дали е добре, ако можете да ми помогнете с моя проблем. Забравих да кажа, че областта на правоъгълника също може да се премества, което означава, че input-type = text не е възможно предполагам. Мисля просто да преначертая правоъгълника и текста, когато преместите (X1,Y1) или една точка. Btw влаченето на една точка вече работи.   -  person Believer    schedule 19.11.2015
comment
Дойдох до този сайт goldfirestudios.com/blog/108/ , възможно ли е да се направи динамичната кутия с него?   -  person Believer    schedule 19.11.2015


Отговори (1)


Html5 canvas няма възможност за собствено въвеждане на текст.

IMO, не се опитвайте да накарате платното да прави това, за което не е предназначено.

Вместо това използвайте CSS, за да позиционирате input-type=text върху желаната част от платното. Потребителят може да въведе своя текст в този вход.

Когато потребителят е въвел желания текст, можете да нарисувате текста му в правоъгълник върху платното по следния начин:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var text='Lorem ipsum dolor sit amet, vel te vocent bonorum singulis. Quem magna commune nam in. Ut eos oportere persecuti efficiantur.';

rectangledText(50,50,150,text,12,'verdana');

function rectangledText(x,y,width,text,fontsize,fontface){

  var height=wrapText(x,y,text,fontsize,fontface,width)

  ctx.strokeRect(x,y,width,height);

}


function wrapText(x,y,text,fontsize,fontface,maxwidth){
  var startingY=y;
  var words = text.split(' ');
  var line = '';
  var space='';
  var lineHeight = fontsize*1.286;
  ctx.font = fontsize + "px " + fontface;
  ctx.textAlign='left';
  ctx.textBaseline='top'
  for (var n=0; n<words.length; n++) {
    var testLine = line + space + words[n];
    space=' ';
    if (ctx.measureText(testLine).width > maxwidth) {
      ctx.fillText(line,x,y);
      line = words[n] + ' ';
      y += lineHeight;
      space='';
    } else {
      line = testLine;
    }
  }
  ctx.fillText(line, x,y);
  return(y+lineHeight-startingY);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=300 height=300></canvas>

person markE    schedule 18.11.2015
comment
какво имаш предвид под CSS за позициониране на input-type=text? - person Believer; 18.11.2015
comment
Проучете CSS позиционирането -- по-специално относително и абсолютно позициониране: developer.mozilla. org/en-US/docs/Web/CSS/position. Опаковайте вашето платно в div елемент, като div има position:relative. Задайте платното на position:absolute. Създайте текст за въвеждане на тип, който първоначално е скрит и има position:absolute, и го поставете в обвиващия div под платното. Когато е необходимо, използвайте CSS, за да позиционирате входа на желаното платно x,y и да го направите видим. - person markE; 18.11.2015
comment
Ето донякъде актуална демонстрация на позициониране на input-type=text върху платното: jsfiddle.net/m1erickson/ 9f2ct - person markE; 18.11.2015
comment
Благодаря, ще се опитам да поправя грешката, когато потребителят напише твърде дълга дума, защото тя просто продължава в един ред - person Believer; 18.11.2015
comment
Коя грешка намирате? За вашето цялостно решение ще трябва да комбинирате кода за въвеждане в моята връзка за коментар с кода на дисплея с опакован текст в моя отговор. Ако искате да дадете на потребителя по-голяма област за въвеждане, тогава можете да замените елемент за въвеждане с текстово поле. - person markE; 18.11.2015
comment
например въведеното от потребителя е 11111111111111111111111111111111111111, текстът просто ще продължи в един ред. Продължението трябва да бъде на следващия ред, ако текстът надвишава максималния знак в един ред - person Believer; 18.11.2015
comment
Да, коментираният jsFiddle ви показва само как да позиционирате вход върху платното. След това трябва да комбинирате това с кода в моя отговор, който рисува опакован текст върху платното. Няма грешка...просто трябва да съберете 2-те части код заедно. ;-) - person markE; 18.11.2015
comment
Ще се опитам да комбинирам вашия отговор със stackoverflow.com/q/29504481/3702797 - person Believer; 18.11.2015