JSFiddle - React, Tailwind, and code Playground
by BurpmanJunior
HTML
<img src="http://i.imgur.com/bBoJbVe.jpg" data-zoom />
<img src="http://i.imgur.com/FHtxfuG.jpg" data-zoom />
SCSS
.zoom-wrap{
position: relative;
box-sizing: border-box;
img{
display: block;
}
&.zoom-init{
cursor: none;
}
}
.zoom-loupe{
transform: scale(0) translateX(-50%) translateY(-50%);
transform-origin: top left;
width: 40vmin;
height: 40vmin;
max-width: 200px;
max-height: 200px;
position: absolute;
border-radius: 50%;
box-sizing: border-box;
border: 2px solid rgba(255, 255, 255, 0.5);
background-color: rgba(200, 200, 200, 0.3);
box-shadow: 0 5px 10px -5px rgba(0, 0, 0, 0.5),
inset 0 5px 0px 5px rgba(255, 255, 255, 0.1);
opacity: 0;
transition: transform 300ms, opacity 300ms;
pointer-events: none;
z-index: 2;
overflow: hidden;
&:after{
content: '';
display: block;
position: absolute;
top: -20%;
left: -20%;
right: -20%;
bottom: 20%;
background-color: rgba(255, 255, 255, 0.08);
border-radius: 50%;
box-shadow: inset 0 75px 50px rgba(255, 255, 255, 0.3);
}
&.active{
transform: scale(1) translateX(-50%) translateY(-50%);
opacity: 1;
}
&.hide{
display: none;
}
top: 0;
left: 0;
}
img{
max-width: 100%;
}
body{
overflow-x: hidden;
}
JavaScript
/**
* Zoom Loupe viewer
*/
var zoomLoupe = {
init: function(){
this.wrapElems();
this.bindEvents();
},
wrapElems: function(){
var elems = document.querySelectorAll('[data-zoom]');
for(var i = 0; i < elems.length; i++){
var zoom = elems[i].getAttribute('data-zoom');
if(zoom === ''){ zoom = elems[i].src; }
var img = elems[i].outerHTML.replace(/\sdata\-zoom[^\s\/\>]*/ig, '');
var o = document.createElement('div');
o.className = 'zoom-wrap';
o.innerHTML = img + '<div class="zoom-loupe" style="background-image: url(' + zoom + ');"></div>';
elems[i].parentNode.insertBefore(o, elems[i]);
elems[i].parentNode.removeChild(elems[i]);
}
},
bindEvents: function(){
var _z = zoomLoupe;
var elems = document.querySelectorAll('.zoom-wrap:not(.zoom-init)');
for(var i = 0; i < elems.length; i++){
var elem = elems[i];
var zoom = elem.getAttribute('data-zoom-level');
elem.className = elem.className + ' zoom-init';
elem.addEventListener('mousemove', function(e){
_z.calcPos(this, e);
});
elem.addEventListener('mouseenter', function(e){
_z.openLoupe(this, e);
});
elem.addEventListener('mouseout', function(e){
_z.closeLoupe(this, e);
});
}
},
calcPos: function(elem, e){
var loupe = elem.getElementsByClassName('zoom-loupe')[0];
var rect = elem.getBoundingClientRect();
var offsets = {
x: (e.offsetX / rect.width) * 100,
y: (e.offsetY / rect.height) * 100
}
loupe.style.left = offsets.x + '%';
loupe.style.top = offsets.y + '%';
loupe.style.backgroundPosition = offsets.x + '% ' + offsets.y + '%';
},
openLoupe: function(elem, e){
var loupe = ...