Reputation: 75864
I want to restrict the pink boxes to not be draggable outside the parent container:
<!doctype html>
<html lang="en">
<head>
<title>arrows</title>
<style>
* {
box-sizing: border-box;
}
#draw {
position: relative;
width: 800px;
height: 800px;
border: 1px solid black;
}
#draw > div {
width: 10rem;
height: 10rem;
border: 1px solid black;
background-color: violet;
}
#box1 {
position: absolute;
top: 100px;
left: 100px;
}
#box2 {
position: absolute;
top: 400px;
left: 400px;
}
</style>
<script type="module">
import { getArrow, getBoxToBoxArrow } from "https://cdn.esm.sh/v58/[email protected]/es2021/curved-arrows.js";
const el1 = document.getElementById('box1');
const el2 = document.getElementById('box2');
function Arrow() {
const pos1 = { x: el1.offsetLeft, y: el1.offsetTop, w: el1.clientWidth, h: el1.clientHeight };
const pos2 = { x: el2.offsetLeft, y: el2.offsetTop, w: el2.clientWidth, h: el2.clientHeight };
console.log(pos1);
const p1 = { x: pos1.x, y: pos1.y, w: pos1.w, h: pos1.h };
const p2 = { x: pos2.x, y: pos2.y, w: pos2.w, h: pos2.h };
const arrowHeadSize = 10;
const color = 'black';
//const [sx, sy, c1x, c1y, c2x, c2y, ex, ey, ae] = getArrow(p1.x, p1.y, p2.x, p2.y, {
const [sx, sy, c1x, c1y, c2x, c2y, ex, ey, ae] = getBoxToBoxArrow(p1.x, p1.y, p1.w, p1.h, p2.x, p2.y, p2.w, p2.h, {
padEnd: arrowHeadSize,
});
return `
<svg
width="100%"
height="100%"
xmlns="http://www.w3.org/2000/svg">
<path
d=${`"M ${sx} ${sy} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${ex} ${ey}"`}
stroke="${color}"
strokeWidth="${(arrowHeadSize / 2) || 1}"
fill="none"
/>
<polygon
points="${`0,${-arrowHeadSize} ${arrowHeadSize *
2},0, 0,${arrowHeadSize}`}"
transform="${`translate(${ex}, ${ey}) rotate(${ae})`}"
fill="${color}"
/>
</svg>
`;
}
function draggable(el) {
el.addEventListener('mousedown', function(e) {
var offsetX = e.clientX - parseInt(window.getComputedStyle(this).left);
var offsetY = e.clientY - parseInt(window.getComputedStyle(this).top);
function mouseMoveHandler(e) {
el.style.top = (e.clientY - offsetY) + 'px';
el.style.left = (e.clientX - offsetX) + 'px';
const arrow = Arrow();
const draw = document.getElementById('draw');
const svg = draw.querySelector('svg');
draw.insertAdjacentHTML('afterbegin', arrow);
(svg && svg.remove());
}
function reset() {
window.removeEventListener('mousemove', mouseMoveHandler);
window.removeEventListener('mouseup', reset);
}
window.addEventListener('mousemove', mouseMoveHandler);
window.addEventListener('mouseup', reset);
});
}
function moveBox(el) {
}
function onLoad() {
const arrow = Arrow();
const draw = document.getElementById('draw');
draw.insertAdjacentHTML('afterbegin', arrow);
draggable(el1);
draggable(el2);
}
window.addEventListener('load', onLoad);
</script>
</head>
<body>
<div id="draw">
<div id="box1"></div>
<div id="box2"></div>
</div>
</body>
</html>
Demo: https://playground-snowy.vercel.app/arrows
https://codepen.io/chovy/pen/WNZZBJe
Upvotes: 1
Views: 1275
Reputation: 4194
When setting the position of the element, if the position is out of bounds on any side, set it to the max value of that side.
If the top value is less than the min of 0, set it to zero.
If the top value is more than the max of (container height - element height), set it to the max.
And so on...
function mouseMoveHandler(e) {
const draw = document.getElementById('draw');
let top = e.clientY - offsetY;
let left = e.clientX - offsetX;
if (top < 0) top = 0;
if (left < 0) left = 0;
if (top > draw.clientHeight - el.clientHeight) top = draw.clientHeight - el.clientHeight;
if (left > draw.clientWidth - el.clientWidth) left = draw.clientWidth - el.clientWidth;
el.style.top = top + 'px';
el.style.left = left + 'px';
const arrow = Arrow();
const svg = draw.querySelector('svg');
draw.insertAdjacentHTML('afterbegin', arrow);
(svg && svg.remove());
}
Upvotes: 2
Reputation: 57
You can update inside of mouseMoverHandler function like this.
let newTop = (e.clientY - offsetY);
if (newTop < 0) {
newTop = 0;
}
if (newTop + 160 > 800) {
newTop = newTop - (newTop + 160 - 800);
}
let newLeft = (e.clientX - offsetX);
if (newLeft < 0) {
newLeft = 0;
}
if (newLeft + 160 > 800) {
newLeft = newLeft - (newLeft + 160 - 800);
}
el.style.top = newTop + 'px';
el.style.left = newLeft + 'px';
Upvotes: 1