const targets = []
const cleanXLine = () => {
const guideLineX = document.querySelector('.guide-line-x')
guideLineX.style.left = 0
guideLineX.style.top = 0
guideLineX.style.width = 0
guideLineX.style.height = 0
}
const cleanYLine = () => {
const guideLineY = document.querySelector('.guide-line-y')
guideLineY.style.left = 0
guideLineY.style.top = 0
guideLineY.style.width = 0
guideLineY.style.height = 0
}
const resetGuideLine = () => {
cleanXLine()
cleanYLine()
}
const handleStart = (event) => {
// get all interactive elements
targets.length = 0
const elements = document.querySelectorAll('.draggable')
elements.forEach((element) => {
const rect = element.getBoundingClientRect()
const { x, y, width, height } = rect
if (element === event.target) return
const actualX = x + window.scrollX
const actualY = y + window.scrollY
const range = 4
targets.push({
x: actualX,
range,
rect,
element,
})
targets.push({
x: actualX + width,
range,
rect,
element,
})
targets.push({
x: actualX + width / 2,
range,
rect,
element,
})
targets.push({
y: actualY,
range,
rect,
element,
})
targets.push({
y: actualY + height,
range,
rect,
element,
})
targets.push({
y: actualY + height / 2,
range,
rect,
element,
})
})
}
const drawGuideLine = (event) => {
const inRange = event.modifiers.length ? event.modifiers[0]?.inRange : false
if (inRange) {
const guideLineX = document.querySelector('.guide-line-x')
const guideLineY = document.querySelector('.guide-line-y')
const {
x: xModifier,
y: yModifier,
rect,
} = event.modifiers[0].target.source
const { x, y } = event.target.getBoundingClientRect()
if (xModifier) {
guideLineX.style.left = `${xModifier}px`
guideLineX.style.top = `${Math.min(rect.y, y)}px`
guideLineX.style.width = '1px'
guideLineX.style.height = `${Math.abs(rect.y - y)}px`
cleanYLine()
}
if (yModifier) {
console.log(rect.x - x)
guideLineY.style.left = `${Math.min(rect.x, x)}px`
guideLineY.style.top = `${yModifier - window.scrollY}px`
guideLineY.style.width = `${Math.abs(rect.x - x)}px`
guideLineY.style.height = '1px'
cleanXLine()
}
} else {
resetGuideLine()
}
}
interact('.draggable')
.draggable({
// enable inertial throwing
inertia: false,
// keep the element within the area of it's parent
modifiers: [interact.modifiers.snap({
targets: targets,
relativePoints: [
{ x: 0, y: 0 }, // snap relative to the element's top-left,
{ x: 0.5, y: 0.5 }, // to the center
{ x: 1, y: 1 }, // and to the bottom-right
],
}),
interact.modifiers.restrictRect({
restriction: 'parent',
endOnly: true
})
],
// enable autoScroll
autoScroll: true,
listeners: {
// call this function on every dragmove event
move: dragMoveListener,
start: handleStart,
// call this function on every dragend event
end (event) {
resetGuideLine()
}
}
})
function dragMoveListener (event) {
drawGuideLine(event)
var target = event.target
// keep the dragged position in the data-x/data-y attributes
var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy
// translate the element
target.style.transform = 'translate(' + x + 'px, ' + y + 'px)'
// update the posiion attributes
target.setAttribute('data-x', x)
target.setAttribute('data-y', y)
}
// this function is used later in the resizing and gesture demos
window.dragMoveListener = dragMoveListener
#canvas{
width: 100vw;
height: 100vh;
background: rgb(22, 197, 180);
}
.draggable {
background: rgb(71, 44, 113);
width: 60px;
height: 60px;
}
.draggable:nth-child(1){
translate: 20px 10px;
}
.draggable:nth-child(2){
translate: 50px 60px;
}
body {
display: grid;
place-items: center;
place-content: center;
height: 100%;
}
html{
height: 100%;
}
.guide-line {
pointer-events:none;
background:red;
position:fixed;
display: flex;
justify-items:space-between;
width: 0;
height:0;
left:0;
right:0;
}
.guide-line > span {
font-size: 9px;
line-height: 0;
color: red;
position: absolute;
}
.guide-line-x > span {
transform: translateX(-50%);
left: 50%;
}
.guide-line-y{
flex-direction:row;
}
.guide-line-x {
flex-direction:column;
}
.guide-line-y > span{
transform: translateY(-50%);
top: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.10.17/interact.min.js"></script>
<div id="canvas">
<div class="draggable" ></div>
<div class="draggable"> </div>
<div class="guide-line-y guide-line">
<span style="opacity:0" >x</span>
<span>x</span>
</div>
<div class="guide-line-x guide-line">
<span style="opacity:0">x</span>
<span>x</span>
</div>
</div>