JSFiddle - React, Tailwind, and code Playground
HTML
<link rel="stylesheet" href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/themes/redmond/jquery-ui.css">
<div class="stage">
<div class="photoCrop" style="width: 400px; height: 479px">
<div class="bg"></div>
<div class="wrapper">
<img src="http://tuxpaint.org/stamps/stamps/animals/birds/cartoon/tux.png" />
<div class="viewport">
<div class="handle ui-resizable-handle ui-resizable-se"></div>
</div>
</div>
</div>
</div>
CSS
.stage {
display: inline-block;
}
.stage, .photoCrop img {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAK3RFWHRDcmVhdGlvbiBUaW1lAFR1ZSA1IE5vdiAyMDEzIDEzOjA5OjA2IC0wNzAwFSsrggAAAAd0SU1FB90LBRQJEhsupd8AAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAEZ0FNQQAAsY8L/GEFAAAAPElEQVR42u3PsQ0AMAgDwZDFvDpMBjM4okjxXxudiMw8TpKs/bXWDwEAAAAAbBTdbR1U1V8fAAAAAABsNP0yCHyWlMhVAAAAAElFTkSuQmCC);
}
.photoCrop {
position: relative;
background-image: url('http://tuxpaint.org/stamps/stamps/animals/birds/cartoon/tux.png');
}
.photoCrop > *, .wrapper > *, .wrapper .handle {
position: absolute;
top: 0;
left: 0;
}
.photoCrop > * {
width: 100%;
height: 100%;
}
.photoCrop img {
clip: rect(0px 328px 256px 72px);
}
.photoCrop .bg {
background-color: #000;
opacity: .6;
}
.viewport {
width: 256px;
height: 256px;
top: 0px;
left: 72px;
cursor: move;
}
.viewport > .handle {
top: auto;
left: auto;
right: -5px;
bottom: -5px;
width: 10px;
height: 10px;
background-color: #D8DFEA;
opacity: .5;
}
JavaScript
var $image = $(".viewport").resizable({
containment: "parent",
handles: {
se: ".handle"
},
minWidth: 50,
minHeight: 50,
aspectRatio: true,
resize: function (e, ui) {
var parentW = $(this).parent().width(),
parentH = $(this).parent().height(),
left = ui.position.left,
top = ui.position.top,
size = ui.size.width;
if (parentW <= left + size) {
size = parentW - left;
}
if (parentH <= top + size) {
size = parentH - top;
}
$image.css("clip", "rect(" + top + "px " + (left + size) + "px " + (top + size) + "px " + left + "px)");
},
}).draggable({
containment: "parent",
drag: function (e, ui) {
var newUI = $.extend({}, ui, {
size: {
width: $(this).width(),
height: $(this).height()
}
});
$(this).resizable("option", "resize").call(this, e, newUI);
}
}).siblings();