gentrobot
gentrobot

Reputation: 671

KonvaJS: How to change the text class properties (fontSize, height & width) on resize in?

I am trying to make the text layer resizable in KonvaJS. My code looks like:

var Canvas = (function() {
    var funct = {};
    var stageWidth,stageHeight,stage,layer,circle,rect,myPlayer,textNode,tr;

    funct.stageInit = function(){
      stage = new Konva.Stage({
        container: 'canvas',
        width: stageWidth,
        height: stageHeight
      });

      layer = new Konva.Layer();
      stage.add(layer);

      funct.addText();
      funct.makeTextResizeable();
      layer.draw();
    }

    funct.addText = function(){
      textNode = new Konva.Text({
        text: 'Some text here',
        x: 50,
        y: 50,
        width: 50,
        height: 50,
        fontSize: 20,
        draggable: true,
      });

      layer.add(textNode);

      textNode.on('dblclick', () => {
        // create textarea over canvas with absolute position

        // first we need to find its positon
        var textPosition = textNode.getAbsolutePosition();
        var stageBox = stage.getContainer().getBoundingClientRect();

        var areaPosition = {
          x: textPosition.x + stageBox.left,
          y: textPosition.y + stageBox.top
        };


        // create textarea and style it
        var textarea = document.createElement('textarea');
        document.body.appendChild(textarea);

        textarea.value = textNode.text();
        textarea.style.position = 'absolute';
        textarea.style.top = areaPosition.y + 'px';
        textarea.style.left = areaPosition.x + 'px';
        textarea.style.width = textNode.width();
        textarea.style.zIndex = 15;

        textarea.focus();


        textarea.addEventListener('keydown', function (e) {
          if (e.keyCode === 13) {
            textNode.text(textarea.value);
            layer.draw();
            document.body.removeChild(textarea);
          }
        });
      });
    }

    funct.makeTextResizeable = function(){
      tr = new Konva.Transformer({
        boundBoxFunc: function (oldBoundBox, newBoundBox) {
          if (newBoundBox.width > 200) {
            return oldBoundBox;
          }
          textNode.attrs.fontSize = (newBoundBox.width/oldBoundBox.width)*textNode.attrs.fontSize;
          textNode.attrs.width = (newBoundBox.width/oldBoundBox.width)*textNode.attrs.width;
          textNode.attrs.height = (newBoundBox.width/oldBoundBox.width)*textNode.attrs.height;
          console.log(textNode.attrs.fontSize);
          return newBoundBox
        },
        isTransforming: function(){
          console.log('a');
        }
      });
      layer.add(tr);
      tr.attachTo(textNode);
    }

    funct.fitStageIntoParentContainer = function(){
      var container = document.querySelector('#canvas-container');
      var containerWidth = container.offsetWidth;
      var scale = containerWidth / stageWidth;

      stage.width(stageWidth * scale);
      stage.height(stageHeight * scale);
      stage.scale({ x: scale, y: scale });
      stage.draw();
    }

    funct.Onresize = function(){
      window.addEventListener('resize', function(){
        funct.fitStageIntoParentContainer();
      });
    }

    funct.init = function(){
      stageHeight = $('.vjs-poster').height();
      stageWidth =  $('.vjs-poster').width();
      funct.stageInit();
      funct.Onresize();
    }
    return funct;
  })();  

I would like to allow resizing the text layer by dragging and change the size of the font accordingly. I would also like the text to wrap/unwrap, based on the size of the text layer.

https://jsfiddle.net/gentrobot/5gk1h67u/

The requirement is to be able to add text dynamically, in runtime, resize & reposition it and then get the final size of text, text container and coordinates of the text container, to save it. From this information, will then generate the HTML with the dynamically added text, positioned on the main element.

I am able to resize the text, but it is not resizing smoothly and does not wrap while resize. Though, once done, I am able to extract the final coordinates and the size as well.

Upvotes: 1

Views: 3034

Answers (1)

lavrton
lavrton

Reputation: 20288

Probably you don't need to change scale while transforming the text. You can reset it on every transform event:

tr.on('transform', function() {
     textNode.setAttrs({
         width: textNode.width() * textNode.scaleX(),
         height: textNode.height() * textNode.scaleY(),
         scaleX: 1,
         scaleY: 1,
     });
})

Also for better UX you can limit some sizes:

  tr = new Konva.Transformer({
    boundBoxFunc: function (oldBoundBox, newBoundBox) {
      if (newBoundBox.width > 200 || newBoundBox.width < textNode.fontSize()) {
        return oldBoundBox;
      } else if (newBoundBox.height < textNode.fontSize()) {
        return oldBoundBox;
      }
      return newBoundBox
    }
});

Demo: https://jsfiddle.net/dgL1kvcb/1/

If you need to change fontSize too while transforming you need to define its logic. How will it work if you want both wrap and font size change?

Upvotes: 2

Related Questions