title: Zooming via HTML5 Canvas Context and drawing a grid over a given image
body: <p>Using the HTML5  element, I would like to load an image file (PNG, JPEG, etc.), draw it to the canvas, and then draw a grid on top of the image;</p>
  
  <p>also, I am trying to set a rectangle margin and a fully transparent content for the rectangle;</p>
  
  <p>the example that I am trying to modify can be found <a href="http://phrogz.net/tmp/canvas_zoom_to_cursor.html" rel="nofollow">here</a></p>
  
  <p>and on my fiddle <a href="http://jsfiddle.net/VMvqt/8/" rel="nofollow">here</a></p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;!-- saved from url=(0048)http://phrogz.net/tmp/canvas_zoom_to_cursor.html --&gt;
  &lt;html lang="en"&gt;&lt;head&gt;&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
  
      &lt;title&gt;Zooming via HTML5 Canvas Context&lt;/title&gt;
      &lt;style type="text/css" media="screen"&gt;
          body { background:#eee; margin:1em; text-align:center; }
          canvas { display:block; margin:1em auto; background:#fff; border:1px solid #ccc }
      &lt;/style&gt;
  &lt;/head&gt;&lt;body style="-webkit-user-select: none;"&gt;
  &lt;p&gt;Showing how to use transform methods on the HTML5 Canvas Context to selectively zoom in and out. Drag to pan. Click to zoom at that location. Shift-click to zoom out. Mousewheel up/down over the canvas to zoom in to/out from that location.&lt;/p&gt;
  &lt;p&gt;By redrawing the canvas at different scales the strokes remain smooth during zooming. For example, zoom in on the earring or circle on the forehead to see fine detail.&lt;/p&gt;
  &lt;canvas width="800" height="600"&gt;&lt;/canvas&gt;
  &lt;p id="footer"&gt;Copyright © 2011 &lt;a href="mailto:!@phrogz.net"&gt;Gavin Kistner&lt;/a&gt;. Written to support &lt;a href="http://stackoverflow.com/questions/5189968/zoom-to-cursor-calculations/5526721#5526721"&gt;this Stack Overflow answer&lt;/a&gt;.&lt;/p&gt;
  &lt;script type="text/javascript" charset="utf-8"&gt;
      var canvas = document.getElementsByTagName('canvas')[0];
      canvas.width = 800; canvas.height = 600;
      var gkhead = new Image;
      var ball   = new Image;
      window.onload = function(){     
          var ctx = canvas.getContext('2d');
          trackTransforms(ctx);
          function redraw(){
              // Clear the entire canvas
              var p1 = ctx.transformedPoint(0,0);
              var p2 = ctx.transformedPoint(canvas.width,canvas.height);
              ctx.clearRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
  
              // Alternatively:
              // ctx.save();
              // ctx.setTransform(1,0,0,1,0,0);
              // ctx.clearRect(0,0,canvas.width,canvas.height);
              // ctx.restore();
  
              ctx.drawImage(gkhead,50,50);//punct stanga sus imagine cu marton
              console.log(ctx);
  
              ctx.fillStyle="#FF0000";
              ctx.fillRect(50,50,60,60);
  
              ctx.beginPath();
              ctx.lineWidth = 10;//rama 10
              ctx.moveTo(399,250);
              ctx.lineTo(474,256);
              ctx.stroke();
  
              ctx.save();
              ctx.translate(4,2);
              ctx.beginPath();
              ctx.lineWidth = 1;//rama 1
              ctx.moveTo(436,253);
              ctx.lineTo(437.5,233);
              ctx.stroke();
  
              ctx.save();
              ctx.translate(438.5,223);
              ctx.strokeStyle = '#06c';
              ctx.beginPath();
              ctx.lineWidth = 0.05;
              for (var i=0;i&lt;60;++i){
                  ctx.rotate(6*i*Math.PI/180);
                  ctx.moveTo(9,0);
                  ctx.lineTo(10,0);
                  ctx.rotate(-6*i*Math.PI/180);
              }
              ctx.stroke();
              ctx.restore();
  
              //ctx.beginPath();
              //ctx.lineWidth = 0.2;
              //ctx.arc(438.5,223,10,0,Math.PI*2);
              //ctx.stroke();
              //ctx.restore();
  
              //ctx.drawImage(ball,379,233,40,40);//bila stanga
              //ctx.drawImage(ball,454,239,40,40);//bila dreapta
              //ctx.drawImage(ball,310,295,20,20);//bila jos
              //ctx.drawImage(ball,314.5,296.5,5,5);//ochi stang
              //ctx.drawImage(ball,319,297.2,5,5);//ochi drept
          }
          redraw();
  
          var lastX=canvas.width/2, lastY=canvas.height/2;
          var dragStart,dragged;
          canvas.addEventListener('mousedown',function(evt){
              document.body.style.mozUserSelect = document.body.style.webkitUserSelect = document.body.style.userSelect = 'none';
              lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft);
              lastY = evt.offsetY || (evt.pageY - canvas.offsetTop);
              console.log(lastX + ' ' + lastY);
              dragStart = ctx.transformedPoint(lastX,lastY);
              dragged = false;
          },false);
          canvas.addEventListener('mousemove',function(evt){
              lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft);
              lastY = evt.offsetY || (evt.pageY - canvas.offsetTop);
              dragged = true;
              if (dragStart){
                  var pt = ctx.transformedPoint(lastX,lastY);
                  ctx.translate(pt.x-dragStart.x,pt.y-dragStart.y);
                  redraw();
              }
          },false);
          canvas.addEventListener('mouseup',function(evt){
              dragStart = null;
              if (!dragged) zoom(evt.shiftKey ? -1 : 1 );
          },false);
  
          var scaleFactor = 1.1;
          var zoom = function(clicks){
              var pt = ctx.transformedPoint(lastX,lastY);
              ctx.translate(pt.x,pt.y);
              var factor = Math.pow(scaleFactor,clicks);
              ctx.scale(factor,factor);
              ctx.translate(-pt.x,-pt.y);
              redraw();
          }
  
          var handleScroll = function(evt){
              var delta = evt.wheelDelta ? evt.wheelDelta/40 : evt.detail ? -evt.detail : 0;
              if (delta) zoom(delta);
              return evt.preventDefault() &amp;&amp; false;
          };
          canvas.addEventListener('DOMMouseScroll',handleScroll,false);
          canvas.addEventListener('mousewheel',handleScroll,false);
      };
      gkhead.src = 'marton.jpg';
      //console.log(gkhead);//img src
      ball.src   = 'http://phrogz.net/tmp/alphaball.png';
      //console.log(ball);
  
      // Adds ctx.getTransform() - returns an SVGMatrix
      // Adds ctx.transformedPoint(x,y) - returns an SVGPoint
      function trackTransforms(ctx){
          var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg');
          var xform = svg.createSVGMatrix();
          ctx.getTransform = function(){ return xform; };
  
          var savedTransforms = [];
          var save = ctx.save;
          ctx.save = function(){
              savedTransforms.push(xform.translate(0,0));
              return save.call(ctx);
          };
          var restore = ctx.restore;
          ctx.restore = function(){
              xform = savedTransforms.pop();
              return restore.call(ctx);
          };
  
          var scale = ctx.scale;
          ctx.scale = function(sx,sy){
              xform = xform.scaleNonUniform(sx,sy);
              return scale.call(ctx,sx,sy);
          };
          var rotate = ctx.rotate;
          ctx.rotate = function(radians){
              xform = xform.rotate(radians*180/Math.PI);
              return rotate.call(ctx,radians);
          };
          var translate = ctx.translate;
          ctx.translate = function(dx,dy){
              xform = xform.translate(dx,dy);
              return translate.call(ctx,dx,dy);
          };
          var transform = ctx.transform;
          ctx.transform = function(a,b,c,d,e,f){
              var m2 = svg.createSVGMatrix();
              m2.a=a; m2.b=b; m2.c=c; m2.d=d; m2.e=e; m2.f=f;
              xform = xform.multiply(m2);
              return transform.call(ctx,a,b,c,d,e,f);
          };
          var setTransform = ctx.setTransform;
          ctx.setTransform = function(a,b,c,d,e,f){
              xform.a = a;
              xform.b = b;
              xform.c = c;
              xform.d = d;
              xform.e = e;
              xform.f = f;
              return setTransform.call(ctx,a,b,c,d,e,f);
          };
          var pt  = svg.createSVGPoint();
          ctx.transformedPoint = function(x,y){
              pt.x=x; pt.y=y;
              return pt.matrixTransform(xform.inverse());
          }
      }
  &lt;/script&gt;
  
  &lt;/body&gt;
  
  &lt;/html&gt;
  </code></pre>