Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there already a canvas drawing directive for AngularJS out there?

Is there already a directive to draw/paint things on a canvas? So you can implement something like Paint or even something bigger like Photoshop etc., but a very basic example would suffice.

I haven't found one in my search and if there's already one that is considered best practice I would like to use it. Else I have to implement one myself.

like image 826
JustGoscha Avatar asked May 16 '13 12:05

JustGoscha


3 Answers

Ok I did one and it is actually pretty easy:

app.directive("drawing", function(){
  return {
    restrict: "A",
    link: function(scope, element){
      var ctx = element[0].getContext('2d');

      // variable that decides if something should be drawn on mousemove
      var drawing = false;

      // the last coordinates before the current move
      var lastX;
      var lastY;

      element.bind('mousedown', function(event){
        if(event.offsetX!==undefined){
          lastX = event.offsetX;
          lastY = event.offsetY;
        } else { // Firefox compatibility
          lastX = event.layerX - event.currentTarget.offsetLeft;
          lastY = event.layerY - event.currentTarget.offsetTop;
        }

        // begins new line
        ctx.beginPath();

        drawing = true;
      });
      element.bind('mousemove', function(event){
        if(drawing){
          // get current mouse position
          if(event.offsetX!==undefined){
            currentX = event.offsetX;
            currentY = event.offsetY;
          } else {
            currentX = event.layerX - event.currentTarget.offsetLeft;
            currentY = event.layerY - event.currentTarget.offsetTop;
          }

          draw(lastX, lastY, currentX, currentY);

          // set current coordinates to last one
          lastX = currentX;
          lastY = currentY;
        }

      });
      element.bind('mouseup', function(event){
        // stop drawing
        drawing = false;
      });

      // canvas reset
      function reset(){
       element[0].width = element[0].width; 
      }

      function draw(lX, lY, cX, cY){
        // line from
        ctx.moveTo(lX,lY);
        // to
        ctx.lineTo(cX,cY);
        // color
        ctx.strokeStyle = "#4bf";
        // draw it
        ctx.stroke();
      }
    }
  };
});

And then you can use it on canvas like this:

<canvas drawing></canvas>

Here's a demo on Plunkr: http://plnkr.co/aG4paH

like image 141
JustGoscha Avatar answered Nov 04 '22 05:11

JustGoscha


Angular is ideally suited for writing applications in declarative style. Once you hit the canvas element you cannot go any further with declarative and you have to switch towards an imperative way of writing mechanism. If the majority of your application is providing UI, which you define in html in the rest of your application I would highly encourage you to use AngularJS. Its an amazing framework for that.

On the other hand if the majority of your code is going to be inside the canvas element, then perhaps AngularJS is not the ideal tool for you. If you really insist on using AngularJS for the majority of your application I would suggest you to consider using something like D3 which is an excellent alternative and uses SVG behind the scenes ( which is declarative in nature and hence a great sidekick for AngularJS ).

like image 27
ganaraj Avatar answered Nov 04 '22 03:11

ganaraj


Some time ago i built a configurable directive for that.

https://github.com/pwambach/angular-canvas-painter

The directive creates the canvas element and adds handlers for mousedown/mousemove/mouseup events (and corresponding touch events) to the element. Mousedown and following mousemove events draw bezier curves with the canvasContext.quadraticCurveTo() method for smoother strokes (instead of just painting circles for every point). For details on the drawing algorithm have a look at this article: http://codetheory.in/html5-canvas-drawing-lines-with-smooth-edges/

like image 5
Philipp Avatar answered Nov 04 '22 03:11

Philipp