我正在尝试组合一个拖放界面,允许用户在页面上拖动 div,该页面被限制在不规则的闭合 SVG 路径内部。
这是一个示例 - 橙色方 block 是我的可拖动元素,灰色 SVG 路径是我想要将其限制在放置时的位置:
<div class="drag-parent">
<svg xmlns="http://www.w3.org/2000/svg" width="141.019" height="74.065" viewBox="0 0 141.019 74.065">
<defs>
<style>
.target {
fill: #333;
}
</style>
</defs>
<path id="Path_4569" data-name="Path 4569" class="target" d="M0,0H141.018V74.065h-24.27V37.033H10.88V12.971H0Z"/>
</svg>
<div class="draggable" style="width:20px;height:20px;background:orange;cursor:pointer;"></div>
</div>
我想做的是在拖动时检查可拖动的 div,以确保它完全位于我的 SVG 的闭合路径内。
我正在使用 GSAP Draggable 来负责实际拖动元素,但我对如何测试它是否在该路径内感到困惑。
到目前为止,我已经尝试了 isPointInFill
但是,无论我给它什么,这似乎都会在 chrome 中返回 true 。
我还尝试在路径上使用 mouseenter
/mouseleave
事件,这是一个很好的起点;但是当您拖动某些内容时,这些事件不会触发,因为鼠标指针位于所拖动项目的“顶部”,而不是 SVG 路径的“顶部”。
什么是强制 SVG 路径边界的好方法 - 或者,是否有更简单的方法来强制拖动项目的不规则边界?
最佳答案
主要思想是检查橙色 div 的所有 4 个 Angular 是否都在路径上方。也许我把事情过于简单化了,因为 drag_parent
有 `margin 0;填充:0;``
我希望这就是您所问的。
let D = false,// if D ids true you can drag
m = {},// the mouse position
thePath = document.querySelector("#Path_4569"),
draggable = document.querySelector("#draggable");
draggable.w = draggable.getBoundingClientRect().width;
draggable.h = draggable.getBoundingClientRect().height;
draggable.p0s = [[], [], [], []];//one array for every corner
draggable.delta = {};// distance between the click point and the left upper corner
draggable.addEventListener("mousedown", e => {
D = true;
draggable.delta = oMousePos(draggable, e);
});
drag_parent.addEventListener("mousemove", e => {
if (D == true) {
let counter = 0;// how many corners are in path
m = oMousePos(drag_parent, e);
draggablePoints(m);
draggable.style.left = draggable.p0s[0][0] + 1 + "px";
draggable.style.top = draggable.p0s[0][1] + 1 + "px";
draggable.p0s.map(p => {
if (document.elementFromPoint(p[0], p[1]) && document.elementFromPoint(p[0], p[1]).id == "Path_4569") {
counter++;
}
});
if (counter == 4) {// if all 4 corners are in path
thePath.setAttributeNS(null, "fill", "#777");
} else {
thePath.setAttributeNS(null, "fill", "black");
}
}
});
drag_parent.addEventListener("mouseup", e => {
D = false;
});
drag_parent.addEventListener("mouseleave", e => {
D = false;
});
function oMousePos(elmt, evt) {
var ClientRect = elmt.getBoundingClientRect();
return {
//objeto
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
};
}
function draggablePoints(m) {
//top left
draggable.p0s[0][0] = m.x - draggable.delta.x - 1;
draggable.p0s[0][1] = m.y - draggable.delta.y - 1;
//top right
draggable.p0s[1][0] = m.x - draggable.delta.x + draggable.w + 1;
draggable.p0s[1][1] = m.y - draggable.delta.y + 1;
//bottom right
draggable.p0s[2][0] = m.x - draggable.delta.x + draggable.w + 1;
draggable.p0s[2][1] = m.y - draggable.delta.y + draggable.h + 1;
//bottom left
draggable.p0s[3][0] = m.x - draggable.delta.x + 1;
draggable.p0s[3][1] = m.y - draggable.delta.y + draggable.h + 1;
}
*{margin:0;padding:0}
svg {
outline: 1px solid;
}
#drag_parent {
outline: 1px solid;
min-height: 100vh;
position:relative;
}
#draggable {
position: absolute;
width: 20px;
height: 20px;
background: orange;
cursor: pointer;
}
<div id="drag_parent">
<svg xmlns="http://www.w3.org/2000/svg" width="141.019" height="74.065" viewBox="0 0 141.019 74.065">
<path id="Path_4569" data-name="Path 4569" class="target" d="M0,0H141.018V74.065h-24.27V37.033H10.88V12.971H0Z"/>
</svg>
<div id="draggable"></div>
</div>
关于javascript - 如何测试一个点是否在 SVG 闭合路径内,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54076532/