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="28" y="28" width="150" height="150" style="fill:black;stroke:black;stroke-width:2;fill-opacity:1;stroke-opacity:1;stroke-dasharray:10"/>
</mask>
</defs>
<rect class="box" x="28" y="28" width="150" height="150" style="fill:black;stroke:black;stroke-width:2;fill-opacity:0;stroke-opacity:1;stroke-dasharray:10"/>
<rect width="100%" height="100%" fill="rgba(0,0,0,0.5)" mask="url(#hole)"/>
</svg>
<div class="obj2 draggable"></div>
<div class="obj draggable"></div>
<img height="100%" src="https://cdnb.artstation.com/p/assets/images/images/017/179/293/large/amir-zand-sample.jpg?1554933668">
CSS
.box {
stroke-dasharray: 100;
animation: dash 20s linear infinite;
}
@keyframes dash {
to {
stroke-dashoffset: -1000;
}
}
.draggable {
cursor: grab;
}
.draggable:active {
cursor: grabbing;
}
:root {
--white: rgba(0, 0, 0, 0.9);
}
svg {
position: absolute;
width: 100%;
height: 100%;
}
.obj,
.obj2 {
position: absolute;
width: 0;
height: 0;
border: 10px solid transparent;
user-select: none;
}
.obj {
top: 159px;
left: 159px;
border-right: 10px solid var(--white);
border-bottom: 10px solid var(--white);
}
.obj2 {
top: 27px;
left: 27px;
border-left: 10px solid var(--white);
border-top: 10px solid var(--white);
}
html,
body {
margin: 0;
padding: 0;
background: blue;
}
JavaScript
var boxs = document.querySelectorAll(".box");
var obj = document.querySelector('.obj');
var obj2 = document.querySelector('.obj2');
var mouseY, mouseX, element;
obj.addEventListener('mousedown', function(e) {
mouseY = e.pageY - obj.offsetTop;
mouseX = e.pageX - obj.offsetLeft;
element = e.currentTarget;
window.addEventListener('mousemove', move);
});
obj2.addEventListener('mousedown', function(e) {
mouseY = e.pageY - obj2.offsetTop;
mouseX = e.pageX - obj2.offsetLeft;
element = e.currentTarget;
window.addEventListener('mousemove', move);
});
window.addEventListener('mouseup', function() {
window.removeEventListener('mousemove', move);
});
function move(e) {
if ((e.pageY - mouseY) > 0) {
if (element == obj) {
if (((e.pageY - mouseY) - obj2.offsetTop + 18) > 50) {
element.style.top = e.pageY - mouseY + 'px';
}
} else {
if ((obj.offsetTop - (e.pageY - mouseY) + 18) > 50) {
element.style.top = e.pageY - mouseY + 'px';
}
}
}
if ((e.pageX - mouseX) > 0) {
if (element == obj) {
if (((e.pageX - mouseX) - obj2.offsetLeft + 18) > 50) {
element.style.left = e.pageX - mouseX + 'px';
}
} else {
if ((obj.offsetLeft - (e.pageX - mouseX) + 18) > 50) {
element.style.left = e.pageX - mouseX + 'px';
}
}
}
boxs.forEach((box) => {
box.setAttribute("width", obj.offsetLeft - obj2.offsetLeft + 18);
box.setAttribute("height", obj.offsetTop - obj2.offsetTop + 18);
box.setAttribute("x", obj2.offsetLeft + 1);
box.setAttribute("y", obj2.offsetTop + 1);
});
}