I have this code from codepen, It makes a resizable div that resizes from corners:
<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>
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;
}
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')
How i make it resizes from sides?
It should have a circle at the midle of right, left, bottom, right and top side and resize from there.
Here is the link from the original pen:
Medium: Making a resizable div
Probably there will be need to four new ifs and to four new css classes but im not sure.
I adjusted the positioning and class titles to place the handles on the sides, then removed the scripting from each one that allowed both directions to be adjusted.
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('right')) {
const width = original_width + (e.pageX - original_mouse_x);
if (width > minimum_size) {
element.style.width = width + 'px'
}
}
else if (currentResizer.classList.contains('left')) {
const width = original_width - (e.pageX - original_mouse_x)
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')) {
const height = original_height - (e.pageY - original_mouse_y)
if (height > minimum_size) {
element.style.height = height + 'px'
element.style.top = original_y + (e.pageY - original_mouse_y) + 'px'
}
}
else if (currentResizer.classList.contains('bottom')) {
const height = original_height + (e.pageY - original_mouse_y)
if (height > minimum_size) {
element.style.height = height + 'px'
}
}
}
function stopResize() {
window.removeEventListener('mousemove', resize)
}
}
}
makeResizableDiv('.resizable')
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;
}
.resizer.top {
left: 50%;
top: -5px;
cursor: ns-resize;
transform: translate(-7px, 0px);
}
.resizer.right {
right: -5px;
bottom: 50%;
cursor: ew-resize;
transform: translate(0px, 5px);
}
.resizer.bottom {
left: 50%;
bottom: -5px;
cursor: ns-resize;
transform: translate(-7px, 0px);
}
.resizer.left {
left: -5px;
bottom: 50%;
cursor: ew-resize;
transform: translate(0px, 5px);
}
<div class='resizable'>
<div class='resizers'>
<div class='resizer top'></div>
<div class='resizer right'></div>
<div class='resizer bottom'></div>
<div class='resizer left'></div>
</div>
</div>
Related
I have made a div with handles that can be used to resize it. Those work well when the rotation of the div is 0 deg. But when angle of rotation changes and I try to resize the div from one side, the position of other sides changes. I want to keep the position fixed of rest of sides when I try to resize it at from one handle. Here is my code: Help me what type of changes should I do in it.
const resizableDiv = document.querySelector('#resizable-div');
const handles = document.querySelectorAll('.handle');
let isResizing = false;
let currentHandle = null;
let originalWidth = 0;
let originalHeight = 0;
let originalX = 0;
let originalY = 0;
let currentX = 0;
let currentY = 0;
handles.forEach(handle => {
handle.addEventListener('mousedown', e => {
isResizing = true;
currentHandle = handle;
originalWidth = resizableDiv.offsetWidth;
originalHeight = resizableDiv.offsetHeight;
originalX = resizableDiv.offsetLeft;
originalY = resizableDiv.offsetTop;
currentX = e.pageX;
currentY = e.pageY;
});
});
document.addEventListener('mouseup', () => {
isResizing = false;
});
document.addEventListener('mousemove', e => {
if (!isResizing) return;
let deltaX = e.pageX - currentX;
let deltaY = e.pageY - currentY;
if (currentHandle.classList.contains('handle-n')) {
resizableDiv.style.height = originalHeight - deltaY + 'px';
resizableDiv.style.top = originalY + deltaY + 'px';
} else if (currentHandle.classList.contains('handle-e')) {
resizableDiv.style.width = originalWidth + deltaX + 'px';
} else if (currentHandle.classList.contains('handle-s')) {
resizableDiv.style.height = originalHeight + deltaY + 'px';
} else if (currentHandle.classList.contains('handle-w')) {
resizableDiv.style.width = originalWidth - deltaX + 'px';
resizableDiv.style.left = originalX + deltaX + 'px';
}
});
// rotation
const rotateHandle = document.querySelector('.rotate-handle');
let isDragging = false;
let currentDeg = 0;
let startX = 0;
let startY = 0;
rotateHandle.addEventListener('mousedown', function(e) {
isDragging = true;
startX = e.clientX;
startY = e.clientY;
});
document.addEventListener('mouseup', function() {
isDragging = false;
});
document.addEventListener('mousemove', function(e) {
if (!isDragging) return;
const deltaX = e.clientX - startX;
const deltaY = e.clientY - startY;
currentDeg = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
resizableDiv.style.transform = `rotate(${currentDeg}deg)`;
});
#resizable-div {
position: absolute;
width: 200px;
height: 200px;
left: 50px;
top: 50px;
background-color: #ddd;
}
.handle {
position: absolute;
width: 10px;
height: 10px;
background-color: #fff;
border: 1px solid #000;
}
.handle-n {
top: -5px;
left: 50%;
transform: translateX(-50%);
cursor: n-resize;
}
.handle-e {
right: -5px;
top: 50%;
transform: translateY(-50%);
cursor: e-resize;
}
.handle-s {
bottom: -5px;
left: 50%;
transform: translateX(-50%);
cursor: s-resize;
}
.handle-w {
left: -5px;
top: 50%;
transform: translateY(-50%);
cursor: w-resize;
}
.rotate-handle {
bottom: 0px;
right: 0px;
border-radius: 50%;
background-color: white;
cursor: pointer;
}
<div id="resizable-div">
<div class="handle handle-n"></div>
<div class="handle handle-e"></div>
<div class="handle handle-s"></div>
<div class="handle handle-w"></div>
<div class="handle rotate-handle"></div>
</div>
Try This:
I removed the left and top event from JS, anded a container to the resizable-div element and added flex to it.
const resizableDiv = document.querySelector('#resizable-div');
const handles = document.querySelectorAll('.handle');
let isResizing = false;
let currentHandle = null;
let originalWidth = 0;
let originalHeight = 0;
let originalX = 0;
let originalY = 0;
let currentX = 0;
let currentY = 0;
handles.forEach(handle => {
handle.addEventListener('mousedown', e => {
isResizing = true;
currentHandle = handle;
originalWidth = resizableDiv.offsetWidth;
originalHeight = resizableDiv.offsetHeight;
originalX = resizableDiv.offsetLeft;
originalY = resizableDiv.offsetTop;
currentX = e.pageX;
currentY = e.pageY;
});
});
document.addEventListener('mouseup', () => {
isResizing = false;
});
document.addEventListener('mousemove', e => {
if (!isResizing) return;
let deltaX = e.pageX - currentX;
let deltaY = e.pageY - currentY;
if (currentHandle.classList.contains('handle-n')) {
resizableDiv.style.height = originalHeight - deltaY + 'px';
} else if (currentHandle.classList.contains('handle-e')) {
resizableDiv.style.width = originalWidth + deltaX + 'px';
} else if (currentHandle.classList.contains('handle-s')) {
resizableDiv.style.height = originalHeight + deltaY + 'px';
} else if (currentHandle.classList.contains('handle-w')) {
resizableDiv.style.width = originalWidth - deltaX + 'px';
}
});
// rotation
const rotateHandle = document.querySelector('.rotate-handle');
let isDragging = false;
let currentDeg = 0;
let startX = 0;
let startY = 0;
rotateHandle.addEventListener('mousedown', function(e) {
isDragging = true;
startX = e.clientX;
startY = e.clientY;
});
document.addEventListener('mouseup', function() {
isDragging = false;
});
document.addEventListener('mousemove', function(e) {
if (!isDragging) return;
const deltaX = e.clientX - startX;
const deltaY = e.clientY - startY;
currentDeg = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
resizableDiv.style.transform = `rotate(${currentDeg}deg)`;
});
.container{
position:relative;
min-height:100vh;
display:flex;
justify-content:center;
align-items:center;
}
#resizable-div {
position: absolute;
width: 200px;
height: 200px;
background-color: #ddd;
transform-orgin:top left;
}
.handle {
position: absolute;
width: 10px;
height: 10px;
background-color: #fff;
border: 1px solid #000;
}
.handle-n {
top: -5px;
left: 50%;
transform: translateX(-50%);
cursor: n-resize;
}
.handle-e {
right: -5px;
top: 50%;
transform: translateY(-50%);
cursor: e-resize;
}
.handle-s {
bottom: -5px;
left: 50%;
transform: translateX(-50%);
cursor: s-resize;
}
.handle-w {
left: -5px;
top: 50%;
transform: translateY(-50%);
cursor: w-resize;
}
.rotate-handle {
bottom: 0px;
right: 0px;
border-radius: 50%;
background-color: white;
cursor: pointer;
}
<div class="container">
<div id="resizable-div">
<div class="handle handle-n"></div>
<div class="handle handle-e"></div>
<div class="handle handle-s"></div>
<div class="handle handle-w"></div>
<div class="handle rotate-handle"></div>
</div>
</div>
I have a container which can resize from right-side and bottom .
It is resizing correctly but in both sides that is in height and width at the same time in unlimited length .
Can there be a way to limit direction of resize either bottom side or right side increase or decrease in size .
Single side increase is only possible when using 1 condition in if
Here is the code :
const panel = document.getElementById("styleChangeOuterTag");
let m_pos;
let m_pos1;
function resize(e) {
const dx = m_pos - e.x;
const dy = m_pos1 - e.y;
m_pos = e.x;
m_pos1 = e.y;
panel.style.width = (parseInt(getComputedStyle(panel).width) - dx) + "px";
panel.style.height = (parseInt(getComputedStyle(panel).height) - dy) + "px";
}
panel.addEventListener("mousedown", function(e) {
if (e.offsetX > panel.clientWidth - 10) {
m_pos = e.x;
document.addEventListener("mousemove", resize);
} else if (e.offsetY > panel.clientHeight - 10) {
m_pos1 = e.y;
document.addEventListener("mousemove", resize);
}
});
document.addEventListener("mouseup", function() {
document.removeEventListener("mousemove", resize);
});
#styleChangeOuterTag {
/* display: none; */
/* position: fixed; */
position: relative;
top: 0;
left: 0;
width: 300px;
height: 300px;
padding: 2vw 1.5vw;
background-color: rgb(255, 245, 245);
border: 2px solid rgb(255, 60, 255);
border-radius: 3px;
z-index: 5;
user-select: none;
}
#styleChangeOuterTag::after {
content: '';
background-color: #ccc;
position: absolute;
top: 0;
right: 0;
width: 10px;
height: 100%;
cursor: ew-resize;
}
#styleChangeOuterTag::before {
content: '';
background-color: #ccc;
position: absolute;
bottom: 0;
right: 0;
width: 100%;
height: 10px;
cursor: ns-resize;
}
#styleOptionDetails {
border: 2px solid purple;
border-radius: 3px;
padding: 1vw;
overflow: auto;
}
<div id="styleChangeOuterTag">
<hr>
<div id="styleOptionDetails">
</div>
</div>
Can you tell about how to size the clickable width(grey part in Container-which trigger resize) as now it not right in size and don't work in whole width
created with e.offsetX > panel.clientWidth - 10
Thanks for help in advance
You may add additional condition in to your resize function, something like this:
const minWidth = 150
const maxWidth = 500
const minHeight = 150
const maxHeight = 500
function resize(e) {
const dx = m_pos - e.x;
const dy = m_pos1 - e.y;
m_pos = e.x;
m_pos1 = e.y;
const newWidth = parseInt(getComputedStyle(panel).width) - dx
const newHeight = parseInt(getComputedStyle(panel).height - dy
if (newWidth > minWidth && newWidth < maxWidth) {
panel.style.width = newWidth + "px";
}
if (newHeight > minHeight && newHeight < maxHeight) {
panel.style.height = newHeight + "px";
}
}
I want to find the position of a circle that's following the mouse in two boxes
and the position of the circle when it's out of them. In addition when it (the circle) goes to red box the circle color changes to black, when it goes to red box it's color changes to red and when it's over neither of them it's blue.
I have included the picture here.
window.addEventListener("mousemove", function(e) {
let x = e.clientX;
let y = e.clientY;
let mouse = "Mouse : " + x + " " + y;
document.getElementById("mouseText").innerText = mouse;
let circle = document.getElementById("circleText");
let newX = e.clientX + 5;
let newY = e.clientY + 5;
let newCircle = "circle : " + newX + " " + newY;
document.getElementById("circleText").innerText = newCircle;
let circle2 = document.getElementById("circle");
circle2.style.marginTop = `${newY}px`;
circle2.style.marginLeft = `${newX}px`;
});
function onMousemove(e) {
var m_posx = 0,
m_posy = 0,
e_posx = 0,
e_posy = 0,
obj = this;
//get mouse position on document crossbrowser
if (!e) {
e = window.event;
}
if (e.pageX || e.pageY) {
m_posx = e.pageX;
m_posy = e.pageY;
} else if (e.clientX || e.clientY) {
m_posx =
e.clientX +
document.body.scrollLeft +
document.documentElement.scrollLeft;
m_posy =
e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
//get parent element position in document
if (obj.offsetParent) {
do {
e_posx += obj.offsetLeft;
e_posy += obj.offsetTop;
} while ((obj = obj.offsetParent));
}
// mouse position minus elm position is mouseposition relative to element:
dbg.innerHTML =
" X Position: " + (m_posx - e_posx) + " Y Position: " + (m_posy - e_posy);
}
html {
position: relative;
}
#circle {
width: 15px;
height: 15px;
background-color: blue;
border-radius: 50px;
position: absolute;
}
#row {
display: flex;
margin: 0 200px;
}
#blackShape {
position: relative;
width: 250px;
height: 250px;
background-color: black;
margin-top: 125px;
margin-left: 300px;
right: 180px;
}
#redCircle {
position: absolute;
width: 25px;
height: 25px;
background-color: red;
border-radius: 50px;
top: 50%;
left: 45%;
}
#redShape {
position: relative;
width: 250px;
height: 250px;
background-color: red;
margin-top: 125px;
margin-right: 150px;
}
#blackCircle {
position: absolute;
width: 25px;
height: 25px;
background-color: black;
border-radius: 50px;
top: 50%;
left: 45%;
}
<div id="mouseText"></div>
<div id="circleText"></div>
<div id="circle"></div>
<div id="dbg"></div>
<div id="row">
<div id="blackShape">
<div id="redCircle"></div>
</div>
<div id="redShape">
<div id="blackCircle"></div>
</div>
</div>
This script adjusts the position and size of the elements and listens when the blue circle will fall in these areas. When it leaves the area, the color style returns to its original state.
Example when the blue dot is in the region:
After resizing the "Run code snippet" screen, it may not work correctly. Please copy the code and try it.
var pos = 5; //<-- Circle position
var csz = 15; //<-- Circle size
var c = document.getElementById('circle');
window.onload = window.onresize = elPositions;
function elPositions() {
blc = document.getElementById('blackShape');
blcH = blc.offsetHeight;
blcW = blc.offsetWidth;
blcT = blc.offsetTop;
blcL = blc.offsetLeft;
red = document.getElementById('redShape');
redH = red.offsetHeight;
redW = red.offsetWidth;
redT = red.offsetTop;
redL = red.offsetLeft;
}
function changeColor(y, x) {
if (redT - pos < y && redT + redH - pos - csz > y && redL - pos < x && redL + redW - pos - csz > x) {
c.style.backgroundColor = 'black';
}
else if (blcT - pos < y && blcT + blcH - pos - csz > y && blcL - pos < x && blcL + blcW - pos - csz > x) {
c.style.backgroundColor = 'red';
}
else {
c.style.backgroundColor = '';
}
}
////////////////////////////////////////////////
window.addEventListener("mousemove", function (e) {
let x = e.clientX;
let y = e.clientY;
let mouse = "Mouse : " + x + " " + y;
document.getElementById("mouseText").innerText = mouse;
let circle = document.getElementById("circleText");
let newX = e.clientX + pos;
let newY = e.clientY + pos;
let newCircle = "circle : " + newX + " " + newY;
document.getElementById("circleText").innerText = newCircle;
let circle2 = document.getElementById("circle");
circle2.style.marginTop = newY + 'px';
circle2.style.marginLeft = newX + 'px';
changeColor(newY, newX); //<-- New Line
});
function onMousemove(e) {
var m_posx = 0,
m_posy = 0,
e_posx = 0,
e_posy = 0,
obj = this;
//get mouse position on document crossbrowser
if (!e) {
e = window.event;
}
if (e.pageX || e.pageY) {
m_posx = e.pageX;
m_posy = e.pageY;
}
else if (e.clientX || e.clientY) {
m_posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
m_posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
//get parent element position in document
if (obj.offsetParent) {
do {
e_posx += obj.offsetLeft;
e_posy += obj.offsetTop;
}
while ((obj = obj.offsetParent));
}
// mouse position minus elm position is mouseposition relative to element:
dbg.innerHTML = " X Position: " + (m_posx - e_posx) + " Y Position: " + (m_posy - e_posy);
}
html {
position: relative;
}
#circle {
width: 15px;
height: 15px;
background-color: blue;
border-radius: 50px;
position: absolute;
z-index: 1; /*<-- New Line*/
}
#row {
display: flex;
margin: 0 200px;
}
#blackShape {
position: relative;
width: 250px;
height: 250px;
background-color: black;
margin-top: 125px;
margin-left: 300px;
right: 180px;
}
#redCircle {
position: absolute;
width: 25px;
height: 25px;
background-color: red;
border-radius: 50px;
top: 50%;
left: 45%;
}
#redShape {
position: relative;
width: 250px;
height: 250px;
background-color: red;
margin-top: 125px;
margin-right: 150px;
}
#blackCircle {
position: absolute;
width: 25px;
height: 25px;
background-color: black;
border-radius: 50px;
top: 50%;
left: 45%;
}
<div id="mouseText"></div>
<div id="circleText"></div>
<div id="circle"></div>
<div id="dbg"></div>
<div id="row">
<div id="blackShape">
<div id="redCircle"></div>
</div>
<div id="redShape">
<div id="blackCircle"></div>
</div>
</div>
Example when the mouse cursor is in the region:
document.getElementById('blackShape').addEventListener("mouseover", getColor);
document.getElementById('blackShape').addEventListener("mouseout", retColor);
document.getElementById('redShape').addEventListener("mouseover", getColor);
document.getElementById('redShape').addEventListener("mouseout", retColor);
function getColor() {
var x = this.id;
var c = document.getElementById('circle');
if(x === 'redShape') {
c.style.backgroundColor = 'black'
}
else if (x === 'blackShape') {
c.style.backgroundColor = 'red'
}
}
function retColor() {
var c = document.getElementById('circle');
c.style.backgroundColor = '';
}
////////////////////////////////////////////////
window.addEventListener("mousemove", function (e) {
let x = e.clientX;
let y = e.clientY;
let mouse = "Mouse : " + x + " " + y;
document.getElementById("mouseText").innerText = mouse;
let circle = document.getElementById("circleText");
let newX = e.clientX + 5;
let newY = e.clientY + 5;
let newCircle = "circle : " + newX + " " + newY;
document.getElementById("circleText").innerText = newCircle;
let circle2 = document.getElementById("circle");
circle2.style.marginTop = newY + 'px';
circle2.style.marginLeft = newX + 'px';
});
function onMousemove(e) {
var m_posx = 0,
m_posy = 0,
e_posx = 0,
e_posy = 0,
obj = this;
//get mouse position on document crossbrowser
if (!e) {
e = window.event;
}
if (e.pageX || e.pageY) {
m_posx = e.pageX;
m_posy = e.pageY;
}
else if (e.clientX || e.clientY) {
m_posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
m_posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
//get parent element position in document
if (obj.offsetParent) {
do {
e_posx += obj.offsetLeft;
e_posy += obj.offsetTop;
}
while ((obj = obj.offsetParent));
}
// mouse position minus elm position is mouseposition relative to element:
dbg.innerHTML = " X Position: " + (m_posx - e_posx) + " Y Position: " + (m_posy - e_posy);
}
html {
position: relative;
}
#circle {
width: 15px;
height: 15px;
background-color: blue;
border-radius: 50px;
position: absolute;
z-index: 1; /*<-- New Line*/
}
#row {
display: flex;
margin: 0 200px;
}
#blackShape {
position: relative;
width: 250px;
height: 250px;
background-color: black;
margin-top: 125px;
margin-left: 300px;
right: 180px;
}
#redCircle {
position: absolute;
width: 25px;
height: 25px;
background-color: red;
border-radius: 50px;
top: 50%;
left: 45%;
}
#redShape {
position: relative;
width: 250px;
height: 250px;
background-color: red;
margin-top: 125px;
margin-right: 150px;
}
#blackCircle {
position: absolute;
width: 25px;
height: 25px;
background-color: black;
border-radius: 50px;
top: 50%;
left: 45%;
}
<div id="mouseText"></div>
<div id="circleText"></div>
<div id="circle"></div>
<div id="dbg"></div>
<div id="row">
<div id="blackShape">
<div id="redCircle"></div>
</div>
<div id="redShape">
<div id="blackCircle"></div>
</div>
</div>
I have attached snippet where I have an image which is draggable and zoomable inside a div. But there is one issue, when moving image from left to right, it should not be able to move if the corner of image meets the corner of parent for both X and Y. I actually want to know when the corners of image meets with parent div corners because I dont want to allow dragging when this condition meets. Background red color should not be visible when dragging image.
window.repositionImage = function(event){
var element = document.getElementById('img');
element.addEventListener('mousedown', function(e){
e.stopPropagation();
element.style.cursor = "grabbing";
if (e.target != element) return;
var offsetX = e.pageX - element.offsetLeft;
var offsetY = e.pageY - element.offsetTop;
var move = function(e){
element.style.left = e.pageX - offsetX + "px";
element.style.top = e.pageY - offsetY + "px";
}
var stop = function(){
element.style.cursor = "default";
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", stop);
}
document.addEventListener("mousemove", move);
document.addEventListener("mouseup", stop);
})
}
window.panChangeHandler = function(e){
var element = document.getElementById('img');
if (e.target.value == 0) {
element.style.left = "0px";
element.style.top = "0px";
}
img.style.transform = `scale(1.${e.target.value})`;
}
.item {
border: 1px solid;
background: red;
width: 300px;
height: 300px;
overflow: hidden;
position:relative;
}
.item img {
position:absolute;
width: 100%;
height: 100%;
-webkit-user-drag: none;
left:0;
top:0;
}
.slider {
z-index: 9;
position: absolute;
left: 0;
top: 0;
margin-left: -20px;
margin-top: 70px;
writing-mode: bt-lr; /* IE */
-webkit-appearance: slider-vertical; /* WebKit */
transform: rotateZ(270deg);
}
.slider input {
width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='item'>
<span class='slider'>
<input type='range' aria-orientation="vertical"
value="0" min="0" max="9" step="1" oninput="panChangeHandler(event)"
/>
</span>
<img id='img' src="https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixlib=rb-1.2.1&w=1000&q=80" alt='image' onmouseover="repositionImage(event)" />
</div>
There is a simple css fix you can try but I'm not sure about it's crossbrowser compatibility. Change the .item img position to sticky.
window.repositionImage = function(event){
var element = document.getElementById('img');
element.addEventListener('mousedown', function(e){
e.stopPropagation();
element.style.cursor = "grabbing";
if (e.target != element) return;
var offsetX = e.pageX - element.offsetLeft;
var offsetY = e.pageY - element.offsetTop;
var move = function(e){
element.style.left = e.pageX - offsetX + "px";
element.style.top = e.pageY - offsetY + "px";
}
var stop = function(){
element.style.cursor = "default";
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", stop);
}
document.addEventListener("mousemove", move);
document.addEventListener("mouseup", stop);
})
}
window.panChangeHandler = function(e){
var element = document.getElementById('img');
img.style.transform = `scale(1.${e.target.value})`;
}
document.getElementById("img").disabled = true;
.item {
border: 1px solid;
background: red;
width: 300px;
height: 300px;
overflow: hidden;
position:relative;
}
.item img {
position: sticky;
width: 100%;
height: 100%;
-webkit-user-drag: none;
left:0;
top:0;
}
.slider {
z-index: 9;
position: absolute;
left: 0;
top: 0;
margin-left: -20px;
margin-top: 70px;
writing-mode: bt-lr; /* IE */
-webkit-appearance: slider-vertical; /* WebKit */
transform: rotateZ(270deg);
}
.slider input {
width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='item'>
<span class='slider'>
<input type='range' aria-orientation="vertical"
value="0" min="0" max="9" step="1" oninput="panChangeHandler(event)"
/>
</span>
<img id='img' src="https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixlib=rb-1.2.1&w=1000&q=80" alt='image' onmouseover="repositionImage(event)" />
</div>
Check
if (e.target.tagName == "DIV" ) return;
On drop event
I managed to solve this issue:
function parseComplexStyleProperty(str) {
var regex = /(\w+)\((.+?)\)/g,
transform = {},
match;
while ((match = regex.exec(str))) transform[match[1]] = match[2];
return transform;
};
window.repositionImage = function(event){
var element = document.getElementById('img');
element.addEventListener('mousedown', function(e){
e.stopPropagation();
element.style.cursor = "grabbing";
if (e.target != element) return;
var offsetX = e.pageX - element.offsetLeft;
var offsetY = e.pageY - element.offsetTop;
var x = 0;
var y = 0;
var move = function(e){
x = e.pageX - offsetX;
y = e.pageY - offsetY;
element.style.left = e.pageX - offsetX + "px";
element.style.top = e.pageY - offsetY + "px";
}
var stop = function(){
element.style.cursor = "default";
var t = parseComplexStyleProperty(element.style.transform);
if (!Object.keys(t).length) {
element.style.left = "0px";
element.style.top = "0px";
}
else {
var imageWidth = element.clientWidth * parseFloat(t.scale);
var imageHeight =
element.clientHeight * parseFloat(t.scale);
var pointToSubX = Math.trunc(
(imageWidth - parent.clientWidth) / 2
);
var pointToSubY = Math.trunc(
(imageHeight - parent.clientHeight) / 2
);
if (x > pointToSubX || x < -pointToSubX) {
if (x > pointToSubX)
element.style.left = pointToSubX + "px";
else element.style.left = -pointToSubX + "px";
}
if (y > pointToSubY || y < -pointToSubY) {
if (y > pointToSubY)
element.style.top = pointToSubY + "px";
else element.style.top = -pointToSubY + "px";
}
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", stop);
}
}
document.addEventListener("mousemove", move);
document.addEventListener("mouseup", stop);
})
}
window.panChangeHandler = function(e){
var element = document.getElementById('img');
img.style.transform = `scale(1.${e.target.value})`;
}
document.getElementById("img").disabled = true;
.item {
margin-right: 1px;
height: 200px;
background: white;
overflow: hidden;
position: relative;
}
.item img {
transform: scale(1);
position: relative;
background-color: #eee;
width: 100%;
height: 100%;
-webkit-user-drag: none;
left:0;
top:0;
}
.slider {
z-index: 9;
position: absolute;
left: 0;
top: 0;
margin-left: -20px;
margin-top: 70px;
writing-mode: bt-lr; /* IE */
-webkit-appearance: slider-vertical; /* WebKit */
transform: rotateZ(270deg);
}
.slider input {
width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='item'>
<span class='slider'>
<input type='range' aria-orientation="vertical"
value="0" min="0" max="9" step="1" oninput="panChangeHandler(event)"
/>
</span>
<img id='img' src="https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixlib=rb-1.2.1&w=1000&q=80" alt='image'
onmouseover="repositionImage(event)" />
</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
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.net/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.com/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.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/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>