title: Creating a resizable/draggable/rotate view in javascript
body: <p>I've been trying to create something like this in Javascript:</p>
  <p><a href="https://i.stack.imgur.com/by73y.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/by73y.gif" alt="enter image description here" /></a></p>
  <p>As you can see, the container can be dragged, rotated and resized. Most of the things work fine but the resizing of container when it is rotated produce weird output.</p>
  <p>I expect this to happen:</p>
  <p><a href="https://i.stack.imgur.com/Lk6Jd.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/Lk6Jd.gif" alt="enter image description here" /></a></p>
  <p>Instead I get this:</p>
  <p><a href="https://i.stack.imgur.com/w8hAX.gif" rel="noreferrer"><img src="https://i.stack.imgur.com/w8hAX.gif" alt="enter image description here" /></a></p>
  <p>Here's the full code:</p>
  <p><a href="https://jsfiddle.net/c0krownz/" rel="noreferrer">https://jsfiddle.net/c0krownz/</a></p>
  <p>or,</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 box = document.getElementById("box");
  var boxWrapper = document.getElementById("box-wrapper");
  
  var initX, initY, mousePressX, mousePressY, initW, initH, initRotate;
  
  function repositionElement(x, y) {
      boxWrapper.style.left = x;
      boxWrapper.style.top = y;
  }
  
  function resize(w, h) {
      box.style.width = w + 'px';
      box.style.height = h + 'px';
      boxWrapper.style.width = w;
      boxWrapper.style.height = h;
  }
  
  
  function getCurrentRotation(el) {
      var st = window.getComputedStyle(el, null);
      var tm = st.getPropertyValue("-webkit-transform") ||
          st.getPropertyValue("-moz-transform") ||
          st.getPropertyValue("-ms-transform") ||
          st.getPropertyValue("-o-transform") ||
          st.getPropertyValue("transform")
      "none";
      if (tm != "none") {
          var values = tm.split('(')[1].split(')')[0].split(',');
          var angle = Math.round(Math.atan2(values[1], values[0]) * (180 / Math.PI));
          return (angle &lt; 0 ? angle + 360 : angle);
      }
      return 0;
  }
  
  function rotateBox(deg) {
      boxWrapper.style.transform = `rotate(${deg}deg)`;
  }
  
  // drag support
  boxWrapper.addEventListener('mousedown', function (event) {
      if (event.target.className.indexOf("dot") &gt; -1) {
          return;
      }
  
      initX = this.offsetLeft;
      initY = this.offsetTop;
      mousePressX = event.clientX;
      mousePressY = event.clientY;
  
  
      function eventMoveHandler(event) {
          repositionElement(initX + (event.clientX - mousePressX) + 'px',
              initY + (event.clientY - mousePressY) + 'px');
      }
  
      boxWrapper.addEventListener('mousemove', eventMoveHandler, false);
  
      window.addEventListener('mouseup', function () {
          boxWrapper.removeEventListener('mousemove', eventMoveHandler, false);
      }, false);
  
  }, false);
  // done drag support
  
  // handle resize
  var rightMid = document.getElementById("right-mid");
  var leftMid = document.getElementById("left-mid");
  var topMid = document.getElementById("top-mid");
  var bottomMid = document.getElementById("bottom-mid");
  
  var leftTop = document.getElementById("left-top");
  var rightTop = document.getElementById("right-top");
  var rightBottom = document.getElementById("right-bottom");
  var leftBottom = document.getElementById("left-bottom");
  
  function resizeHandler(event, left = false, top = false, xResize = false, yResize = false) {
      initX = boxWrapper.offsetLeft;
      initY = boxWrapper.offsetTop;
      mousePressX = event.clientX;
      mousePressY = event.clientY;
  
      initW = box.offsetWidth;
      initH = box.offsetHeight;
  
      initRotate = getCurrentRotation(boxWrapper);
  
      function eventMoveHandler(event) {
          var wDiff = event.clientX - mousePressX;
          var hDiff = event.clientY - mousePressY;
  
          var newW = initW, newH = initH, newX = initX, newY = initY;
  
          if (xResize) {
              if (left) {
                  newW = initW - wDiff;
                  newX = initX + wDiff;
              } else {
                  newW = initW + wDiff;
              }
          }
  
          if (yResize) {
              if (top) {
                  newH = initH - hDiff;
                  newY = initY + hDiff;
              } else {
                  newH = initH + hDiff;
              }
          }
  
          resize(newW, newH);
          repositionElement(newX, newY);
      }
  
      window.addEventListener('mousemove', eventMoveHandler, false);
  
      window.addEventListener('mouseup', function () {
          window.removeEventListener('mousemove', eventMoveHandler, false);
      }, false);
  }
  
  
  rightMid.addEventListener('mousedown', e =&gt; resizeHandler(e, false, false, true, false));
  leftMid.addEventListener('mousedown', e =&gt; resizeHandler(e, true, false, true, false));
  topMid.addEventListener('mousedown', e =&gt; resizeHandler(e, false, true, false, true));
  bottomMid.addEventListener('mousedown', e =&gt; resizeHandler(e, false, false, false, true));
  leftTop.addEventListener('mousedown', e =&gt; resizeHandler(e, true, true, true, true));
  rightTop.addEventListener('mousedown', e =&gt; resizeHandler(e, false, true, true, true));
  rightBottom.addEventListener('mousedown', e =&gt; resizeHandler(e, false, false, true, true));
  leftBottom.addEventListener('mousedown', e =&gt; resizeHandler(e, true, false, true, true));
  
  // handle rotation
  var rotate = document.getElementById("rotate");
  rotate.addEventListener('mousedown', function (event) {
      // if (event.target.className.indexOf("dot") &gt; -1) {
      //     return;
      // }
  
      initX = this.offsetLeft;
      initY = this.offsetTop;
      mousePressX = event.clientX;
      mousePressY = event.clientY;
  
  
      var arrow = document.querySelector("#box");
      var arrowRects = arrow.getBoundingClientRect();
      var arrowX = arrowRects.left + arrowRects.width / 2;
      var arrowY = arrowRects.top + arrowRects.height / 2;
  
      function eventMoveHandler(event) {
          var angle = Math.atan2(event.clientY - arrowY, event.clientX - arrowX) + Math.PI / 2;
          rotateBox(angle * 180 / Math.PI);
      }
  
      window.addEventListener('mousemove', eventMoveHandler, false);
  
      window.addEventListener('mouseup', function () {
          window.removeEventListener('mousemove', eventMoveHandler, false);
      }, false);
  
  }, false);
  
  
  
  resize(300, 200);
  repositionElement(100, 100);</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>.box {
      background-color: #00BCD4;
      position: relative;
      user-select: none;
  }
  
  .box-wrapper {
      position: absolute;
      transform-origin: center center;
      user-select: none;
  }
  
  .dot {
      height: 10px;
      width: 10px;
      background-color: #1E88E5;
      position: absolute;
      border-radius: 100px;
      border: 1px solid white;
      user-select: none;
  }
  
  .dot:hover {
      background-color: #0D47A1;
  }
  
  .dot.left-top {
      top: -5px;
      left: -5px;
      /* cursor: nw-resize; */
  }
  
  .dot.left-bottom {
      bottom: -5px;
      left: -5px;
      /* cursor: sw-resize; */
  }
  
  .dot.right-top {
      top: -5px;
      right: -5px;
      /* cursor: ne-resize; */
  }
  
  .dot.right-bottom {
      bottom: -5px;
      right: -5px;
      /* cursor: se-resize; */
  }
  
  .dot.top-mid {
      top: -5px;
      left: calc(50% - 5px);
      /* cursor: n-resize; */
  }
  
  .dot.left-mid {
      left: -5px;
      top: calc(50% - 5px);
      /* cursor: w-resize; */
  }
  
  .dot.right-mid {
      right: -5px;
      top: calc(50% - 5px);
      /* cursor: e-resize; */
  }
  
  .dot.bottom-mid {
      bottom: -5px;
      left: calc(50% - 5px);
      /* cursor: s-resize; */
  }
  
  .dot.rotate {
      top: -30px;
      left: calc(50% - 5px);
      cursor: url('https://findicons.com/files/icons/1620/crystal_project/16/rotate_ccw.png'), auto;
  }
  
  .rotate-link {
      position: absolute;
      width: 1px;
      height: 15px;
      background-color: #1E88E5;
      top: -20px;
      left: calc(50% + 0.5px);
      z-index: -1;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div class="box-wrapper" id="box-wrapper"&gt;
      &lt;div class="box" id="box"&gt;
          &lt;div class="dot rotate" id="rotate"&gt;&lt;/div&gt;
          &lt;div class="dot left-top" id="left-top"&gt;&lt;/div&gt;
          &lt;div class="dot left-bottom" id="left-bottom"&gt;&lt;/div&gt;
          &lt;div class="dot top-mid" id="top-mid"&gt;&lt;/div&gt;
          &lt;div class="dot bottom-mid" id="bottom-mid"&gt;&lt;/div&gt;
          &lt;div class="dot left-mid" id="left-mid"&gt;&lt;/div&gt;
          &lt;div class="dot right-mid" id="right-mid"&gt;&lt;/div&gt;
          &lt;div class="dot right-bottom" id="right-bottom"&gt;&lt;/div&gt;
          &lt;div class="dot right-top" id="right-top"&gt;&lt;/div&gt;
          &lt;div class="rotate-link"&gt;&lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>