KineticJS – draw lines using mouse tutorial

kineticjs line drawing using mouse

In this post we will see how to draw lines using mouse with KineticJS canvas library. First we will go through a basic logic for drawing line. Also we will see how this logic can be implemented for KineticJS.


Logic for drawing line on canvas using mouse
  1. Listen for mousedown, mousemove, mouseup events on canvas
  2. on mousedown
    store x1, y1 relative to canvas element
    set started = true
  3. on mousemove
    if started = false then exit
    get current x, y
    element = line(x1, y1, x, y)
  4. on mouseup
    if started = false then exit
    get current x, y
    element = line(x1, y1, x, y)
Explanation is as below
Add following div into body
<div id="canvasArea"> 
</div>
Initialize a stage and layers
  var stage = new Kinetic.Stage({
    container: 'canvasArea',
    width: 500,
    height: 500,
    draggable: false
  }),

  layer = new Kinetic.Layer({
    name: 'layer'
  }),
  
  tmpLayer = new Kinetic.Layer({
    name: 'tmpLayer'
  });
In above code you can see two layers are initialized. Now you must be thinking about what is the need of 2nd layer if single layer is sufficient. One extra layer that is “tmpLayer” is used for real-time drawing of the element on canvas using mouse.
This is because “layer” will hold multiple objects and if we want to show real-time drawing line then we have to remove/modify that line and redraw the “layer” again on every mouse move to show effect. This will be expensive operation as other shapes are there on “layer” already and they will be redrawn as well unnecessarily. So to avoid this we have added “tmpLayer” to show real-time line drawing which will be added in mousedown event and will be removed in mouseup event .
Add layer into stage
stage.add(layer);
Initialize events for canvas
 $('#canvasArea .kineticjs-content').on('mousedown', tool.line_mousedown);
 $('#canvasArea .kineticjs-content').on('mousemove', tool.line_mousemove);
 $('#canvasArea .kineticjs-content').on('mouseup', tool.line_mouseup);
Mousedown callback function
tool.line_mousedown = function(evt) {
  console.log('line_mousedown');
  //store start point relative to canvas
  tool.startPoint = getRelativePointerPosition();
  //set started flag to true
  tool.started = true;
  //add temporary layer to stage
  stage.add(tmpLayer);  
};
Above started flag has been set to true and x,y co-ordinate of mouse is stored as a startPoint upon mousedown event. Also “tempLayer” is now added to stage.
Mousemove callback function
tool.line_mousemove = function(evt) {
  //if drawing of tool (line) is not started then exit
  if(!tool.started) {
    return;
  }

  //get x,y co-ordinate relative to canvas
  var tempPoint = getRelativePointerPosition();
  if(tempPoint !== undefined && tool.startPoint !== undefined) {
    //create kinetic line instance
    var tmpLine = new Kinetic.Line({
      points: [tool.startPoint.x, tool.startPoint.y, tempPoint.x, tempPoint.y],
      stroke: '#C00000',
      strokeWidth: 1
    });
    //remove previous line off temporary layer
    tmpLayer.removeChildren();
    //add current line to temporary canvas
    tmpLayer.add(tmpLine);
    //draw temporary layer to draw previously added line instance
    tmpLayer.draw();      
  }  
};
In above snippet upon mousemove event we are checking if line drawing has been started or not with “tool.started” flag. “tempPoint” will have x,y co-ordinate relative to canvas element. Next inside if-condition we are creating an instance of Kinetic.Line class as “tmpLine”. Before adding it into “tmpLayer” we are first removing all shapes on that layer with method “removeChildren”. After adding “tmpLine” into “tmpLayer” we are calling “draw” method of “tmpLayer” which will draw “tmpLine” and this will happen as we move mouse holding mouse button.
Mouseup callback function
tool.line_mouseup = function(evt) { 
  if (tool.started) {
    //get x,y co-ordinate relative to canvas
    var tempPoint = getRelativePointerPosition();
    if(tempPoint !== undefined && tool.startPoint !== undefined) {
      //create kinetic line instance
      var tmpLine = new Kinetic.Line({
        points: [tool.startPoint.x, tool.startPoint.y, tempPoint.x, tempPoint.y],
        stroke: '#C00000',
        strokeWidth: 1
      });    
      //destroy temporary layer      
      tmpLayer.destroy();
      //add previously created line instance to main layer
      layer.add(tmpLine);
      //draw layer to draw previously added line instance
      layer.draw();     
    }
    //set started flag to false
    tool.started = false;
  }  
};
Mouseup event callback function is same as mousemove function except for adding line to the layer. This is the final step in which we will destroy “tmpLayer” which we added in “mousedown” function and will add Kinetic.Line instance on to “layer” which is main layer for this case.
I am planning to add drawing of different shapes using mouse on canvas in coming posts with different canvas libraries like fabricjs etc.

Comments

Anonymous said…
You've written a very detailed post regarding..... This information is useful to me and is also beneficial to people who...... I appreciate you providing this information.digital signature
Anonymous said…
You've provided here with great substance. I'm happy that I came into this article because it has a wealth of useful information. I appreciate you sharing such an informative article.Offshore Java Developers

Popular posts from this blog

How to get local time from UTC using Moment.JS

Partially rendering Handlerbars from Backbone view

6 steps to create local copy of your live WordPress site