JSFiddle - React, Tailwind, and code Playground

by hiral

HTML

<div id="container" class="inline relative">
    <div id="preview">
        <img class="preview-image relative block" height="360" width="640" src="http://i.imgur.com/tBkSTZC.jpg" />
    </div>
    <div id="cropper" class="absolute">
        <div class="relative full-height full-width">
            <div class="inline resize-container top-left absolute" data-resize="tl">
                <div class="resize inline"></div>
            </div>
            <div class="inline resize-container top-right absolute" data-resize="tr"> <span class="resize inline"></span>

            </div>
            <div class="inline resize-container bottom-left absolute" data-resize="bl"> <span class="resize inline"></span>

            </div>
            <div class="inline resize-container bottom-right absolute" data-resize="br"> <span class="resize inline"></span>

            </div>
        </div>
    </div>
</div>
 <h2>Preview</h2>

<canvas class="canvas block"></canvas>

CSS

* {
    margin:0;
    padding:0;
}
.absolute {
    position:absolute;
}
.relative {
    position:relative;
}
.block {
    display:block;
}
.inline {
    display:inline-block;
}
.inline.hide, .hide {
    display:none;
}
.full-height {
    height:100%;
}
.full-width {
    width:100%;
}
#container {
    overflow:hidden;
}
#cropper {
    height:100px;
    width:200px;
    opacity:0.9;
    top:0px;
    left:0px;
    box-shadow:0 0 0 1px #CCC, 0 0 0 1000px rgba(0, 0, 0, 0.7);
    cursor:move;
}
#drop {
    height:100px;
}
.resize {
    height:10px;
    width:10px;
    border:1px solid #333;
    background-color:white;
    margin-bottom:2px;
}
.resize-container {
    padding:15px;
    height:12px;
    width:12px;
    margin-top:-22px;
    z-index:1;
}
.resize-container.bottom-left {
    cursor:sw-resize;
}
.resize-container.bottom-right {
    cursor:se-resize;
}
.resize-container.top-left {
    cursor:nw-resize;
}
.resize-container.top-right {
    cursor:ne-resize;
}
.resize-container.bottom-right, .resize-container.top-right {
    right:0;
}
.resize-container.bottom-left, .resize-container.bottom-right {
    bottom:-22px;
}
.resize-container.bottom-left, .resize-container.top-left {
    margin-left:-22px;
}
.resize-container.bottom-right, .resize-container.top-right {
    margin-right:-22px;
}

JavaScript

var cropper = "#cropper",
    cropw = 200,
    croph = 100,
    resize = ".resize-container";
image_events(cropw, croph);
$(".preview-image").load(function () {    
    show_cropped_img();
});
function show_cropped_img(swidth, sheight) {
    var canvas = $("canvas")[0],
        x, y,
        position = $(cropper).position();
    x = position.left;
    y = position.top;
    canvas.width = cropw;
    canvas.height = croph;
    if (!swidth) {
        swidth = cropw;
    }
    if (!sheight) {
        sheight = croph;
    }
    var ctx = canvas.getContext("2d");
    ctx.drawImage($("#preview").find(".preview-image")[0], x, y, swidth, sheight, 0, 0, cropw, croph);
    $(".canvas").removeClass("hide");
}
function image_events(width, height) {
    crop_events();
    resize_events();
    function crop_events() {
        $(cropper).on("mousedown", function () {
            $(this).on("mousemove", start_move);
        });
        $(cropper).on("mouseup", leave);
        $(cropper).on("mouseleave", leave);
        function start_move(event) {
            var x = event.pageX - width / 2,
                maxw = $("#preview").width() - width,
                maxh = $("#preview").height() - height,
                swidth = $(cropper).width(),
                sheight = $(cropper).height();
            if (x > maxw) {
                x = maxw;
            }
            if (y > maxh) {
                y = maxh;
            }
            if (x < 0) {
                x = 0;
            }
            if (y < 0) {
                y = 0;
            }
            $(cropper).offset({
                left: x,
                top: y
            });
            show_cropped_img(swidth, sheight);
        }
        function leave() {
            $(cropper).off("mousemove", start_move);
        }
    }
    function resize_events() {
        $(resize).mousedown(function () {
            $(this).on("mousemove", start_resize);
        });
        $(resize).on("mouseup", leave);
       ...