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 div */
.area {
  overflow: hidden;
  position: relative;
  margin-bottom: 8px;
}

/* area div hover cursor */
.area:hover {
  cursor: crosshair;
}

/* img tag in area div */
.area IMG {
  display: block;
  width: 100%;
  pointer-events: none;
  user-select: none;
}

/* rectangle div in area div */
.area .rect {
  opacity: 0;
  transition: all 0s ease;
  position: absolute;
  border: 1px solid red;
  z-index: 1;
  pointer-events: none;
  user-select: none;
}

/* rectangle div css when in draw or drawn mode */
.area.draw .rect,
.area.drawn .rect {
  opacity: 1;
  pointer-events: initial;
  user-select: initial;
}

/* below css is for fun rendering outer exclusion area of drawn rectangle div with a opaque overlay */

/* rectange exclusing pseudo elems base css */
.area.drawn .rect .exclusion-x::before,
.area.drawn .rect .exclusion-x::after,
.area.drawn .rect .exclusion-y::before,
.area.drawn .rect .exclusion-y::after {
  position: absolute;
  content: '';
  display: block;
  background: #000;
  opacity: .75;
  z-index: -1;
  pointer-events: none;
  user-select: none;
}

/* rectange outer opaque x above css */
.area.drawn .rect .exclusion-x::before {
  bottom: calc(100% + 1px);
  left: 50%;
  transform: translateX(-50%);
  height: 200vh;
  width: 200vw;
}

/* rectange outer opaque x below css */
.area.drawn .rect .exclusion-x::after {
  top: calc(100% + 1px);
  left: 50%;
  transform: translateX(-50%);
  height: 200vh;
  width: 200vw;
}

/* rectange outer opaque y left css */
.area.drawn .rect .exclusion-y::before {
  right: calc(100% + 1px);
  top: -1px;
  bottom: -1px;
  width: 200vw;
}

/* rectange outer opaque y right css */
.area.drawn .rect .exclusion-y::after {
  left: calc(100% + 1px);
  top: -1px;
  bottom: -1px;
  width: 200vw;
}

/* below css is for fun hovering and draging the rectangle */

/* rectangle div in area div */
.area .rect:hover {
  cursor: move;
}

JavaScript

// our updatable variable objects to use globally
let img = {};
let rect = {};
let position = {};
let drag = {};
let dragPoint = {};

// image matrix function to update img object variable
function imgMatrix() {

  // our image object inside area
  let $img = $('IMG', '.area');

  // offset data of image
  let offset = $img.offset();

  // add/update object key data
  img.width = $img.outerWidth();
  img.height = $img.outerHeight();
  img.offsetX = offset.left - $(document).scrollLeft();
  img.offsetY = offset.top - $(document).scrollTop();

}

// position matrix function to update position object variable
function positionMatrix(e, type = false) {

  // if mousedown param is true... for use in 
  if (type === 'mousemove') {

    // set the top/left position object data with percentage position
    drag.top = (100 / img.height) * ((e.pageY - $(document).scrollTop()) - img.offsetY);
    drag.right = 100 - ((100 / img.width) * ((e.pageX - $(document).scrollLeft()) - img.offsetX));
    drag.bottom = 100 - ((100 / img.height) * ((e.pageY - $(document).scrollTop()) - img.offsetY));
    drag.left = (100 / img.width) * ((e.pageX - $(document).scrollLeft()) - img.offsetX);

 
    position.top = drag.top - dragPoint.top;
    position.left = drag.left - dragPoint.left;
    position.bottom = drag.bottom - dragPoint.bottom;
    position.right = drag.right - dragPoint.right;
    
    //console.log(position);

  } else {

    // if mousedown param is true... for use in 
    if (type === 'mousedown') {

      // set the top/left position object data with percentage position
      position.top = (100 / img.height) * ((e.pageY - $(document).scrollTop()) - img.offsetY);
      position.left = (100 / img.width) * ((e.pageX - $(document).scrollLeft()) - img.offsetX);

    }

    // set the right/bottom position object data with percentage position
    position.right = 100 - ((100 / img.width) * ((e.pageX - $(document).scrollLeft()) - img.offsetX));
    position.bottom = 100 - ((100 /...