JSFiddle - React, Tailwind, and code Playground
by itsazzad
HTML
<svg width="400" height="400" transform="scale(1)">
<rect id="_svg_editor_background_" fill="#fafafa" width="100%" height="100%"></rect>
<g id="active_group" transform="">
<rect x="100" y="138" width="200" height="125" stroke-width="2" stroke="red" fill="transparent" class="active-control-border" pointer-events="none"></rect>
<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://eskipaper.com/images/berries-nature-winter-1.jpg" preserveAspectRatio="none" x="100" y="138.5" width="200px" class=""></image>
<circle cx="200" cy="200.5" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-center" style="null"></circle>
<circle cx="200" cy="118" r="6" fill="rgba(150, 243, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-rotator" style="cursor: crosshair;"></circle>
<circle cx="100" cy="138" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-nw" style="cursor: nw-resize;"></circle>
<circle cx="200" cy="138" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-n" style="cursor: n-resize;"></circle>
<circle cx="300" cy="138" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-ne" style="cursor: ne-resize;"></circle>
<circle cx="300" cy="200.5" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-e" style="cursor: e-resize;"></circle>
<circle cx="300" cy="263" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-se" style="cursor: se-resize;"></circle>
<circle cx="200" cy="263" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-s" style="cursor: s-resize;"></circle>
<circle cx="100" cy="263" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-sw" style="cursor:...
CSS
#console{
position:absolute;
bottom:10px;
left:10px;
}
.active-control-nw,
.active-control-ne,
.active-control-sw,
.active-control-se{display:none;}
JavaScript
//DRAGGING
$('image').mousedown(function(e){
if (!$(this).is('[class^=active-control-]') && !$(e.target).is('[class^=active-control-]')) {
var elem = this;
if ($(this).is('g#active_group')) {
elem = $(this).find(':not([class^=active-control-])').get(0);
}
var pageX0 = e.pageX;
var pageY0 = e.pageY;
var init_scale = {width: elem.getBBox().width, height: elem.getBBox().height};
var init_offset = {x: parseInt($(elem).attr('x')), y: parseInt($(elem).attr('y'))};
function handle_dragging(e) {
var x = init_offset.x + (e.pageX - pageX0);
var y = init_offset.y + (e.pageY - pageY0);
//change center of rotation to match new element center when dragging
var trans = transform2Array(elem);
if (!Object.values(trans).length) {
trans = transform2Array($(elem).parent());
}
var transform = "";
if (trans.rotate != undefined) {
var rot_cx = x + init_scale.width / 2;
var rot_cy = y + init_scale.height / 2;
transform += "rotate(" + trans.rotate[0] + "," + rot_cx + "," + rot_cy + ")";
}
$(elem).attr({x: x, y: y});
//fix bug rotate +90 drag rotate clear select& drag => rotate svg element !
if ($(elem).parent().is('g#active_group'))
$(elem).parent().attr({transform: transform});
updateControls($(elem));//update controls to match the new position
}
function handle_mouseup(e) {
$('body')
.off('mousemove', handle_dragging)
.off('mouseup', handle_mouseup);
}
$('body')
.on('mouseup', handle_mouseup)
.on('mousemove', handle_dragging);
}
});
//END OF DRAGGING
$('circle[class^=active-control-]').mousedown(function(md_e) {
var $control = $(this);
var $element = $('image:first');
var control_name = $(this).attr('class').replace('active-control-', '').trim();
var pageX0 = md_e.pageX;
var pageY0 = md_e.pageY;
var init_offset = {
x: $element.get(0).getBBox().x,
y: $element.get(0).getBBox().y
};
var init_scale = {
width: $element.get(0).getBBox().width,
height:...