title: TypeScript/JavaScript image rotation and resize
body: <p>I have a requirement where I have to rotate and resize an image using TypeScript (or JavaScript also, since I am using Angular2). This image rotation and resizing feature is similar to MS Outlook (when you compose mail and add images in the body of mail). </p>
  
  <p>I am able to resize and rotate separately but I need it like one combined feature with the below look and feel.</p>
  
  <p><a href="https://i.stack.imgur.com/P6Yc6.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/P6Yc6.png" alt="enter image description here"></a>   <a href="https://i.stack.imgur.com/VGzeV.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/VGzeV.png" alt="enter image description here"></a></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var minWidth = 60;
  var minHeight = 40;
  
  // Thresholds
  var MARGINS = 4;
  
  // End of what's configurable.
  var clicked = null;
  var onRightEdge, onBottomEdge, onLeftEdge, onTopEdge;
  
  var b, x, y;
  
  var redraw = false;
  
  var pane = document.getElementById('pane');
  
  var e;
  
  // Mouse events
  pane.addEventListener('mousedown', onMouseDown);
  document.addEventListener('mousemove', onMove);
  document.addEventListener('mouseup', onUp);
  
  // Touch events 
  pane.addEventListener('touchstart', onTouchDown);
  document.addEventListener('touchmove', onTouchMove);
  document.addEventListener('touchend', onTouchEnd);
  
  
  function onTouchDown(e) {
    onDown(e.touches[0]);
    e.preventDefault();
  }
  
  function onTouchMove(e) {
    onMove(e.touches[0]);     
  }
  
  function onTouchEnd(e) {
    if (e.touches.length ==0) onUp(e.changedTouches[0]);
  }
  
  function onMouseDown(e) {
    onDown(e);
    e.preventDefault();
  }
  
  function onMove(ee) {
    calc(ee);
    e = ee;
    redraw = true;
  }
  
  function onUp(e) {
    calc(e);
    clicked = null;
  
  }
  
  function onDown(e) {
    calc(e);
  
    var isResizing = onRightEdge || onBottomEdge || onTopEdge || onLeftEdge;
    console.log("isResizing: " + isResizing);
  
    clicked = {
   x: x,
   y: y,
   cx: e.clientX,
   cy: e.clientY,
   w: b.width,
   h: b.height,
   isResizing: isResizing,
   onTopEdge: onTopEdge,
   onLeftEdge: onLeftEdge,
   onRightEdge: onRightEdge,
   onBottomEdge: onBottomEdge
    };
    
    
  }
  
  
  function animate() {
  
    requestAnimationFrame(animate);
  
    if (!redraw) return;
  
    redraw = false;
  
    if (clicked &amp;&amp; clicked.isResizing) {
  
   if (clicked.onRightEdge) pane.style.width = Math.max(x, minWidth) + 'px';
   if (clicked.onBottomEdge) pane.style.height = Math.max(y, minHeight) + 'px';
  
   if (clicked.onLeftEdge) {
     var currentWidth = Math.max(clicked.cx - e.clientX  + clicked.w, minWidth);
     if (currentWidth &gt; minWidth) {
    pane.style.width = currentWidth + 'px';
    pane.style.left = e.clientX + 'px'; 
     }
   }
  
   if (clicked.onTopEdge) {
     var currentHeight = Math.max(clicked.cy - e.clientY  + clicked.h, minHeight);
     if (currentHeight &gt; minHeight) {
    pane.style.height = currentHeight + 'px';
    pane.style.top = e.clientY + 'px';  
     }
   }
  
  
   return;
    }
  
    // This code executes when mouse moves without clicking
  
    // style cursor
    if (onRightEdge &amp;&amp; onBottomEdge || onLeftEdge &amp;&amp; onTopEdge) {
   pane.style.cursor = 'nwse-resize';
    } else if (onRightEdge &amp;&amp; onTopEdge || onBottomEdge &amp;&amp; onLeftEdge) {
   pane.style.cursor = 'nesw-resize';
    } else if (onRightEdge || onLeftEdge) {
   pane.style.cursor = 'ew-resize';
    } else if (onBottomEdge || onTopEdge) {
   pane.style.cursor = 'ns-resize';
    } else {
   pane.style.cursor = 'default';
    }
  }
  
  function calc(e) {
    b = pane.getBoundingClientRect();
    x = e.clientX - b.left;
    y = e.clientY - b.top;
  
    onTopEdge = y &lt; MARGINS;
    onLeftEdge = x &lt; MARGINS;
    onRightEdge = x &gt;= b.width - MARGINS;
    onBottomEdge = y &gt;= b.height - MARGINS;
    
   
  }
  
  animate();
  
  
  var count = 0;
      $(".btn-rotate").on("click",function(){
          if(count == 0){
              $("#pane").css("transform","rotate(90deg)");
              count++;
          } 
          else if (count == 1){
              $("#pane").css("transform","rotate(180deg)");
              count++;
          }  
          else if (count == 2){
              $("#pane").css("transform","rotate(270deg)");
              count++;
          }
          else {
              $("#pane").css("transform","rotate(360deg)");
              count=0;
          }
      });</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>#pane {
    position: absolute;
    top: 150px;
    left:200px;
   }
    
    img{
      width:100px;
      height: 100px;
    }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"&gt;&lt;/script&gt;
  &lt;body&gt;
  &lt;h1&gt;
  You can Resize the Image by Hovering over the edges and drag it
  &lt;/h1&gt;
   &lt;img src="https://www.bleedingcool.com/wp-content/uploads/2014/10/DC-Logo.png" id="pane" height="100px" width="100px"/&gt;
  &lt;button class="btn-rotate"&gt;
  Rotate Me
  &lt;/button&gt;
  &lt;/body&gt;</code></pre>
  </div>
  </div>
  </p>