JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/themes/base/jquery-ui.css">
<!--<select id="EditingScale">
<option value="0.5">50%</option>
<option value="1" selected="true">100%</option>
<option value="1.5">150%</option>
</select>
-->
<div id="wrap-outer">
<div id="wrap-inner">
<div class="elements">
<div class='element' style="width:200px;transform: translate3d(100px, 80px ,0px) rotate(30deg);">
<div class="inner">sss ss I'mfdgfdg <span style="font-size:40px;">sadfsadsa</span> sjdsaidj sdk dasd k sadopskaf kpsoadk ijfdk jod sadsassads</div>
</div>
<div class='element text' style="width:200px;transform: translate3d(100px, 80px ,0px) rotate(30deg);">
<div class="inner-text">sss ss I'mfdgfdg <span style="font-size:40px;">sadfsadsa</span> sjdsaidj sdk dasd k sadopskaf kpsoadk ijfdk jod sadsassads</div>
</div>
<div class='element text' style="width:300px;transform: translate3d(100px, 340px ,0px) rotate(0deg)">
<div class="inner-text">sss ss I'mfdgf sjdsaidj sdk dasd k sadopskaf kpsoadk ijfdk jod sadsassads</div>
</div>
</div>
<div id="handles_manager" style="transform: translate3d(100px, 80px ,0px) rotate(30deg);">
<!-- IMAGE, SVG HANDLES -->
<div class="ui-resizable-handle ui-resizable-ne" id="negrip"></div>
<div class="ui-resizable-handle ui-resizable-nw" id="nwgrip"></div>
<div class="ui-resizable-handle ui-resizable-se" id="segrip"></div>
<div class="ui-resizable-handle ui-resizable-sw" id="swgrip"></div>
<!-- TEXT HANDLES -->
<div class="ui-resizable-handle ui-resizable-e" id="egrip"></div>
<div class="ui-resizable-handle ui-resizable-w" id="wgrip"></div>
<!-- Rotable -->
<div class="ui-rotable-handle ui-rotable-s" id="srgrip"></div>
</div>
</div>
</div>
CSS
#wrap-outer {
padding-top:30px;
}
#wrap-inner {
position: absolute;
}
.elements {
position: absolute;
overflow: hidden;
border: 3px solid #ebeced;
background-color: #fff;
width: 500px;
height: 500px;
border: 1px solid blue;
}
.elements .element:hover {
cursor: pointer;
}
.element {
min-height: 30px;
position: absolute;
}
.element .inner-text {
word-break: break-all;
}
.elements .text {
z-index: 9;
}
#nwgrip,
#negrip,
#swgrip,
#segrip,
#egrip,
#wgrip,
#srgrip {
width: 10px;
height: 10px;
background-color: #ffffff;
border: 1px solid #000000;
position: absolute;
cursor: pointer;
}
#srgrip {
bottom: -30px;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
}
#wgrip {
left: -7px;
top: 50%;
}
#egrip {
right: -7px;
top: 50%;
}
#nwgrip {
left: -5px;
top: -5px;
}
#negrip {
top: -5px;
right: -5px;
}
#swgrip {
bottom: -5px;
left: -5px;
}
#segrip {
bottom: -5px;
right: -5px;
}
#handles_manager {
z-index: 1;
min-height: 5px;
visibility: hidden;
padding: 5px 10px;
border: 2px dotted #ccc;
position: absolute;
}
.elements .element,
.elements .inner-text {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
JavaScript
/*
** Scalable : stack[JQuery, Javascript]
** Scalable events : onchange
*/
/*
var selectScale = document.getElementById('EditingScale');
selectScale.onchange = getSelectedScale;
function getSelectedScale(e) {
$("#wrap-inner").css({
'transform':'scale(' + this.value + ', ' + this.value + ')',
});
}
*/
/*
** Draggable : stack[JQuery, Javascript]
** Draggable events : mousedown, mousemove, mouseup
*/
$('.text').on("mousedown", function(me) {
var move = $(this);
position = move.position();
// Keeps Last Data
var lastOffset = move.data('lastTransform');
var lastOffsetX = lastOffset ? lastOffset.dx : position.left;
var lastOffsetY = lastOffset ? lastOffset.dy : position.top;
var startX = me.pageX - lastOffsetX;
var startY = me.pageY - lastOffsetY;
// --------------------- //
// Get div rotation angle
var angle = elementAngle(this);
// --------------------- //
$('#handles_manager').css({
'left':'0px',
});
// --------------------- //
// Onmousedown + onmousemove (being dragged)
$(document).on("mousemove", function(e) {
var newDx = e.pageX - startX;
var newDy = e.pageY - startY;
move.css(
'transform', 'translate3d(' + newDx + 'px, ' + newDy + 'px, 0px) rotate(' + angle + 'deg)',
);
$('#handles_manager').css({
'transform': 'translate3d(' + (newDx - 13) + 'px, ' + (newDy - 4) + 'px, 0px) rotate(' + angle + 'deg)',
'left':'0px',
});
// we need to save last made offset
move.data('lastTransform', {
dx: newDx,
dy: newDy
});
});
});
$(document).on("mouseup", function() {
$(this).off("mousemove");
$(this).off("resize");
});
/* --------------------------------------------------------------------- */
/*
** Resizable : stack[JQuery, JQuery UI, JQuery CSS, Javascript]
** Resizable events : mousedown (count as click), resizable
*/
$('#handles_manager').resizable({
handles: {
'ne': '#negrip',
'se': '#segrip',
'sw': '#swgrip',
...