JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://unpkg.com/interactjs@1.3.3/dist/interact.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div id="container">
<div id="rectangle">
</div>
<div id="selector">
<div class="pointers pointer1">
<div class="point"></div>
</div>
<div class="pointers pointer2">
<div class="point">
</div>
</div>
<div class="pointers pointer3">
<div class="point">
</div>
</div>
<div class="pointers pointer4">
<div class="point">
</div>
</div>
<div class="pointers pointer-north">
<div class="point">
</div>
</div>
<div class="pointers pointer-east">
<div class="point">
</div>
</div>
<div class="pointers pointer-south">
<div class="point">
</div>
</div>
<div class="pointers pointer-west">
<div class="point">
</div>
</div>
<span class="topline lines-resize" />
<span class="rightline lines-resize" />
<span class="botline lines-resize" />
<span class="leftline lines-resize" />
<div class="pointer-rotate pointer9" />
<div class="rotate-line" />
</div>
</div>
CSS
#container {
width: 500px;
height: 400px;
top: 0;
left: 0;
position: absolute;
background-color: #CCC;
}
#rectangle {
top: 50px;
left: 50px;
width: 120px;
height: 60px;
background-color: red;
position: absolute;
}
#selector {
display: inline-block;
position: absolute;
pointer-events: none;
z-index: 9999;
top: -1000px;
/*Not showing at start*/
}
#selector .pointers {
display: inline-block;
position: absolute;
z-index: 2;
width: 10px;
height: 10px;
pointer-events: all;
}
#selector .pointers .point {
width: 10px;
height: 10px;
background-color: #fff;
border: 2px solid rgba(0, 0, 0, 0.9);
border-radius: 50%;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
#selector .pointers.pointer1 {
top: -5px;
left: -5px;
}
#selector .pointers.pointer2 {
bottom: -5px;
left: -5px;
}
#selector .pointers.pointer3 {
top: -5px;
right: -5px;
}
#selector .pointers.pointer4 {
bottom: -5px;
right: -5px;
}
#selector .pointers.pointer-north {
top: -5px;
left: calc(50% - 5px);
}
#selector .pointers.pointer-south {
bottom: -5px;
left: calc(50% - 5px);
}
#selector .pointers.pointer-east {
right: -5px;
top: calc(50% - 5px);
}
#selector .pointers.pointer-west {
left: -5px;
top: calc(50% - 5px);
}
#selector .pointer-rotate {
border: 2px solid rgba(0, 0, 0, 0.9);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 50%;
cursor: rotate;
}
#selector .pointer9 {
bottom: -70px;
left: calc(50% - 11px);
display: inline-block;
width: 20px;
height: 20px;
background-color: #fff;
pointer-events: all;
position: absolute;
}
#selector .rotate-line {
border-left: 1px dashed #5f5f5f;
height: 40px;
position: absolute;
top: -40px;
left: calc(50% - 1px);
width: 1px;
}
JavaScript
interact('#rectangle').on('tap', event => {
console.log('Tap Box!');
event.stopPropagation();
const $rectangleCloned = $('#rectangle').clone();
const previousTransform = $rectangleCloned.css('transform');
$rectangleCloned.css('transform', 'none');
$rectangleCloned.css('opacity', '0');
$rectangleCloned.css('display', 'block');
$('#container').append($rectangleCloned);
const values = $rectangleCloned[0].getBoundingClientRect();
$('#selector').css('top', values.y);
$('#selector').css('left', values.x);
$('#selector').css('width', values.width);
$('#selector').css('height', values.height);
$('#selector').css('transform', previousTransform);
$rectangleCloned.remove();
return values;
});
interact('.pointer9').draggable({
max: 1,
onmove: event => {
const angleDeg =
Math.atan2(
centerRotate.posY - event.pageY,
centerRotate.posX - event.pageX
) *
180 /
Math.PI;
console.log(this.rotate);
const prevAngle = this.rotate - angleInitial;
const angle = parseInt(angleDeg) + prevAngle;
this.$rectangle.css({
transform: 'rotate(' + angle + 'deg)'
});
this.$selector.css({
transform: 'rotate(' + angle + 'deg)'
});
},
onstart: event => {
const data = event.interactable.getRect(event.target.parentNode);
this.centerRotate = {
posX: data.left + data.width / 2,
posY: data.top + data.height / 2
};
this.angleInitial =
Math.atan2(
centerRotate.posY - event.pageY,
centerRotate.posX - event.pageX
) *
180 /
Math.PI;
this.$rectangle = $('#rectangle');
this.$selector = $('#selector');
this.rotate = $rectangle.attr('angle') || 0;
},
onend: event => {
const $box = $('#selector');
const matrix = $box.css('transform');
const values = matrix
.split('(')[1]
.split(')')[0]
.split(',');
var a = values[0];
var b = values[1];
var angle =...