JSFiddle - React, Tailwind, and code Playground

HTML

<div id="loup">
    <img src="http://3.bp.blogspot.com/-Pv3UuU1VtIY/T7RFN54LKmI/AAAAAAAAFW8/AfVYysfr00U/s1600/paisaje-italia.jpg" />
</div>

CSS

#loup {
    position:relative
}
#loup .circle{
    position:absolute;
    height:180px;
    width:180px;
    border-radius:90px;
    box-shadow:-2px -3px 5px #000;
    background-repeat:no-repeat;
    display:none;
}
#loup img{
    position:absolute
}

#loup .layer{
    background:black;
    opacity:0.6;
    width:100%;
    height:100%
}

JavaScript

$(document).ready(function(){
    var obj = $("#loup"), img = obj.find("img")[0], 
        circle = $("<div>",{'class':'circle'}), layer = $("<div>",{'class':'layer'})
        
        function start(){
            var width = img.width, height = img.height
            obj.css({width:width,height:height,margin:'auto'})
            obj.append(layer)
            obj.hover(function(){
                circle.show(300)
            },function(){
                circle.hide(300)
            }).mousemove(function(e){
                var left = e.pageX, top = e.pageY, offset = obj.offset(), 
                    circleSize = [circle.width(),circle.height()],
                    topPos = top-offset.top-(circleSize[1]/2), 
                    leftPos = left-offset.left-(circleSize[0]/2)
                circle.css({
                    left:leftPos+"px",
                    top:topPos+"px",
                    backgroundPosition: -leftPos + "px "+ -topPos + "px"
                });
                if((leftPos > width || topPos > height 
                    || leftPos < -circleSize[0] || topPos < -circleSize[1])){
                    circle.hide()
                }
             })
            obj.append(circle.css({backgroundImage:'url('+img.src+')'}));
        }
        if(img.complete){
            start()
        }else{
            img.onload = start
        }
})