move-rotate-resizer
Version:
A simple javascript object that provide easy way to make any dom element resizable. It provide handles to move, resize and rotate target element. Optimized, fastest and easiest single javascript file.
1,044 lines (999 loc) • 35.9 kB
JavaScript
if (document.querySelectorAll('link[href*="resizer.css"], style[src*="resizer.css"]').length === 0) {
fetch('https://raw.githubusercontent.com/developergovindgupta/move-rotate-resizer/master/resizer.css')
.then((response) => {
if (response.ok) {
response.text().then((data) => {
let style = document.createElement('style');
style.setAttribute('type', 'text/css');
style.setAttribute('src', 'resizer.css');
style.innerHTML = data;
document.head.appendChild(style);
});
} else {
console.info('download resizer.css and include in index.html');
}
})
.catch((err) => {
console.log(err);
});
}
const resizer = {
target: null,
resizer: null,
hoverLine: null,
add(target, options) {
this.target = target;
if (target) {
let defaultOptions = {
minWidth: 30,
minHeight: 30,
aspectRatio: true,
resizeFromCenter: false,
onDragStart: null,
onDragging: null,
onDragEnd: null,
onResizeStart: null,
onResizing: null,
onResizeEnd: null,
onRotateStart: null,
onRotating: null,
onRotateEnd: null,
onResizerShown: null,
onResizerHide: null,
isHideOnResize: true,
isHoverLine: true,
boundWithContainer: false,
resizers: {
n: true,
s: true,
e: true,
w: true,
ne: true,
nw: true,
se: true,
sw: true,
r: true,
},
};
let getAngle = (target) => {
let angle = 0;
if (target) {
angle = parseFloat(target.angle);
if (isNaN(angle)) {
angle = 0;
let tmatrix = window.getComputedStyle(target).transform;
if (tmatrix && tmatrix != 'none') {
let matrixValues = tmatrix.split('(')[1].split(')')[0].split(',');
let matrix_a = matrixValues[0];
let matrix_b = matrixValues[1];
let rotationInRadians = Math.atan2(matrix_b, matrix_a);
angle = parseInt(rotationInRadians * (180 / Math.PI));
if (angle < 0) {
angle = 360 + angle;
}
}
}
target.angle = angle;
}
return angle;
};
options = options || {};
target.options = { ...defaultOptions, ...options };
target.options.resizers = { ...target.options.resizers };
target.style.position = 'absolute';
target.style.left = target.offsetLeft + 'px';
target.style.top = target.offsetTop + 'px';
target.style.width = target.offsetWidth + 'px';
target.style.height = target.offsetHeight + 'px';
target.angle = getAngle(target);
target.resizer = true;
target.isDisabled = target.getAttribute('isDisabled') === 'true';
if (target.isDisabled) {
target.resizer = false;
}
let bBox = this.show(target);
target.bBox = bBox;
target.scale = bBox.width / target.offsetWidth;
target.moveCounter = 0;
target.resizer = this.resizer;
if (!document.querySelector('.resizer-container')) {
document.body.appendChild(target.resizer);
}
let handleMousedown = (e) => {
if (e.type === 'mousedown') {
e.preventDefault();
if (e.button != 0) {
return;
}
}
e.stopPropagation();
target.isDisabled = target.getAttribute('isDisabled') === 'true';
if (target.isDisabled) {
target.resizer = false;
this.hide();
}
target.isLocked = target.getAttribute('islocked') === 'true';
target.startPos = { x: e.clientX + document.body.scrollLeft, y: e.clientY + document.body.scrollTop };
target.size = { left: target.offsetLeft, top: target.offsetTop, width: target.offsetWidth, height: target.offsetHeight };
if (!target.isLocked && !target.isDisabled) {
document.addEventListener('mousemove', handleMousemove);
document.addEventListener('mouseup', handleMouseup);
document.addEventListener('touchmove', handleMousemove);
document.addEventListener('touchend', handleMouseup);
}
if (e.type === 'touchstart') {
if (e.touches.length > 1) {
return;
}
target.startPos = { x: e.touches[0].clientX + document.body.scrollLeft, y: e.touches[0].clientY + document.body.scrollTop };
}
target.resizer && (target.resizer.visibile = false);
this.show(target);
this.target = target;
let handleClick = (e) => {
e.stopPropagation();
e.preventDefault();
this.show(target);
window.removeEventListener('click', handleClick, true);
};
window.addEventListener('click', handleClick, true);
target.moveCounter = 0;
this.hoverLine && (this.hoverLine.style.opacity = '0');
};
let handleMousemove = (e) => {
e.stopPropagation();
e.type === 'mousemove' && e.preventDefault();
target.moveCounter++;
if (target.moveCounter === 1) {
e.size = { ...target.size };
e.angle = target.angle;
e.evtTarget = target;
e.handler = this.resizer;
target.options.onDragStart && target.options.onDragStart(e);
target.resizer && target.resizer.showHideResizer && target.resizer.showHideResizer(true);
}
let x = e.clientX + document.body.scrollLeft - target.startPos.x;
let y = e.clientY + document.body.scrollTop - target.startPos.y;
if (e.type === 'touchmove') {
x = e.touches[0].clientX + document.body.scrollLeft - target.startPos.x;
y = e.touches[0].clientY + document.body.scrollTop - target.startPos.y;
}
let newX = target.size.left + x / target.scale;
let newY = target.size.top + y / target.scale;
target.style.left = newX + 'px';
target.style.top = newY + 'px';
if (options.boundWithContainer) {
let container = options.boundWithContainer instanceof HTMLDivElement ? options.boundWithContainer : target.offsetParent;
if (container) {
let bBox = container.getBoundingClientRect();
let xBox = target.getBoundingClientRect();
if (xBox.left < bBox.left) {
let dx = bBox.left - xBox.left;
newX += dx / target.scale;
}
if (xBox.top < bBox.top) {
let dy = bBox.top - xBox.top;
newY += dy / target.scale;
}
if (xBox.right > bBox.right) {
let dx = bBox.right - xBox.right;
newX += dx / target.scale;
}
if (xBox.bottom > bBox.bottom) {
let dy = bBox.bottom - xBox.bottom;
newY += dy / target.scale;
}
target.style.left = newX + 'px';
target.style.top = newY + 'px';
}
}
target.newSize = { ...target.size, left: newX, top: newY };
//dispatch Events
if (target.options.onDragging) {
e.size = { ...target.newSize };
e.angle = target.angle;
e.evtTarget = target;
e.handler = this.resizer;
target.options.onDragging(e);
}
this.show(target);
};
let handleMouseup = (e) => {
e.stopPropagation();
e.type === 'mouseup' && e.preventDefault();
document.removeEventListener('mousemove', handleMousemove);
document.removeEventListener('mouseup', handleMouseup);
document.removeEventListener('touchmove', handleMousemove);
document.removeEventListener('touchend', handleMouseup);
target.resizer.showHideResizer(false);
//dispatch Events
if (target.moveCounter && target.options.onDragEnd) {
e.size = { ...target.newSize };
e.angle = target.angle;
e.evtTarget = target;
e.handler = this.resizer;
target.options.onDragEnd(e);
}
this.show(target);
target.dispatchEvent(new MouseEvent('click'));
};
target.handleMouseEnter = (e) => {
if (this.target != e.target && e.target.options.isHoverLine) {
let getBorderBox = (target) => {
let _hoverLine = target.cloneNode();
_hoverLine.innerHTML = '';
_hoverLine.style.cssText = target.style.cssText;
_hoverLine.style.opacity = '0';
_hoverLine.style.pointerEvents = 'none';
let transform = _hoverLine.style.transform;
if (transform && transform.indexOf('rotate') >= 0) {
_hoverLine.style.transform = transform.replace(/rotate\(\w*\)/gi, '');
} else if (target.angle) {
_hoverLine.style.transform = transform + ' rotate(0deg)';
}
target.parentNode.appendChild(_hoverLine);
let bBox = _hoverLine.getBoundingClientRect();
_hoverLine.remove();
return bBox;
};
let hoverLine = document.querySelector('.resizer-target-hover-line');
!hoverLine && (hoverLine = document.createElement('div'));
hoverLine.className = 'resizer-target-hover-line';
hoverLine.style.position = 'absolute';
document.body.appendChild(hoverLine);
this.hoverLine = hoverLine;
let bBox = getBorderBox(e.target);
hoverLine.style.left = parseInt(bBox.left + window.scrollX) + 'px';
hoverLine.style.top = parseInt(bBox.top + window.scrollY) + 'px';
hoverLine.style.width = parseInt(bBox.width + 2) + 'px';
hoverLine.style.height = parseInt(bBox.height + 2) + 'px';
hoverLine.style.opacity = '1';
hoverLine.style.transform = 'rotate(' + (e.target.angle || 0) + 'deg)';
hoverLine.target = e.target;
}
};
target.handleMouseLeave = (e) => {
this.hoverLine && (this.hoverLine.style.opacity = '0');
};
if (!target.handleMousedown) {
target.handleMousedown = handleMousedown;
target.removeEventListener('mousedown', handleMousedown);
target.addEventListener('mousedown', handleMousedown);
target.removeEventListener('touchstart', handleMousedown);
target.addEventListener('touchstart', handleMousedown);
target.handleClick = (e) => {
e.stopPropagation();
};
target.removeEventListener('click', target.handleClick);
target.addEventListener('click', target.handleClick);
target.addEventListener('mouseenter', target.handleMouseEnter);
target.addEventListener('mouseleave', target.handleMouseLeave);
}
}
},
show(target) {
if (target && target.resizer) {
if (!this.resizer) {
let resizer = document.querySelector('.resizer-container');
resizer && resizer.remove();
//create new resizer-container
resizer = document.createElement('div');
resizer.className = 'resizer-container';
resizer.style.position = 'absolute';
document.body.appendChild(resizer);
this.resizer = resizer;
let resizer_border = document.createElement('div');
resizer_border.className = 'resizer-border';
resizer_border.actionName = 'resizer-border';
resizer.resizer_border = resizer_border;
resizer.appendChild(resizer_border);
let nw_resizer = document.createElement('div');
nw_resizer.className = 'nw-resizer';
nw_resizer.actionName = 'nw-resizer';
resizer.nw_resizer = nw_resizer;
resizer.appendChild(nw_resizer);
let ne_resizer = document.createElement('div');
ne_resizer.className = 'ne-resizer';
ne_resizer.actionName = 'ne-resizer';
resizer.ne_resizer = ne_resizer;
resizer.appendChild(ne_resizer);
let sw_resizer = document.createElement('div');
sw_resizer.className = 'sw-resizer';
sw_resizer.actionName = 'sw-resizer';
resizer.sw_resizer = sw_resizer;
resizer.appendChild(sw_resizer);
let se_resizer = document.createElement('div');
se_resizer.className = 'se-resizer';
se_resizer.actionName = 'se-resizer';
resizer.se_resizer = se_resizer;
resizer.appendChild(se_resizer);
let n_resizer = document.createElement('div');
n_resizer.className = 'n-resizer';
n_resizer.actionName = 'n-resizer';
resizer.n_resizer = n_resizer;
resizer.appendChild(n_resizer);
let e_resizer = document.createElement('div');
e_resizer.className = 'e-resizer';
e_resizer.actionName = 'e-resizer';
resizer.e_resizer = e_resizer;
resizer.appendChild(e_resizer);
let s_resizer = document.createElement('div');
s_resizer.className = 's-resizer';
s_resizer.actionName = 's-resizer';
resizer.s_resizer = s_resizer;
resizer.appendChild(s_resizer);
let w_resizer = document.createElement('div');
w_resizer.className = 'w-resizer';
w_resizer.actionName = 'w-resizer';
resizer.w_resizer = w_resizer;
resizer.appendChild(w_resizer);
let r_resizer = document.createElement('div');
r_resizer.className = 'r-resizer';
r_resizer.actionName = 'r-resizer';
resizer.r_resizer = r_resizer;
resizer.appendChild(r_resizer);
let ddmrr_angle_div = document.createElement('div');
ddmrr_angle_div.className = 'rotator-angle-div';
ddmrr_angle_div.style.display = 'none';
document.body.appendChild(ddmrr_angle_div);
resizer.showHideResizer = function (isHide, resizerHandle) {
if (this.target.isLocked) {
isHide = false;
}
resizer.querySelectorAll('*').forEach((x) => {
x !== resizerHandle && (x.style.opacity = isHide ? 0 : 1);
});
};
let showAngleValue = (x, y, angle) => {
ddmrr_angle_div.style.display = '';
ddmrr_angle_div.style.left = x + 'px';
ddmrr_angle_div.style.top = y + 'px';
ddmrr_angle_div.innerHTML = angle;
};
let hideAngleValue = () => {
ddmrr_angle_div.style.display = 'none';
};
let rotateXY = (cx, cy, x, y, angle) => {
let radians = (Math.PI / 180) * angle,
cos = Math.cos(radians),
sin = Math.sin(radians),
nx = cos * (x - cx) + sin * (y - cy) + cx,
ny = cos * (y - cy) - sin * (x - cx) + cy;
return { x: nx, y: ny };
};
let getCoordinates = (size, angle) => {
/*
a(x,y) _____________________________ b(x,y)
| |
| |
| |
| |
d(x,y)|_____________________________| c(x,y)
*/
let radians = (Math.PI / -180) * angle;
let cos = Math.cos(radians);
let sin = Math.sin(radians);
let x1 = size.left;
let y1 = size.top;
let x2 = x1 + size.width;
let y2 = y1;
let x3 = x1 + size.width;
let y3 = y1 + size.height;
let x4 = x1;
let y4 = y1 + size.height;
let px = x1 + size.width / 2;
let py = y1 + size.height / 2;
// console.table({ angle, radians, cos, sin, x1, y1, x2, y2, x3, y3, x4, y4, px, py });
let ax = parseInt(cos * (x1 - px) + sin * (y1 - py) + px);
let ay = parseInt(cos * (y1 - py) - sin * (x1 - px) + py);
let bx = parseInt(cos * (x2 - px) + sin * (y2 - py) + px);
let by = parseInt(cos * (y2 - py) - sin * (x2 - px) + py);
let cx = parseInt(cos * (x3 - px) + sin * (y3 - py) + px);
let cy = parseInt(cos * (y3 - py) - sin * (x3 - px) + py);
let dx = parseInt(cos * (x4 - px) + sin * (y4 - py) + px);
let dy = parseInt(cos * (y4 - py) - sin * (x4 - px) + py);
return { ax, ay, bx, by, cx, cy, dx, dy, px, py };
};
let adjustRotateDiv = (size, oldSize, angle, fixToPos) => {
let s1 = getCoordinates(oldSize, angle);
let s2 = getCoordinates(size, angle);
// console.log('--------------------');
// console.log('oldSize:=', oldSize);
// console.log('s1:=', s1);
// console.log('newSize:=', size);
// console.log('s2:=', s2);
let newX = 0;
let newY = 0;
switch (fixToPos) {
case 1:
case 'TopLeft':
newX = size.left + s1.ax - s2.ax;
newY = size.top + s1.ay - s2.ay;
break;
case 2:
case 'TopRight':
newX = size.left + s1.bx - s2.bx;
newY = size.top + s1.by - s2.by;
break;
case 3:
case 'BottomRight':
newX = size.left + s1.cx - s2.cx;
newY = size.top + s1.cy - s2.cy;
break;
case 4:
case 'BottomLeft':
newX = size.left + s1.dx - s2.dx;
newY = size.top + s1.dy - s2.dy;
break;
default:
newX = size.left + s1.ax - s2.ax;
newY = size.top + s1.ay - s2.ay;
break;
}
return {
x: newX,
y: newY,
};
};
let handleMousedown = (e) => {
if (e.type === 'mousedown') {
if (e.button != 0) {
return;
}
e.preventDefault();
}
e.stopPropagation();
let target = this.target;
target.isLocked = target.getAttribute('islocked') === 'true';
if (!target.isLocked) {
window.addEventListener('mousemove', handleMousemove);
window.addEventListener('mouseup', handleMouseup);
window.addEventListener('touchmove', handleMousemove);
window.addEventListener('touchend', handleMouseup);
}
resizer.current = e.target;
moveCounter = 0;
resizer.current.classList.add('active');
resizer.startPos = {
x: e.clientX + document.body.scrollLeft,
y: e.clientY + document.body.scrollTop,
};
target.size = {
left: target.offsetLeft,
top: target.offsetTop,
width: target.offsetWidth,
height: target.offsetHeight,
cx: target.offsetLeft + target.offsetWidth / 2,
cy: target.offsetTop + target.offsetHeight / 2,
angle: target.angle,
};
target.prevSize = { ...target.size };
if (e.type === 'touchstart') {
if (e.touches.length > 1) {
return;
}
resizer.startPos = {
x: e.touches[0].clientX + document.body.scrollLeft,
y: e.touches[0].clientY + document.body.scrollTop,
};
}
target.bBox = target.getBoundingClientRect();
if (target.angle) {
let bBox = target.bBox;
let cx = bBox.left + bBox.width / 2;
let cy = bBox.top + bBox.height / 2;
resizer.startPos = rotateXY(cx, cy, resizer.startPos.x, resizer.startPos.y, target.angle);
}
if (target.angle && !target.options.resizeFromCenter) {
let coord = getCoordinates(target.size, target.angle);
target.coord = coord;
switch (resizer.current.actionName) {
case 'se-resizer':
case 'e-resizer':
case 's-resizer':
// toFixPos = 'TopLeft';
resizer.style.transformOrigin = 'top left';
target.style.transformOrigin = 'top left';
target.style.left = coord.ax + 'px';
target.style.top = coord.ay + 'px';
break;
case 'sw-resizer':
case 'w-resizer':
// toFixPos = 'TopRight';
resizer.style.transformOrigin = 'top right';
target.style.transformOrigin = 'top right';
target.style.left = coord.bx - target.size.width + 'px';
target.style.top = coord.by + 'px';
break;
case 'ne-resizer':
// toFixPos = 'BottomLeft';
resizer.style.transformOrigin = 'bottom left';
target.style.transformOrigin = 'bottom left';
target.style.left = coord.dx + 'px';
target.style.top = coord.dy - target.size.height + 'px';
break;
case 'nw-resizer':
case 'n-resizer':
// toFixPos = 'BottomRight';
resizer.style.transformOrigin = 'bottom right';
target.style.transformOrigin = 'bottom right';
target.style.left = coord.cx - target.size.width + 'px';
target.style.top = coord.cy - target.size.height + 'px';
break;
default:
break;
}
}
this.show(target);
let handleClick = (e) => {
e.stopPropagation();
e.preventDefault();
window.removeEventListener('click', handleClick, true);
};
window.addEventListener('click', handleClick, true);
resizer.showHideResizer(true, resizer.current);
};
let handleMousemove = (e) => {
e.stopPropagation();
e.type === 'mousemove' && e.preventDefault();
let target = this.target;
let resizer = this.resizer;
let resizeFromCenter = target.options.resizeFromCenter;
let { minWidth, minHeight, aspectRatio } = target.options;
let X = e.clientX + document.body.scrollLeft;
let Y = e.clientY + document.body.scrollTop;
let x = e.clientX + document.body.scrollLeft - resizer.startPos.x;
let y = e.clientY + document.body.scrollTop - resizer.startPos.y;
let left = target.size.left;
let top = target.size.top;
let width = target.size.width;
let height = target.size.height;
let bBox = target.bBox;
let cx = bBox.left + bBox.width / 2;
let cy = bBox.top + bBox.height / 2;
let angle = target.angle;
if (moveCounter === 0) {
if (this.resizer.current.actionName === 'r-resizer') {
if (target.options && target.options.onRotateStart) {
e.size = { ...target.size };
e.angle = target.angle;
e.evtTarget = target;
e.handler = resizer.current;
target.options.onRotateStart(e);
}
} else {
if (target.options && target.options.onResizeStart) {
e.size = { ...target.size };
e.angle = target.angle;
e.evtTarget = target;
e.handler = resizer.current;
target.options.onResizeStart(e);
}
}
}
moveCounter++;
if (e.type === 'touchmove') {
x = e.touches[0].clientX + document.body.scrollLeft - resizer.startPos.x;
y = e.touches[0].clientY + document.body.scrollTop - resizer.startPos.y;
X = e.touches[0].clientX + document.body.scrollLeft;
Y = e.touches[0].clientY + document.body.scrollTop;
}
if (angle) {
let cx = bBox.left + bBox.width / 2;
let cy = bBox.top + bBox.height / 2;
let newXY = rotateXY(cx, cy, X, Y, angle);
x = newXY.x - resizer.startPos.x;
y = newXY.y - resizer.startPos.y;
}
if (resizeFromCenter) {
x = x * 2;
y = y * 2;
}
switch (this.resizer.current.actionName) {
case 'se-resizer':
{
width = target.size.width + x / target.scale;
height = target.size.height + y / target.scale;
if (width < minWidth) {
width = minWidth;
}
if (height < minHeight) {
height = minHeight;
}
if (aspectRatio) {
let hr = target.size.height / target.size.width;
height = width * hr;
if (height < minHeight) {
height = minHeight;
let wr = target.size.width / target.size.height;
width = height * wr;
}
}
width = parseInt(width);
height = parseInt(height);
}
break;
case 'sw-resizer':
{
width = target.size.width - x / target.scale;
height = target.size.height + y / target.scale;
if (width < minWidth) {
width = minWidth;
}
if (height < minHeight) {
height = minHeight;
}
if (aspectRatio) {
let hr = target.size.height / target.size.width;
height = width * hr;
}
width = parseInt(width);
height = parseInt(height);
left = left + target.size.width - width;
}
break;
case 'ne-resizer':
{
width = target.size.width + x / target.scale;
height = target.size.height - y / target.scale;
if (width < minWidth) {
width = minWidth;
}
if (height < minHeight) {
height = minHeight;
}
if (aspectRatio) {
let hr = target.size.height / target.size.width;
height = width * hr;
}
width = parseInt(width);
height = parseInt(height);
top = top + target.size.height - height;
}
break;
case 'nw-resizer':
{
width = target.size.width - x / target.scale;
height = target.size.height - y / target.scale;
if (width < minWidth) {
width = minWidth;
}
if (height < minHeight) {
height = minHeight;
}
if (aspectRatio) {
let hr = target.size.height / target.size.width;
height = width * hr;
}
width = parseInt(width);
height = parseInt(height);
top = top + target.size.height - height;
left = left + target.size.width - width;
}
break;
case 'n-resizer':
{
height = target.size.height - y / target.scale;
if (height < minHeight) {
height = minHeight;
}
width = parseInt(width);
height = parseInt(height);
top = top + target.size.height - height;
}
break;
case 'e-resizer':
{
width = target.size.width + x / target.scale;
if (width < minWidth) {
width = minWidth;
}
width = parseInt(width);
height = parseInt(height);
}
break;
case 's-resizer':
{
height = target.size.height + y / target.scale;
if (height < minHeight) {
height = minHeight;
}
width = parseInt(width);
height = parseInt(height);
}
break;
case 'w-resizer':
{
width = target.size.width - x / target.scale;
if (width < minWidth) {
width = minWidth;
}
width = parseInt(width);
height = parseInt(height);
left = left + target.size.width - width;
}
break;
case 'r-resizer':
{
angle = Math.atan2(X - cx, -(Y - cy)) * (180 / Math.PI) - 180;
angle = parseInt(angle >= 0 ? angle : 360 + angle);
target.angle = angle;
if (target.style.transform.indexOf('rotate') >= 0) {
target.style.transform = target.style.transform.replace(/rotate\(\w*\)/gi, 'rotate(' + angle + 'deg)');
} else {
target.style.transform += ' rotate(' + angle + 'deg)';
}
showAngleValue(X, Y, angle);
}
break;
default:
break;
}
if (target.angle && this.resizer.current.actionName !== 'r-resizer' && !resizeFromCenter) {
let toFixPos = 'TopLeft';
switch (this.resizer.current.actionName) {
case 'se-resizer':
case 'e-resizer':
case 's-resizer':
// toFixPos = 'TopLeft';
left = target.coord.ax;
top = target.coord.ay;
break;
case 'sw-resizer':
case 'w-resizer':
// toFixPos = 'TopRight';
left = target.coord.bx - width;
top = target.coord.by;
let s1 = getCoordinates({ left, top, width, height }, 0);
break;
case 'ne-resizer':
// toFixPos = 'BottomLeft';
left = target.coord.dx;
top = target.coord.dy - height;
break;
case 'nw-resizer':
case 'n-resizer':
// toFixPos = 'BottomRight';
left = target.coord.cx - width;
top = target.coord.cy - height;
break;
default:
break;
}
}
if (resizeFromCenter) {
left = target.size.cx - width / 2;
top = target.size.cy - height / 2;
}
let newSize = { left, top, width, height };
target.newSize = newSize;
target.style.left = left + 'px';
target.style.top = top + 'px';
target.style.width = width + 'px';
target.style.height = height + 'px';
if (target.options.boundWithContainer) {
let container = target.options.boundWithContainer instanceof HTMLDivElement ? target.options.boundWithContainer : target.offsetParent;
if (container) {
let bBox = container.getBoundingClientRect();
let xBox = target.getBoundingClientRect();
if (xBox.left < bBox.left || xBox.top < bBox.top || xBox.right > bBox.right || xBox.bottom > bBox.bottom) {
left = target.prevSize.left;
top = target.prevSize.top;
width = target.prevSize.width;
height = target.prevSize.height;
angle = target.prevSize.angle;
newSize = { left, top, width, height };
target.newSize = newSize;
target.style.left = left + 'px';
target.style.top = top + 'px';
target.style.width = width + 'px';
target.style.height = height + 'px';
target.angle = angle;
if (target.style.transform.indexOf('rotate') >= 0) {
target.style.transform = target.style.transform.replace(/rotate\(\w*\)/gi, 'rotate(' + angle + 'deg)');
} else {
target.style.transform += ' rotate(' + angle + 'deg)';
}
showAngleValue(X, Y, angle);
} else {
target.prevSize = { left, top, width, height, angle };
}
}
}
//trigger onResizing Event
if (this.resizer.current.actionName === 'r-resizer') {
if (target.options && target.options.onRotating) {
e.size = { ...target.newSize };
e.angle = target.angle;
e.evtTarget = target;
e.handler = resizer.current;
target.options.onRotating(e);
}
} else {
if (target.options && target.options.onResizing) {
e.size = { ...target.newSize };
e.angle = target.angle;
e.evtTarget = target;
e.handler = resizer.current;
target.options.onResizing(e);
}
}
this.show(target);
};
let handleMouseup = (e) => {
e.stopPropagation();
e.type === 'mouseup' && e.preventDefault();
window.removeEventListener('mousemove', handleMousemove);
window.removeEventListener('mouseup', handleMouseup);
window.removeEventListener('touchmove', handleMousemove);
window.removeEventListener('touchend', handleMouseup);
hideAngleValue();
resizer.showHideResizer(false, resizer.current);
let target = this.target;
let resizeFromCenter = target.options.resizeFromCenter;
if (target.angle && resizer.current.actionName !== 'r-resizer' && !resizeFromCenter) {
let toFixPos = 'TopLeft';
resizer.style.transformOrigin = '';
target.style.transformOrigin = '';
let newSize;
let adj;
switch (this.resizer.current.actionName) {
case 'se-resizer':
toFixPos = 'TopLeft';
break;
case 'sw-resizer':
toFixPos = 'TopRight';
break;
case 'ne-resizer':
toFixPos = 'BottomLeft';
break;
case 'nw-resizer':
toFixPos = 'BottomRight';
break;
case 'n-resizer':
toFixPos = 'BottomRight';
break;
case 'e-resizer':
toFixPos = 'TopLeft';
break;
case 's-resizer':
toFixPos = 'TopLeft';
break;
case 'w-resizer':
toFixPos = 'TopRight';
break;
default:
break;
}
newSize = { left: target.size.left, top: target.size.top, width: target.newSize.width, height: target.newSize.height };
adj = adjustRotateDiv(newSize, target.size, target.angle, toFixPos);
target.style.left = adj.x + 'px';
target.style.top = adj.y + 'px';
target.newSize = { ...newSize, left: adj.x, top: adj.y };
}
if (moveCounter) {
if (resizer.current.actionName === 'r-resizer') {
if (target.options && target.options.onRotateEnd) {
e.size = { ...target.newSize };
e.angle = target.angle;
e.evtTarget = target;
e.handler = resizer.current;
target.options.onRotateEnd(e);
}
} else {
if (target.options && target.options.onResizeEnd) {
e.size = { ...target.newSize };
e.angle = target.angle;
e.evtTarget = target;
e.handler = resizer.current;
target.options.onResizeEnd(e);
}
}
}
resizer.current.classList.remove('active');
this.show(target);
};
let moveCounter = 0;
resizer.removeEventListener('mousedown', handleMousedown);
resizer.addEventListener('mousedown', handleMousedown);
resizer.removeEventListener('touchstart', handleMousedown);
resizer.addEventListener('touchstart', handleMousedown);
let onWindowResize = (e) => {
resizer.visibile && this.show(this.target);
};
window.removeEventListener('resize', onWindowResize, true);
window.addEventListener('resize', onWindowResize, true);
let scrollHandler = (e) => {
resizer.visibile && this.show(this.target);
};
window.removeEventListener('scroll', scrollHandler, true);
window.addEventListener('scroll', scrollHandler, true);
}
let resizer = this.resizer;
let getBorderBox = (target) => {
let _target = resizer._target;
if (!_target) {
_target = target.cloneNode();
_target.innerHTML = '';
target.parentNode.appendChild(_target);
resizer._target = _target;
}
_target.style.cssText = target.style.cssText;
_target.style.opacity = '0';
_target.style.pointerEvents = 'none';
let transform = _target.style.transform;
if (transform && transform.indexOf('rotate') >= 0) {
_target.style.transform = transform.replace(/rotate\(\w*\)/gi, '');
} else if (target.angle) {
_target.style.transform = transform + ' rotate(0deg)';
}
_target.timeOut && window.clearTimeout(_target.timeOut);
_target.timeOut = window.setTimeout(() => {
window.clearTimeout(_target.timeOut);
_target.remove();
resizer._target = null;
}, 1000);
return _target.getBoundingClientRect();
};
let updateResizerCursor = (angle) => {
if (angle != this.resizer.angle) {
let a = (angle + 7) % 15;
let d = (angle - a + 7) % 180;
let resizer = this.resizer;
resizer.angle = angle;
resizer.ne_resizer.className = resizer.ne_resizer.className.replace(/ cursor_(\d)+d/gi, '') + ' cursor_' + ((d + 45) % 180) + 'd';
resizer.sw_resizer.className = resizer.sw_resizer.className.replace(/ cursor_(\d)+d/gi, '') + ' cursor_' + ((d + 45) % 180) + 'd';
resizer.nw_resizer.className = resizer.nw_resizer.className.replace(/ cursor_(\d)+d/gi, '') + ' cursor_' + ((d + 135) % 180) + 'd';
resizer.se_resizer.className = resizer.se_resizer.className.replace(/ cursor_(\d)+d/gi, '') + ' cursor_' + ((d + 135) % 180) + 'd';
resizer.n_resizer.className = resizer.n_resizer.className.replace(/ cursor_(\d)+d/gi, '') + ' cursor_' + ((d + 0) % 180) + 'd';
resizer.s_resizer.className = resizer.s_resizer.className.replace(/ cursor_(\d)+d/gi, '') + ' cursor_' + ((d + 0) % 180) + 'd';
resizer.w_resizer.className = resizer.w_resizer.className.replace(/ cursor_(\d)+d/gi, '') + ' cursor_' + ((d + 90) % 180) + 'd';
resizer.e_resizer.className = resizer.e_resizer.className.replace(/ cursor_(\d)+d/gi, '') + ' cursor_' + ((d + 90) % 180) + 'd';
}
};
if (!resizer.visibile) {
let resizers = target.options && target.options.resizers;
if (resizers) {
resizer.nw_resizer.style.display = resizers.nw ? '' : 'none';
resizer.ne_resizer.style.display = resizers.ne ? '' : 'none';
resizer.sw_resizer.style.display = resizers.sw ? '' : 'none';
resizer.se_resizer.style.display = resizers.se ? '' : 'none';
resizer.n_resizer.style.display = resizers.n ? '' : 'none';
resizer.e_resizer.style.display = resizers.e ? '' : 'none';
resizer.s_resizer.style.display = resizers.s ? '' : 'none';
resizer.w_resizer.style.display = resizers.w ? '' : 'none';
resizer.r_resizer.style.display = resizers.r ? '' : 'none';
}
}
let bBox = getBorderBox(target);
resizer.style.left = parseInt(bBox.left + window.scrollX) + 'px';
resizer.style.top = parseInt(bBox.top + window.scrollY) + 'px';
resizer.style.width = parseInt(bBox.width + 1) + 'px';
resizer.style.height = parseInt(bBox.height + 1) + 'px';
resizer.style.display = '';
resizer.style.transform = 'rotate(' + (target.angle || 0) + 'deg)';
resizer.visibile = true;
resizer.target = target;
updateResizerCursor(target.angle);
return bBox;
}
return target.getBoundingClientRect();
},
hide() {
this.target = null;
this.resizer.style.display = 'none';
this.resizer.visibile = false;
},
remove(target) {
if (target && target.handleMousedown) {
target.removeEventListener('mousedown', target.handleMousedown);
target.removeEventListener('touchstart', target.handleMousedown);
target.removeEventListener('mouseenter', target.handleMouseEnter);
target.removeEventListener('mouseleave', target.handleMouseLeave);
target.options && (target.options = null);
target.resizer = null;
this.hide();
}
},
};
// export default resizer;