monicao
6/6/2012 - 7:18 PM

Zach's super awesome rectangle drawing algo

Zach's super awesome rectangle drawing algo

$(document).ready(function(){
  window.drawing = false;
  $("#wrapper").mousedown(function(e){
    x = e.pageX; // not supported in IE7, IE8  (clientX, clientY)
    y = e.pageY;
    window.originalX = x;
    window.originalY = y;
    window.drawing = true;
    window.active_rect = $("<div class='rect'></div>");
    window.active_rect.css({
      position: "absolute", 
      left: x, 
      top: y, 
      border: "1px solid red",
      width: 1,
      height: 1
    });
    $("#wrapper").append(window.active_rect);
    return false; // prevent drag
  });
  
  $("#wrapper").mousemove(function(e){
    if(window.drawing && typeof(window.active_rect) != "undefined" && window.active_rect) {
      var css = window.rectangleCSS({x: window.originalX, y: window.originalY}, {x: e.pageX, y: e.pageY});
      window.active_rect.css(css);
    }
  });
  
  $("#wrapper").mouseup(function(e){
    window.drawing = false;
    delete window.active_rect;
  });
  
  
  // K   L
  // M   N
  // point A and point B are two opposing points (Ax != Bx and Ay != By)
  // Returns: the css coordinates for an absolutely positioned div representing 
  //          the rectangle described by pointA and pointB
  window.rectangleCSS = function(pointA, pointB) {
    //console.log("rectangleCSS " + pointA.x + ", " + pointA.y + " " + pointB.x + ", " + pointB.y);
    var K, L, M, N;
    // Figure out if we're dealing with a K, N pair or a L, M pair
    if(pointA.x > pointB.x) {  // A is either L or N
      if(pointA.y > pointB.y) {
        //console.log("NK");
        N = pointA; K = pointB; 
      } else {
        //console.log("LM");
        L = pointA; M = pointB;
      }
    } else { // A is either K or M
      if(pointA.y > pointB.y) {
        //console.log("ML");
        M = pointA; L = pointB; 
      } else {
        //console.log("KN");
        K = pointA, N = pointB;
      }
    }
    
    // Calculate the rectangle CSS values
    if(K && N) {
      console.log("KN");
      return {left: K.x, top: K.y, width: (N.x - K.x), height: (N.y - K.y)};
    } else { // we know L, M
      console.log("LM");
      return {left: M.x, top: L.y, width: (L.x - M.x), height: (M.y - L.y)};
    }
    
  }
  
  // TESTS
  
  window.runTests = function() {
    console.log("Starting tests.");
    var result;

    console.log("Testing {x: 1, y: 1}, {x: 20, y: 20}");
    result = window.rectangleCSS({x: 1, y: 1}, {x: 20, y: 20});
    equals(result.x,      1);
    equals(result.y,      1);
    equals(result.width,  19);
    equals(result.height, 19);
    
    console.log("Testing {x: 20, y: 20}, {x: 1, y: 1}");
    result = window.rectangleCSS({x: 20, y: 20}, {x: 1, y: 1});
    equals(result.x,      1);
    equals(result.y,      1);
    equals(result.width,  19);
    equals(result.height, 19);
    
    console.log("Testing {x: 1, y: 20}, {x: 20, y: 1}");
    result = window.rectangleCSS({x: 1, y: 20}, {x: 20, y: 1});
    equals(result.x,      1);
    equals(result.y,      1);
    equals(result.width,  19);
    equals(result.height, 19);
    
    console.log("Testing {x: 20, y: 1}, {x: 1, y: 20}");
    result = window.rectangleCSS({x: 20, y: 1}, {x: 1, y: 20});
    equals(result.x,      1);
    equals(result.y,      1);
    equals(result.width,  19);
    equals(result.height, 19);
    
  }
  
  window.equals = function(a, b) {
    if(a === b) {
      console.log("Passed");
    } else {
      console.log("Failed. Expected a: " + a + " to be equal to b: " + b);
    }
  }
});






<html>
  <head>
    <title>Drawing</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script type="text/javascript" src="drawing.js"></script>
    
    <style type="text/css">
      #wrapper {
        width: 100%;
        height: 100%;
        border: 1px solid black;
      }
    </style>
  </head>
  
  <body>
    <div id="wrapper">
      
    </div>
  </body>

</html>