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