2

I'm making a dragible and resizable div. Dragible works normally. I want the div to be able to change the width and height with the move mouse after clicking on the "resizer" which is located at all corners. I figured out how to do the Right Bottom "resizer" and it works fine, but I can't make Left Bottom. Does anyone have an idea how?

window.addEventListener('mouseup', mouseUpDragElement, false);
document.getElementById("dragdiv").addEventListener('mousedown', mouseDownDragElement, false);
document.getElementById("dragdiv").addEventListener('mousedown', mouseDownResizeElement, false);

var elementdragTop;
var elementdragLeft;

function mouseDownDragElement(e) {
  window.addEventListener("mousemove", myFunctionDragElement, true);
  elementdragTop = e.clientX - document.getElementById("dragdiv").offsetLeft;
  elementdragLeft = e.clientY - document.getElementById("dragdiv").offsetTop;
}

function mouseUpDragElement() {
  window.removeEventListener("mousemove", myFunctionDragElement, true);
}

function myFunctionDragElement(e) {

  var x = e.clientX;
  var y = e.clientY;

  document.getElementById("dragdiv").style.position = "absolute";
  document.getElementById("dragdiv").style.left = (x - elementdragTop) + 'px';
  document.getElementById("dragdiv").style.top = (y - elementdragLeft) + 'px';

}

function mouseDownResizeElement(e) {
  var resizertopleft = document.createElement("DIV");
  resizertopleft.id = "resizer-top-left";
  document.getElementById("dragdiv").appendChild(resizertopleft);

  var resizertopright = document.createElement("DIV");
  resizertopright.id = "resizer-top-right";
  document.getElementById("dragdiv").appendChild(resizertopright);

  var resizerbottomleft = document.createElement("DIV");
  resizerbottomleft.id = "resizer-bottom-left";
  resizerbottomleft.addEventListener('mousedown', mouseDownResizeElementResizerBottomLeft, false);
  document.getElementById("dragdiv").appendChild(resizerbottomleft);

  var resizerbottomright = document.createElement("DIV");
  resizerbottomright.id = "resizer-bottom-right";
  resizerbottomright.addEventListener('mousedown', mouseDownResizeElementResizerBottomRight, false);
  document.getElementById("dragdiv").appendChild(resizerbottomright);


}

function mouseUpResizeElement(e) {
  document.getElementById("resizer-top-left").remove();
}

// BUTTON BOTTOM RIGHT

function mouseDownResizeElementResizerBottomRight() {
  window.addEventListener("mousemove", mouseMoveResizeElementResizerBottomRight, true);
  document.getElementById("dragdiv").addEventListener('mouseup', mouseUpResizeElementResizerBottomRight, true);

}

function mouseMoveResizeElementResizerBottomRight(e) {
  document.getElementById("dragdiv").addEventListener('mouseup', mouseUpResizeElementResizerBottomRight, true);
  window.removeEventListener("mousemove", myFunctionDragElement, true);

  document.getElementById("dragdiv").style.width = e.pageX - document.getElementById("dragdiv").getBoundingClientRect().left + 'px';
  document.getElementById("dragdiv").style.height = e.pageY - document.getElementById("dragdiv").getBoundingClientRect().top + 'px';

}

function mouseUpResizeElementResizerBottomRight() {
  window.removeEventListener("mousemove", mouseMoveResizeElementResizerBottomRight, true);


}

// BUTTON BOTTOM LEFT ???  Here is the code that does not work

function mouseDownResizeElementResizerBottomLeft(e) {
  window.addEventListener("mousemove", mouseMoveResizeElementResizerBottomLeft, true);
  document.getElementById("dragdiv").addEventListener('mouseup', mouseUpResizeElementResizerBottomLeft, true);
  originaldivwidth = document.getElementById("dragdiv").style.width;
  originaldivleft = document.getElementById("dragdiv").getBoundingClientRect().left;
  originaldivright = document.getElementById("dragdiv").getBoundingClientRect().right;
  originalmousex = e.clientX;
}

function mouseMoveResizeElementResizerBottomLeft(e) {
  document.getElementById("dragdiv").addEventListener('mouseup', mouseUpResizeElementResizerBottomLeft, true);
  window.removeEventListener("mousemove", myFunctionDragElement, true);

  var elementoriginalwidth = document.getElementById("dragdiv").style.width;
  var elementoriginalleft = document.getElementById("dragdiv").getBoundingClientRect().left;
  var mouseX = e.clientX;



  document.getElementById("dragdiv").style.width = document.getElementById("dragdiv").style.width + (e.clientX - originalmousex) + 'px';
  document.getElementById("dragdiv").style.left = e.clientX + (e.clientX - originalmousex) + 'px';


}

function mouseUpResizeElementResizerBottomLeft() {
  window.removeEventListener("mousemove", mouseMoveResizeElementResizerBottomLeft, true);


}
#dragdiv {
  width: 100px;
  height: 100px;
  background-color: red;
  position: absolute;
  margin: 0px;
}

#resizer-top-left {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: white;
  border: 3px solid #4286f4;
  position: absolute;
  left: -5px;
  top: -5px;
  cursor: nwse-resize;
}

#resizer-top-right {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: white;
  border: 3px solid #4286f4;
  position: absolute;
  right: -5px;
  top: -5px;
  cursor: nesw-resize;
}

#resizer-bottom-left {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: white;
  border: 3px solid #4286f4;
  position: absolute;
  left: -5px;
  bottom: -5px;
  cursor: nesw-resize;
}

#resizer-bottom-right {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: white;
  border: 3px solid #4286f4;
  position: absolute;
  right: -5px;
  bottom: -5px;
  cursor: nwse-resize;
}
<div id="container">
  <div id="dragdiv"></div>
</div>
Emiel Zuurbier
  • 19,095
  • 3
  • 17
  • 32
maja
  • 177
  • 1
  • 13
  • By every "angle" do you mean by every "corner"? It makes sense that "left bottom" wouldnt work in a concept understanding, since the left could be already at 0px. – GetSet Mar 14 '20 at 18:31
  • Yes by every "corner". Bottom right and top right work fine, but I didn't write the whole code so it wouldn't be too big. Can't figure out how to do top left and bottom left? – maja Mar 14 '20 at 18:39

2 Answers2

2

It's interesting what a little bit of Google searching can do (: This is a working solution from Hưng Nguyễn https://codepen.io/ZeroX-DG

HTML

<div class='resizable'>
  <div class='resizers'>
    <div class='resizer top-left'></div>
    <div class='resizer top-right'></div>
    <div class='resizer bottom-left'></div>
    <div class='resizer bottom-right'></div>
  </div>
</div>

CSS

body,
html {
  background: black;
}
.resizable {
  background: white;
  width: 100px;
  height: 100px;
  position: absolute;
  top: 100px;
  left: 100px;
}

.resizable .resizers{
  width: 100%;
  height: 100%;
  border: 3px solid #4286f4;
  box-sizing: border-box;
}

.resizable .resizers .resizer{
  width: 10px;
  height: 10px;
  border-radius: 50%; /*magic to turn square into circle*/
  background: white;
  border: 3px solid #4286f4;
  position: absolute;
}

.resizable .resizers .resizer.top-left {
  left: -5px;
  top: -5px;
  cursor: nwse-resize; /*resizer cursor*/
}
.resizable .resizers .resizer.top-right {
  right: -5px;
  top: -5px;
  cursor: nesw-resize;
}
.resizable .resizers .resizer.bottom-left {
  left: -5px;
  bottom: -5px;
  cursor: nesw-resize;
}
.resizable .resizers .resizer.bottom-right {
  right: -5px;
  bottom: -5px;
  cursor: nwse-resize;
}

JS

function makeResizableDiv(div) {
  const element = document.querySelector(div);
  const resizers = document.querySelectorAll(div + ' .resizer')
  const minimum_size = 20;
  let original_width = 0;
  let original_height = 0;
  let original_x = 0;
  let original_y = 0;
  let original_mouse_x = 0;
  let original_mouse_y = 0;
  for (let i = 0;i < resizers.length; i++) {
    const currentResizer = resizers[i];
    currentResizer.addEventListener('mousedown', function(e) {
      e.preventDefault()
      original_width = parseFloat(getComputedStyle(element, null).getPropertyValue('width').replace('px', ''));
      original_height = parseFloat(getComputedStyle(element, null).getPropertyValue('height').replace('px', ''));
      original_x = element.getBoundingClientRect().left;
      original_y = element.getBoundingClientRect().top;
      original_mouse_x = e.pageX;
      original_mouse_y = e.pageY;
      window.addEventListener('mousemove', resize)
      window.addEventListener('mouseup', stopResize)
    })

    function resize(e) {
      if (currentResizer.classList.contains('bottom-right')) {
        const width = original_width + (e.pageX - original_mouse_x);
        const height = original_height + (e.pageY - original_mouse_y)
        if (width > minimum_size) {
          element.style.width = width + 'px'
        }
        if (height > minimum_size) {
          element.style.height = height + 'px'
        }
      }
      else if (currentResizer.classList.contains('bottom-left')) {
        const height = original_height + (e.pageY - original_mouse_y)
        const width = original_width - (e.pageX - original_mouse_x)
        if (height > minimum_size) {
          element.style.height = height + 'px'
        }
        if (width > minimum_size) {
          element.style.width = width + 'px'
          element.style.left = original_x + (e.pageX - original_mouse_x) + 'px'
        }
      }
      else if (currentResizer.classList.contains('top-right')) {
        const width = original_width + (e.pageX - original_mouse_x)
        const height = original_height - (e.pageY - original_mouse_y)
        if (width > minimum_size) {
          element.style.width = width + 'px'
        }
        if (height > minimum_size) {
          element.style.height = height + 'px'
          element.style.top = original_y + (e.pageY - original_mouse_y) + 'px'
        }
      }
      else {
        const width = original_width - (e.pageX - original_mouse_x)
        const height = original_height - (e.pageY - original_mouse_y)
        if (width > minimum_size) {
          element.style.width = width + 'px'
          element.style.left = original_x + (e.pageX - original_mouse_x) + 'px'
        }
        if (height > minimum_size) {
          element.style.height = height + 'px'
          element.style.top = original_y + (e.pageY - original_mouse_y) + 'px'
        }
      }
    }

    function stopResize() {
      window.removeEventListener('mousemove', resize)
    }
  }
}

makeResizableDiv('.resizable')

Source: https://codepen.io/ZeroX-DG/pen/vjdoYe

bananaforscale
  • 820
  • 10
  • 13
  • Heh! I found this example and many other examples, I tried to insert these variables and this idea into my code in botton left, but it doesn't work. – maja Mar 14 '20 at 18:58
  • Perhaps check out this article through from start to finish. This process might shed some light on the top and bottom left issue you are having. https://medium.com/the-z/making-a-resizable-div-in-js-is-not-easy-as-you-think-bda19a1bc53d – bananaforscale Mar 14 '20 at 19:03
  • I also looked at this article ... what's the difference between original_x and original_mouse_x? Where is the variable for original_x? – maja Mar 14 '20 at 19:08
  • `let original_x = 0` – bananaforscale Mar 14 '20 at 19:17
  • 1
    I think it will work .., The only problem is that the div is constantly changing location .. as soon as I correct and if I can correct the code I will report ... – maja Mar 14 '20 at 19:24
  • What is with top-left? – maja Mar 15 '20 at 20:50
  • @maja keep in mind, "typically" the intersection of 0,0 as far as calculations going on under the hood, start at top-left in web-browser world. – bananaforscale Mar 16 '20 at 19:00
  • Everything's working fine, I'm currently doing rotation on mousems, but every time I do a rotation and click on the "resizer" div on the change position, if you have any idea why it's happening it would be very helpful to me .. – maja Mar 16 '20 at 19:41
  • @maja can you clarify your question? – bananaforscale Mar 16 '20 at 22:45
  • This is an example. If you use bottom-right button you will make resize div, if you use top-right then you will rotate div. But...,If you rotate just a bit and then click the bottom-right resize button again, the cursor changes position and is not on the bottom-right button. Why is this happening and how do I apply it to my code? https://codepen.io/anon/pen/rrAWJA – maja Mar 17 '20 at 07:14
  • @maja one thing I am noticing about the rotate behavior is that the rotate jumps to a skew of about 30 degrees immediately and does not rotate gratefully. This is without any resize behavior prior. Maybe this could be a clue as to what is going on. – bananaforscale Mar 19 '20 at 17:16
0

This is the Vue3 implementation of @bananaforscale's answer. Although it may not work as smoothly as the original, it still works reasonably well. You can find the tutorial for vanilla-Js here and the codePen demo here. I hope that this will help someone.

const { onMounted, onUnmounted, ref } = Vue;

const App = {
  setup() {
    const resizableEl = ref(null);
    const resizers = ref(null);
    const minimum_size = 20;
    let original_width = 0;
    let original_height = 0;
    let original_x = 0;
    let original_y = 0;
    let original_mouse_x = 0;
    let original_mouse_y = 0;

    function resize(e) {
      if (e.target.classList.contains("bottom-right")) {
        const width = original_width + (e.pageX - original_mouse_x);
        const height = original_height + (e.pageY - original_mouse_y);
        if (width > minimum_size) {
          resizableEl.value.style.width = width + "px";
        }
        if (height > minimum_size) {
          resizableEl.value.style.height = height + "px";
        }
      } else if (e.target.classList.contains("bottom-left")) {
        const height = original_height + (e.pageY - original_mouse_y);
        const width = original_width - (e.pageX - original_mouse_x);
        if (height > minimum_size) {
          resizableEl.value.style.height = height + "px";
        }
        if (width > minimum_size) {
          resizableEl.value.style.width = width + "px";
          resizableEl.value.style.left =
            original_x + (e.pageX - original_mouse_x) + "px";
        }
      } else if (e.target.classList.contains("top-right")) {
        const width = original_width + (e.pageX - original_mouse_x);
        const height = original_height - (e.pageY - original_mouse_y);
        if (width > minimum_size) {
          resizableEl.value.style.width = width + "px";
        }
        if (height > minimum_size) {
          resizableEl.value.style.height = height + "px";
          resizableEl.value.style.top =
            original_y + (e.pageY - original_mouse_y) + "px";
        }
      } else {
        const width = original_width - (e.pageX - original_mouse_x);
        const height = original_height - (e.pageY - original_mouse_y);
        if (width > minimum_size) {
          resizableEl.value.style.width = width + "px";
          resizableEl.value.style.left =
            original_x + (e.pageX - original_mouse_x) + "px";
        }
        if (height > minimum_size) {
          resizableEl.value.style.height = height + "px";
          resizableEl.value.style.top =
            original_y + (e.pageY - original_mouse_y) + "px";
        }
      }
    }

    function stopResize() {
      window.removeEventListener("mousemove", resize);
    }

    onMounted(() => {
      resizers.value = resizableEl.value.querySelectorAll(".resizer");

      for (let i = 0; i < resizers.value.length; i++) {
        const currentResizer = resizers.value[i];
        currentResizer.addEventListener("mousedown", (e) => {
          e.preventDefault();
          original_width = parseFloat(
            getComputedStyle(resizableEl.value, null)
              .getPropertyValue("width")
              .replace("px", "")
          );
          original_height = parseFloat(
            getComputedStyle(resizableEl.value, null)
              .getPropertyValue("height")
              .replace("px", "")
          );
          original_x = resizableEl.value.getBoundingClientRect().left;
          original_y = resizableEl.value.getBoundingClientRect().top;
          original_mouse_x = e.pageX;
          original_mouse_y = e.pageY;
          window.addEventListener("mousemove", resize);
          window.addEventListener("mouseup", stopResize);
        });
      }
    });

    onUnmounted(() => {
      for (let i = 0; i < resizers.value.length; i++) {
        const currentResizer = resizers.value[i];
        currentResizer.removeEventListener("mousemove", resize);
        currentResizer.removeEventListener("mouseup", stopResize);
      }
    });

    return { resizableEl, resize };
  },
};

Vue.createApp(App).mount("#app");
.resizable {
  background: white;
  width: 100px;
  height: 100px;
  position: absolute;
  top: 100px;
  left: 100px;
}

.resizable .resizers {
  width: 100%;
  height: 100%;
  border: 3px solid #4286f4;
  box-sizing: border-box;
}

.resizable .resizers .resizer {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: white;
  border: 3px solid #4286f4;
  position: absolute;
}

.resizable .resizers .resizer.top-left {
  left: -5px;
  top: -5px;
  cursor: nwse-resize; /*resizer cursor*/
}

.resizable .resizers .resizer.top-right {
  right: -5px;
  top: -5px;
  cursor: nesw-resize;
}

.resizable .resizers .resizer.bottom-left {
  left: -5px;
  bottom: -5px;
  cursor: nesw-resize;
}

.resizable .resizers .resizer.bottom-right {
  right: -5px;
  bottom: -5px;
  cursor: nwse-resize;
}
<script src="https://unpkg.com/vue@3.2.47/dist/vue.global.js"></script>

<div id="app">
  <div class="resizable" ref='resizableEl' @mousedown='resize'>
    <div class="resizers">
      <div class="resizer top-left"></div>
      <div class="resizer top-right"></div>
      <div class="resizer bottom-left"></div>
      <div class="resizer bottom-right"></div>
    </div>  
  </div>
</div>
Syed
  • 15,657
  • 13
  • 120
  • 154