JSFiddle - React, Tailwind, and code Playground
by joshmoto
HTML
<div class="area">
<img src="https://dragonballsuper-france.fr/wp-content/uploads/2017/10/DIHQF2OXoAAJi4n-660x330.jpg" alt="" />
<div class="rect">
<div class="exclusion-x"></div>
<div class="exclusion-y"></div>
</div>
</div>
CSS
.area IMG {
display: block;
max-width: 100%;
pointer-events: none;
user-select: none;
}
.area {
overflow: hidden;
position: relative;
}
.area:hover {
cursor: crosshair;
}
.area .rect {
opacity: 0;
transition: all 0s ease;
position: absolute;
border: 1px solid red;
z-index: 1;
}
.area.draw .rect,
.area.drawn .rect {
opacity: 1;
}
.area .rect .exclusion-x::before,
.area .rect .exclusion-x::after,
.area .rect .exclusion-y::before,
.area .rect .exclusion-y::after {
position: absolute;
content: '';
display: block;
background: #000;
opacity: .75;
z-index: -1;
pointer-events: none;
user-select: none;
}
.area .rect .exclusion-x::before {
bottom: calc(100% + 1px);
left: 50%;
transform: translateX(-50%);
height: 200vh;
width: 200vw;
}
.area .rect .exclusion-x::after {
top: calc(100% + 1px);
left: 50%;
transform: translateX(-50%);
height: 200vh;
width: 200vw;
}
.area .rect .exclusion-y::before {
right: calc(100% + 1px);
top: -1px;
bottom: -1px;
width: 200vw;
}
.area .rect .exclusion-y::after {
left: calc(100% + 1px);
top: -1px;
bottom: -1px;
width: 200vw;
}
JavaScript
let img = {};
let position = {};
function imgMatrix() {
let $img = $('IMG', '.area');
let offset = $img.offset();
img.width = $img.outerWidth();
img.height = $img.outerHeight();
img.offsetX = offset.left - $(document).scrollLeft();
img.offsetY = offset.top - $(document).scrollTop();
console.log(img);
}
$(document).on('mousemove', '.area', function(e) {
console.clear();
imgMatrix();
console.log(e.pageX, e.pageY);
if ($(this).hasClass('draw')) {
position.right = 100 - ((100 / img.width) * (e.pageX - img.offsetX));
position.bottom = 100 - ((100 / img.height) * (e.pageY - img.offsetY));
console.log(position, 100 - position.right);
if ((100 - position.right) < position.left) {
$('.rect', this).css({
left: (100 - position.right) + '%',
right: (100 - position.left) + '%'
});
} else {
$('.rect', this).css({
right: position.right + '%',
left: position.left + '%'
});
}
if ((100 - position.bottom) < position.top) {
$('.rect', this).css({
top: (100 - position.bottom) + '%',
bottom: (100 - position.top) + '%'
});
} else {
$('.rect', this).css({
bottom: position.bottom + '%',
top: position.top + '%',
});
}
}
});
$(document).on('mousedown', '.area', function(e) {
console.clear();
imgMatrix();
console.log(e.pageX, e.pageY);
position.left = (100 / img.width) * (e.pageX - img.offsetX);
position.top = (100 / img.height) * (e.pageY - img.offsetY);
$('.rect', this).css({
left: position.left + '%',
top: position.top + '%'
});
$(this).addClass('draw');
});
$(document).on('mouseup', '.area', function(e) {
$(this).addClass('drawn').removeClass('draw');
console.clear();
imgMatrix();
console.log(e.pageX, e.pageY);
});
$(window).on('resize', function(e) {
console.clear();
imageMatrix();
});