admin管理员组

文章数量:1394152

I been working on a code which was showing how to resize a div dynamically. However code was stuck on 1 element and I worked on a little to convert into multiple div resizer.

Now there is a space appears between mouse and the div while being resized, my goal is to make sure every single element seperately being resized with exact mouse location depending on parent position. Any approach that would change my perspective is appriciated. Not bound to the resize nodes instead directly holding div borders also possible.

Things I ve achived so far :

-Made multiple divs resizable by mouse location.

-Holded first location info in a function.

-Calgulated difference betweeen child and parent.

Things I would like to achieve:

-To make sure holders stays under mouse location while resizing without any space between mouse and div.

After couple attempts to resize I see there is a space appears caused by parent elements margins, paddings...etc. and div starts resizing with a space between div and the mouse location.

I need a recursive solution in calgulation to correctly resize and relocate divs.

May be another approach could be used to calgulate only x,y,w,h inside parent but I need some explanation about how to achive that with mouse...

function resizeable() {
  var resizers = document.querySelectorAll('.n, .s, .w, .e, .nw, .ne, .se, .sw');
  const min = 40;
  for (let i = 0; i < resizers.length; i++) {
    const currentResizer = resizers[i];
    const element = currentResizer.parentElement;
    const parent = currentResizer.parentElement.parentElement;
    let p;
    let c;
    let original_w = 0;
    let original_h = 0;
    let parent_x = 0;
    let parent_y = 0;
    let child_x = 0;
    let child_y = 0;
    let mouse_x = 0;
    let mouse_y = 0;
    let scale_x = 0;
    let scale_y = 0;
    // Mouse events
    currentResizer.addEventListener('mousedown', function(e) {
      first(e);
      document.addEventListener('mousemove', resize);
      document.addEventListener('mouseup', stopResize);
      e.preventDefault();
    });
    // Log
    function log(e){
      var str = 'original_w['+original_w+'] original_h['+original_h+'] \n'+
                'parent_x['+parent_x+'] parent_y['+parent_y+'] \n'+
                'child_x['+child_x+'] child_y['+child_y+'] \n'+
                'scale_x['+scale_x+'] scale_y['+scale_y+'] \n'+
                'mouse_x['+mouse_x+'] mouse_y['+mouse_y+'] \n'+
                'e.pageX['+e.pageX+'] e.pageY['+e.pageY+'] \n'+
                'obj.left['+element.style.left+'] obj.top['+element.style.top+']';
      console.log(str);
      /**/
      str = '<table>'+
          '<tr>'+
            '<th colspan="2">First Locations:</td>'+
          '</tr>'+
          '<tr>'+
            '<td>original_w['+original_w+']</td>'+
            '<td>original_h['+original_h+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>parent_x['+parent_x+']</td>'+
            '<td>parent_y['+parent_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>child_x['+child_x+']</td>'+
            '<td>child_y['+child_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>scale_x['+scale_x+']</td>'+
            '<td>scale_y['+scale_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>mouse_x['+mouse_x+']</td>'+
            '<td>mouse_y['+mouse_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>e.pageX['+e.pageX+']</td>'+
            '<td>e.pageY['+e.pageY+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>obj.left['+element.style.left+']</td>'+
            '<td>obj.top['+element.style.top+']</td>'+
          '</tr>'
      '</table>';
      var m = document.getElementById("nfo"); // Debug element
      m.innerHTML = str;
    }
    // First location & width
    function first(e) {
      c = element.getBoundingClientRect();
      child_y = c.top;
      child_x = c.left;
      p = parent.getBoundingClientRect();
      parent_y = p.top;
      parent_x = p.left;
      original_w = parseFloat(c.width).toFixed(2);
      original_h = parseFloat(c.height).toFixed(2);
      scale_y = parseFloat(c.height / element.offsetHeight).toFixed(2);
      scale_x = parseFloat(c.width / element.offsetWidth).toFixed(2);
      mouse_y = e.pageY;
      mouse_x = e.pageX;
      log(e);
    }
    // Resize process
    function resize(e) {
      element.style.position = "absolute";
      if (currentResizer.classList.contains('se')) {
        const width = e.pageX - child_x;
        const height = e.pageY - child_y;
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
      }
      else if (currentResizer.classList.contains('sw')) {
        const width = original_w - (e.pageX - child_x);
        const height = e.pageY - child_y;
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
        if (width > min) {
          element.style.left = e.pageX - parent_x + 'px';
          element.style.width = (width / scale_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('ne')) {
        const width = e.pageX - child_x;
        const height = original_h - (e.pageY - mouse_y);
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top =  e.pageY - parent_y + 'px';
        }
      }
      else if (currentResizer.classList.contains('nw')) {
        const width = original_w - (e.pageX - child_x);
        const height = original_h - (e.pageY - mouse_y);
        if (width > min) {
          element.style.left = e.pageX - parent_x + 'px';
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top = e.pageY - parent_y + 'px';
        }
      }
      else if (currentResizer.classList.contains('e')) {
        const width = e.pageX - child_x;
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('s')) {
        const height = e.pageY - child_y;
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
      }
      else if (currentResizer.classList.contains('w')) {
        const width = original_w - (e.pageX - child_x);
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
          element.style.left = (e.pageX - parent_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('n')) {
        const height = original_h - (e.pageY - mouse_y);
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top = e.pageY - parent_y + 'px';
        }
      }
      log(e);
    }
    // When mouse released stop
    function stopResize(e) {
      first(e);
      document.removeEventListener('mousemove', resize);
    }
  }
}
resizeable();
.another_element_on_the_way {
  position: relative;
  width: 100px;
  height: 100px;
  float: left;
}
#nfo {
  position: relative;
  float: left;
}
div {
  position: absolute;
  background-color: grey;
}
.holder {
  float: left;
  clear: left;
  position: relative;
  margin: 20px;
  width: 550px;
  height: 600px;
}
.scaled:hover:before, .regular:hover:before {
  content: '';
  position: absolute;
  top: -3px;
  left: -3px;
  width: calc(100% - 6px);
  height: calc(100% - 6px);
  border: 6px solid #ccc;
}
.regular:nth-child(1){
  top: 5px;
  left: 5px;
  width: 120px;
  height: 120px;
  background-color: red;
}
.regular:nth-child(3){
  top: 270px;
  left: 60px;
  width: 240px;
  height: 180px;
  background-color: blue;
}
.scaled {
  top: 150px;
  left: 25px;
  width: 160px;
  height: 160px;
  transform: scale(0.6) translate(0, 0);
  transform-origin: top left 0px;
  background-color: green;
  overflow: visible;
}
.previewHeader {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: #eee;
  border: 1px solid #dedede;
}
.n, .s, .w, .e, .nw, .ne, .se, .sw {
  position: absolute;
  width: 18px;
  height: 18px;
  border: 1px solid grey;
  border-radius: 20px;
  background-color: #fff;
}
.n:hover, .s:hover, .w:hover, .e:hover,
.nw:hover, .ne:hover, .se:hover, .sw:hover {
  background-color: red;
}
.nw {
  top: -10px;
  left: -10px;
  cursor: nw-resize;
}
.ne {
  top: -10px;
  left: calc(100% - 10px);
  cursor: ne-resize;
}
.sw {
  top: calc(100% - 10px);
  left: -10px;
  cursor: sw-resize;
}
.se {
  top: calc(100% - 10px);
  left: calc(100% - 10px);
  cursor: se-resize;
}
.n {
  top: -10px;
  left: calc(50% - 10px);
  cursor: n-resize;
}
.w {
  top: calc(50% - 10px);
  left: -10px;
  cursor: w-resize;
}
.e {
  top: calc(50% - 10px);
  left:  calc(100% - 10px);
  cursor: e-resize;
}
.s {
  top: calc(100% - 10px);
  left: calc(50% - 10px);
  cursor: s-resize;
}
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="holder">
  <div class="regular">
      <div class="previewHeader">Resizable</div>
      <div class="nw"></div>
      <div class="ne"></div>
      <div class="sw"></div>
      <div class="se"></div>
      <div class="n"></div>
      <div class="s"></div>
      <div class="w"></div>
      <div class="e"></div>
  </div>
  <div class="scaled">
    <div class="previewHeader">Scaled</div>
    <div class="nw"></div>
    <div class="ne"></div>
    <div class="sw"></div>
    <div class="se"></div>
    <div class="n"></div>
    <div class="s"></div>
    <div class="w"></div>
    <div class="e"></div>
  </div>
  <div class="regular">
    <div class="previewHeader">Resizable</div>
    <div class="nw"></div>
    <div class="ne"></div>
    <div class="sw"></div>
    <div class="se"></div>
    <div class="n"></div>
    <div class="s"></div>
    <div class="w"></div>
    <div class="e"></div>
  </div>
</div>
<div id="nfo"> X & Y</div>

I been working on a code which was showing how to resize a div dynamically. However code was stuck on 1 element and I worked on a little to convert into multiple div resizer.

Now there is a space appears between mouse and the div while being resized, my goal is to make sure every single element seperately being resized with exact mouse location depending on parent position. Any approach that would change my perspective is appriciated. Not bound to the resize nodes instead directly holding div borders also possible.

Things I ve achived so far :

-Made multiple divs resizable by mouse location.

-Holded first location info in a function.

-Calgulated difference betweeen child and parent.

Things I would like to achieve:

-To make sure holders stays under mouse location while resizing without any space between mouse and div.

After couple attempts to resize I see there is a space appears caused by parent elements margins, paddings...etc. and div starts resizing with a space between div and the mouse location.

I need a recursive solution in calgulation to correctly resize and relocate divs.

May be another approach could be used to calgulate only x,y,w,h inside parent but I need some explanation about how to achive that with mouse...

function resizeable() {
  var resizers = document.querySelectorAll('.n, .s, .w, .e, .nw, .ne, .se, .sw');
  const min = 40;
  for (let i = 0; i < resizers.length; i++) {
    const currentResizer = resizers[i];
    const element = currentResizer.parentElement;
    const parent = currentResizer.parentElement.parentElement;
    let p;
    let c;
    let original_w = 0;
    let original_h = 0;
    let parent_x = 0;
    let parent_y = 0;
    let child_x = 0;
    let child_y = 0;
    let mouse_x = 0;
    let mouse_y = 0;
    let scale_x = 0;
    let scale_y = 0;
    // Mouse events
    currentResizer.addEventListener('mousedown', function(e) {
      first(e);
      document.addEventListener('mousemove', resize);
      document.addEventListener('mouseup', stopResize);
      e.preventDefault();
    });
    // Log
    function log(e){
      var str = 'original_w['+original_w+'] original_h['+original_h+'] \n'+
                'parent_x['+parent_x+'] parent_y['+parent_y+'] \n'+
                'child_x['+child_x+'] child_y['+child_y+'] \n'+
                'scale_x['+scale_x+'] scale_y['+scale_y+'] \n'+
                'mouse_x['+mouse_x+'] mouse_y['+mouse_y+'] \n'+
                'e.pageX['+e.pageX+'] e.pageY['+e.pageY+'] \n'+
                'obj.left['+element.style.left+'] obj.top['+element.style.top+']';
      console.log(str);
      /**/
      str = '<table>'+
          '<tr>'+
            '<th colspan="2">First Locations:</td>'+
          '</tr>'+
          '<tr>'+
            '<td>original_w['+original_w+']</td>'+
            '<td>original_h['+original_h+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>parent_x['+parent_x+']</td>'+
            '<td>parent_y['+parent_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>child_x['+child_x+']</td>'+
            '<td>child_y['+child_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>scale_x['+scale_x+']</td>'+
            '<td>scale_y['+scale_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>mouse_x['+mouse_x+']</td>'+
            '<td>mouse_y['+mouse_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>e.pageX['+e.pageX+']</td>'+
            '<td>e.pageY['+e.pageY+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>obj.left['+element.style.left+']</td>'+
            '<td>obj.top['+element.style.top+']</td>'+
          '</tr>'
      '</table>';
      var m = document.getElementById("nfo"); // Debug element
      m.innerHTML = str;
    }
    // First location & width
    function first(e) {
      c = element.getBoundingClientRect();
      child_y = c.top;
      child_x = c.left;
      p = parent.getBoundingClientRect();
      parent_y = p.top;
      parent_x = p.left;
      original_w = parseFloat(c.width).toFixed(2);
      original_h = parseFloat(c.height).toFixed(2);
      scale_y = parseFloat(c.height / element.offsetHeight).toFixed(2);
      scale_x = parseFloat(c.width / element.offsetWidth).toFixed(2);
      mouse_y = e.pageY;
      mouse_x = e.pageX;
      log(e);
    }
    // Resize process
    function resize(e) {
      element.style.position = "absolute";
      if (currentResizer.classList.contains('se')) {
        const width = e.pageX - child_x;
        const height = e.pageY - child_y;
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
      }
      else if (currentResizer.classList.contains('sw')) {
        const width = original_w - (e.pageX - child_x);
        const height = e.pageY - child_y;
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
        if (width > min) {
          element.style.left = e.pageX - parent_x + 'px';
          element.style.width = (width / scale_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('ne')) {
        const width = e.pageX - child_x;
        const height = original_h - (e.pageY - mouse_y);
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top =  e.pageY - parent_y + 'px';
        }
      }
      else if (currentResizer.classList.contains('nw')) {
        const width = original_w - (e.pageX - child_x);
        const height = original_h - (e.pageY - mouse_y);
        if (width > min) {
          element.style.left = e.pageX - parent_x + 'px';
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top = e.pageY - parent_y + 'px';
        }
      }
      else if (currentResizer.classList.contains('e')) {
        const width = e.pageX - child_x;
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('s')) {
        const height = e.pageY - child_y;
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
      }
      else if (currentResizer.classList.contains('w')) {
        const width = original_w - (e.pageX - child_x);
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
          element.style.left = (e.pageX - parent_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('n')) {
        const height = original_h - (e.pageY - mouse_y);
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top = e.pageY - parent_y + 'px';
        }
      }
      log(e);
    }
    // When mouse released stop
    function stopResize(e) {
      first(e);
      document.removeEventListener('mousemove', resize);
    }
  }
}
resizeable();
.another_element_on_the_way {
  position: relative;
  width: 100px;
  height: 100px;
  float: left;
}
#nfo {
  position: relative;
  float: left;
}
div {
  position: absolute;
  background-color: grey;
}
.holder {
  float: left;
  clear: left;
  position: relative;
  margin: 20px;
  width: 550px;
  height: 600px;
}
.scaled:hover:before, .regular:hover:before {
  content: '';
  position: absolute;
  top: -3px;
  left: -3px;
  width: calc(100% - 6px);
  height: calc(100% - 6px);
  border: 6px solid #ccc;
}
.regular:nth-child(1){
  top: 5px;
  left: 5px;
  width: 120px;
  height: 120px;
  background-color: red;
}
.regular:nth-child(3){
  top: 270px;
  left: 60px;
  width: 240px;
  height: 180px;
  background-color: blue;
}
.scaled {
  top: 150px;
  left: 25px;
  width: 160px;
  height: 160px;
  transform: scale(0.6) translate(0, 0);
  transform-origin: top left 0px;
  background-color: green;
  overflow: visible;
}
.previewHeader {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: #eee;
  border: 1px solid #dedede;
}
.n, .s, .w, .e, .nw, .ne, .se, .sw {
  position: absolute;
  width: 18px;
  height: 18px;
  border: 1px solid grey;
  border-radius: 20px;
  background-color: #fff;
}
.n:hover, .s:hover, .w:hover, .e:hover,
.nw:hover, .ne:hover, .se:hover, .sw:hover {
  background-color: red;
}
.nw {
  top: -10px;
  left: -10px;
  cursor: nw-resize;
}
.ne {
  top: -10px;
  left: calc(100% - 10px);
  cursor: ne-resize;
}
.sw {
  top: calc(100% - 10px);
  left: -10px;
  cursor: sw-resize;
}
.se {
  top: calc(100% - 10px);
  left: calc(100% - 10px);
  cursor: se-resize;
}
.n {
  top: -10px;
  left: calc(50% - 10px);
  cursor: n-resize;
}
.w {
  top: calc(50% - 10px);
  left: -10px;
  cursor: w-resize;
}
.e {
  top: calc(50% - 10px);
  left:  calc(100% - 10px);
  cursor: e-resize;
}
.s {
  top: calc(100% - 10px);
  left: calc(50% - 10px);
  cursor: s-resize;
}
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="another_element_on_the_way">
</div>
<div class="holder">
  <div class="regular">
      <div class="previewHeader">Resizable</div>
      <div class="nw"></div>
      <div class="ne"></div>
      <div class="sw"></div>
      <div class="se"></div>
      <div class="n"></div>
      <div class="s"></div>
      <div class="w"></div>
      <div class="e"></div>
  </div>
  <div class="scaled">
    <div class="previewHeader">Scaled</div>
    <div class="nw"></div>
    <div class="ne"></div>
    <div class="sw"></div>
    <div class="se"></div>
    <div class="n"></div>
    <div class="s"></div>
    <div class="w"></div>
    <div class="e"></div>
  </div>
  <div class="regular">
    <div class="previewHeader">Resizable</div>
    <div class="nw"></div>
    <div class="ne"></div>
    <div class="sw"></div>
    <div class="se"></div>
    <div class="n"></div>
    <div class="s"></div>
    <div class="w"></div>
    <div class="e"></div>
  </div>
</div>
<div id="nfo"> X & Y</div>

Also a codepen to show it more clear: https://codepen.io/BerkerYuceer/pen/gOYwqdb

Share Improve this question edited Sep 2, 2019 at 6:01 Berker Yüceer asked Aug 23, 2019 at 7:32 Berker YüceerBerker Yüceer 7,34518 gold badges71 silver badges104 bronze badges 17
  • Also for debug help: check the .ne or .nw holders to see how top calc fails. – Berker Yüceer Commented Aug 23, 2019 at 7:37
  • I think you may have to calculate the scaling and the conditional code to when it is scaled let match = getComputedStyle(element).transform.match(/matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s*0\)/); if (match && match[1] != 0 && match[2] != 0) and multiply +match[1] or +match[2] accordingly based on x,y – shrys Commented Aug 23, 2019 at 8:00
  • Could you please send it as an answer and with explanation. Cause I found many questions like this but none was curing this issue so if you can post a quality answer it may be usefull for future reference and would be a helpfull topic for all. – Berker Yüceer Commented Aug 23, 2019 at 8:08
  • sure, I'll try to solve the issue too – shrys Commented Aug 23, 2019 at 8:17
  • 1 That didn't help me understand anything. I understand the current behaviour is odd / wrong, as pulling left, up etc. causes issues with margin/padding. I can see that. But, I also notice that when you pull south, the box below is moved out of the way. Is this desired behaviour? You could just set everything to position absolute and it would make things a whole lot easier, but then boxes won't interact with eachother. – George Commented Sep 3, 2019 at 19:39
 |  Show 12 more ments

2 Answers 2

Reset to default 5 +100

You could use getComputedStyle to get the transform value with regex and apply 1 / scale value to required coordinates. I was able to solve the issue only for the East holder (I'm too dumb for coordinate geometry :P):

let match = getComputedStyle(element)
           .transform.match(/matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s*0\)/);
let scale = 1; //for .regular folks
if (match && +match[1] != 0)
   scale = 1 / +match[1]; //because we need to unapply the transformation

Sample:

function resizeable() {
  var resizers = document.querySelectorAll('.n, .s, .w, .e, .nw, .ne, .se, .sw');
  const min = 40;
  for (let i = 0; i < resizers.length; i++) {
    const currentResizer = resizers[i];
    const element = currentResizer.parentElement;
    const parent = currentResizer.parentElement.parentElement;
    let p;
    let c;
    let original_w = 0;
    let original_h = 0;
    let parent_x = 0;
    let parent_y = 0;
    let child_x = 0;
    let child_y = 0;
    let mouse_x = 0;
    let mouse_y = 0;
    let scale_x = 0;
    let scale_y = 0;
    let scroll_x = 0;
    let scroll_y = 0;
    // Mouse events
    currentResizer.addEventListener('mousedown', function(e) {
      first(e);
      document.addEventListener('mousemove', resize);
      document.addEventListener('mouseup', stopResize);
      e.preventDefault();
    });
    // Log
    function log(e){
      var str = 'original_w['+original_w+'] original_h['+original_h+'] \n'+
                'parent_x['+parent_x+'] parent_y['+parent_y+'] \n'+
                'scroll_x['+scroll_x+'] scroll_y['+scroll_y+'] \n'+
                'child_x['+child_x+'] child_y['+child_y+'] \n'+
                'scale_x['+scale_x+'] scale_y['+scale_y+'] \n'+
                'mouse_x['+mouse_x+'] mouse_y['+mouse_y+'] \n'+
                'e.pageX['+e.pageX+'] e.pageY['+e.pageY+'] \n'+
                'obj.left['+element.style.left+'] obj.top['+element.style.top+']';
      console.log(str);
      /**/
      str = '<table>'+
          '<tr>'+
            '<th colspan="2">First Locations:</td>'+
          '</tr>'+
          '<tr>'+
            '<td>original_w['+original_w+']</td>'+
            '<td>original_h['+original_h+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>parent_x['+parent_x+']</td>'+
            '<td>parent_y['+parent_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>scroll_x['+scroll_x+']</td>'+
            '<td>scroll_y['+scroll_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>child_x['+child_x+']</td>'+
            '<td>child_y['+child_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>scale_x['+scale_x+']</td>'+
            '<td>scale_y['+scale_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>mouse_x['+mouse_x+']</td>'+
            '<td>mouse_y['+mouse_y+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>e.pageX['+e.pageX+']</td>'+
            '<td>e.pageY['+e.pageY+']</td>'+
          '</tr>'+
          '<tr>'+
            '<td>obj.left['+element.style.left+']</td>'+
            '<td>obj.top['+element.style.top+']</td>'+
          '</tr>'
      '</table>';
      var m = document.getElementById("nfo"); // Debug element
      m.innerHTML = str;
    }
    // First location & width
    function first(e) {
      c = element.getBoundingClientRect();
      child_y = c.top;
      child_x = c.left;
      p = parent.getBoundingClientRect();
      parent_y = p.top;
      parent_x = p.left;
      scroll_y = window.scrollY;
      scroll_x = window.scrollX;
      original_w = parseFloat(c.width).toFixed(2);
      original_h = parseFloat(c.height).toFixed(2);
      scale_y = parseFloat(c.height / element.offsetHeight).toFixed(2);
      scale_x = parseFloat(c.width / element.offsetWidth).toFixed(2);
      mouse_y = e.pageY - scroll_y;
      mouse_x = e.pageX - scroll_x;
      log(e);
    }
    // Resize process
    function resize(e) {
      element.style.position = "absolute";
      if (currentResizer.classList.contains('se')) {
        const width = e.pageX - scroll_x - child_x ;
        const height = e.pageY - scroll_y - child_y ;
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
      }
      else if (currentResizer.classList.contains('sw')) {
        const width = original_w - (e.pageX - scroll_x - child_x);
        const height = e.pageY - scroll_y - child_y;
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
        if (width > min) {
          element.style.left = e.pageX - scroll_x - parent_x + 'px';
          element.style.width = (width / scale_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('ne')) {
        const width = e.pageX - child_x - scroll_x;
        const height = original_h - (e.pageY - mouse_y - scroll_y);
        if (width > min) {
          element.style.width = (width / scale_x)  + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top =  e.pageY - parent_y - scroll_y + 'px';
        }
      }
      else if (currentResizer.classList.contains('nw')) {
        const width = original_w - (e.pageX - scroll_x - child_x);
        const height = original_h - (e.pageY - scroll_y - mouse_y);
        if (width > min) {
          element.style.left = e.pageX - parent_x - scroll_x + 'px';
          element.style.width = (width / scale_x) + 'px';
        }
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top = e.pageY - parent_y - scroll_y + 'px';
        }
      }
      else if (currentResizer.classList.contains('e')) {
        const width = e.pageX - scroll_x - child_x;
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('s')) {
        const height = e.pageY - scroll_y - child_y;
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
        }
      }
      else if (currentResizer.classList.contains('w')) {
        const width = original_w - (e.pageX - scroll_x - child_x);
        if (width > min) {
          element.style.width = (width / scale_x) + 'px';
          element.style.left = (e.pageX - scroll_x - parent_x) + 'px';
        }
      }
      else if (currentResizer.classList.contains('n')) {
        const height = original_h - (e.pageY - scroll_y - mouse_y);
        if (height > min) {
          element.style.height = (height / scale_y) + 'px';
          element.style.top = e.pageY - scroll_y - parent_y + 'px';
        }
      }
      log(e);
    }
    // When mouse released stop
    function stopResize(e) {
      first(e);
      document.removeEventListener('mousemove', resize);
    }
  }
}
resizeable();
body {
  width: 1200px;
}
.another_element_on_the_top {
  position: relative;
  float: left;
  margin: 10px;
  width: 100px;
  height: 100px;
}
.another_element_on_the_left {
  position: relative;
  float: left;
  clear: left;
  margin: 10px;
  width: 100px;
  height: 100px;
}
#nfo {
  position: relative;
  float: left;
}
div {
  position: absolute;
  background-color: grey;
}
.holder {
  float: left;
  position: relative;
  margin: -470px 20px 20px 20px;
  width: 550px;
  height: 600px;
}
.scaled:hover:before, .regular:hover:before {
  content: '';
  position: absolute;
  top: -3px;
  left: -3px;
  width: calc(100% - 6px);
  height: calc(100% - 6px);
  border: 6px solid #ccc;
}
.regular:nth-child(1){
  top: 5px;
  left: 5px;
  width: 120px;
  height: 120px;
  background-color: red;
}
.regular:nth-child(3){
  top: 270px;
  left: 60px;
  width: 240px;
  height: 180px;
  background-color: blue;
}
.scaled {
  top: 150px;
  left: 25px;
  width: 160px;
  height: 160px;
  transform: scale(0.6) translate(0, 0);
  transform-origin: top left 0px;
  background-color: green;
  overflow: visible;
}
.previewHeader {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: #eee;
  border: 1px solid #dedede;
}
.n, .s, .w, .e, .nw, .ne, .se, .sw {
  position: absolute;
  width: 18px;
  height: 18px;
  border: 1px solid grey;
  border-radius: 20px;
  background-color: #fff;
}
.n:hover, .s:hover, .w:hover, .e:hover,
.nw:hover, .ne:hover, .se:hover, .sw:hover {
  background-color: red;
}
.nw {
  top: -10px;
  left: -10px;
  cursor: nw-resize;
}
.ne {
  top: -10px;
  left: calc(100% - 10px);
  cursor: ne-resize;
}
.sw {
  top: calc(100% - 10px);
  left: -10px;
  cursor: sw-resize;
}
.se {
  top: calc(100% - 10px);
  left: calc(100% - 10px);
  cursor: se-resize;
}
.n {
  top: -10px;
  left: calc(50% - 10px);
  cursor: n-resize;
}
.w {
  top: calc(50% - 10px);
  left: -10px;
  cursor: w-resize;
}
.e {
  top: calc(50% - 10px);
  left:  calc(100% - 10px);
  cursor: e-resize;
}
.s {
  top: calc(100% - 10px);
  left: calc(50% - 10px);
  cursor: s-resize;
}
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>
<div class="another_element_on_the_top">
</div>

<div class="another_element_on_the_left">
</div>
<div class="another_element_on_the_left">
</div>
<div class="another_element_on_the_left">
</div>
<div class="another_element_on_the_left">
</div>
<div class="another_element_on_the_left">
</div>

<div class="holder">
  <div class="regular">
      <div class="previewHeader">Resizable</div>
      <div class="nw"></div>
      <div class="ne"></div>
      <div class="sw"></div>
      <div class="se"></div>
      <div class="n"></div>
      <div class="s"></div>
      <div class="w"></div>
      <div class="e"></div>
  </div>
  <div class="scaled">
    <div class="previewHeader">Scaled</div>
    <div class="nw"></div>
    <div class="ne"></div>
    <div class="sw"></div>
    <div class="se"></div>
    <div class="n"></div>
    <div class="s"></div>
    <div class="w"></div>
    <div class="e"></div>
  </div>
  <div class="regular">
    <div class="previewHeader">Resizable</div>
    <div class="nw"></div>
    <div class="ne"></div>
    <div class="sw"></div>
    <div class="se"></div>
    <div class="n"></div>
    <div class="s"></div>
    <div class="w"></div>
    <div class="e"></div>
  </div>
</div>
<div id="nfo"> X & Y</div>

or by using this method in another question.

   var element = document.querySelector('...');
   var scaleX = element.getBoundingClientRect().width / element.offsetWidth;

"This works because getBoundingClientRect returns the actual dimension while offsetWidth/Height is the unscaled size."

Edit: window.scrollX/Y added. Now it is usable in scrolled pages.

For future reference in any part of the page it works solid. Even while object is scaled.

Have you gave a thought about using jquery resizable o.O? That will save you a lot of time and trouble :)

Here you can check, it's easy and simple : https://jsfiddle/maehy5tj/1/

This is all you will need to do :)

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Resizable - Default functionality</title>
  <link rel="stylesheet" href="//code.jquery./ui/1.12.1/themes/base/jquery-ui.css">
  <link rel="stylesheet" href="/resources/demos/style.css">
  <style>
  #resizable { width: 150px; height: 150px; padding: 0.5em; }
  #resizable h3 { text-align: center; margin: 0; }
  </style>
  <script src="https://code.jquery./jquery-1.12.4.js"></script>
  <script src="https://code.jquery./ui/1.12.1/jquery-ui.js"></script>
  <script>
  $( function() {
    $( "#resizable" ).resizable();
  } );
  </script>
</head>
<body>

<div id="resizable" class="ui-widget-content">
  <h3 class="ui-widget-header">Resizable</h3>
</div>


</body>
</html>

本文标签: javascriptHow to resize div dynamically depending on parent position in jsStack Overflow