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();



});