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>