JSFiddle - React, Tailwind, and code Playground

by Lazaro Contreras

HTML

<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
<defs>
  <mask id="hole">
    <rect width="100%" height="100%" fill="white"/>
    <rect class="box" x="0" y="0" width="0" height="0" style="fill:black;stroke:black;stroke-width:0;fill-opacity:1;stroke-opacity:1;stroke-dasharray:25"/>
  </mask>
</defs>
<rect class="outer" width="100%" height="100%" fill="rgba(0,0,0,0.6)" mask="url(#hole)"/>
<rect class="box inner" x="0" y="0" width="0" height="0" style="fill:black;stroke:var(--white);stroke-width:2;fill-opacity:0;stroke-opacity:1;stroke-dasharray:25"/>
</svg>


<div class="hit2"></div>
<div class="hit3"></div>
<div class="hit4"></div>
<div class="hit5"></div>
<div class="hit6"></div>
<div class="hit7"></div>
<div class="hit8"></div>
<div class="hit1"></div>


<img height="100%" src="https://cdna.artstation.com/p/assets/images/images/017/604/714/large/travis-m-couch-mountaintopweb.jpg?1556656231">

CSS

.box {
  stroke-dasharray: 100;
  animation: dash 20s linear infinite;
}

@keyframes dash {
  to {
    stroke-dashoffset: -1000;
  }
}

:root {
  --white: rgba(255, 255, 255, 0.8);
}

svg {
  position: absolute;
  width: 100%;
  height: 100%;
}

[class^="hit"]{
  top: -10px;
  left: -10px;
  position: absolute;
  width: 10px;
  height: 10px;
  background: var(--white);
  user-select: none;
}

.hit1, .hit2 {
  cursor: nwse-resize;
}

.hit3, .hit4 {
  cursor: nesw-resize;
}

.hit5, .hit6 {
  cursor: ns-resize;
}

.hit7, .hit8 {
  cursor: ew-resize;
}

html,
body {
  margin: 0;
  padding: 0;
  background: blue;
}

JavaScript

var boxs = document.querySelectorAll(".box");

var inner = document.querySelector('.inner'),
  outer = document.querySelector('.outer');
  
var hit1 = document.querySelector('.hit1'),
  hit2 = document.querySelector('.hit2'),
  hit3 = document.querySelector('.hit3'),
  hit4 = document.querySelector('.hit4'),
  hit5 = document.querySelector('.hit5'),
  hit6 = document.querySelector('.hit6'),
  hit7 = document.querySelector('.hit7'),
  hit8 = document.querySelector('.hit8');

var hits = document.querySelectorAll('[class^="hit"]');

var mouseY = 0, mouseX = 0, element = null, minBox = 0, hitSize = 10;

hits.forEach((h) => {
  h.addEventListener('mousedown', function(e) {
    mouseY = e.pageY - e.currentTarget.offsetTop;
    mouseX = e.pageX - e.currentTarget.offsetLeft;
    element = (element == null)? e.currentTarget : element;
    window.addEventListener('mousemove', move);
  })
});

outer.addEventListener('mousedown', function(e) {
		hit1.style.top = e.pageY + 'px'
    hit1.style.left = e.pageX + 'px'
		hit2.style.top = e.pageY + 'px'
    hit2.style.left = e.pageX + 'px'
    hit3.style.top = e.pageY + 'px'
    hit3.style.left = e.pageX + 'px'
    hit4.style.top = e.pageY + 'px'
    hit4.style.left = e.pageX + 'px'
    hit5.style.top = e.pageY + 'px'
    hit5.style.left = e.pageX + 'px'
    hit6.style.top = e.pageY + 'px'
    hit6.style.left = e.pageX + 'px'
    hit7.style.top = e.pageY + 'px'
    hit7.style.left = e.pageX + 'px'
    hit8.style.top = e.pageY + 'px'
    hit8.style.left = e.pageX + 'px'
    element = hit1;
    window.addEventListener('mousemove', move);
})

window.addEventListener('mouseup', function() {
	element = null;
  window.removeEventListener('mousemove', move);
});

function move(e) {

  if ((e.pageY - mouseY) > 0) {
    if (element == hit1 || element == hit3 || element == hit5) {
      if (((e.pageY - mouseY) - hit2.offsetTop - hitSize) > minBox) {
        hit1.style.top = e.pageY - mouseY + 'px';
        hit3.style.top = e.pageY - mouseY +...