不可重叠可拖放与Snap.svg (Javascript)
Unoverlappable Draggables with Snap.svg (Javascript)
这是我第一次在Stack Overflow上发表问题,所以请随意评论我如何改进我的问题。
我试图使两个SVG矩形拖拽不能重叠。为此,我使用Snap.svg来拖动元素,并使用Snap API中的. isbboxintersect实用程序方法,在每次调用move函数时获取它们的边界框,以查看它们是否发生碰撞。如果它们发生碰撞,我要确保它们不会重叠,从而使每个对象无法通过另一个对象。当前被拖动的对象将沿着某个轴移动,直到碰撞再次返回false。这里有一些我想要的基本代码:
<html>
<head>
<title>
</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js"></script>
</head>
<body>
<script>
var s = Snap(600,500);
var rect = s.rect(0,0,40,40);
var rectr = s.rect(400,90,50,50);
var b=0;
var c=0;
var isInter;
var move = function(dx,dy, x, y, event) {
var b1 = rect.getBBox();
var b2 = rectr.getBBox();
isInter = Snap.path.isBBoxIntersect(b1, b2);
if (isInter==false) {
b=dx;
c=dy;
}
if (isInter==true) {
if (b1.y2==b2.y&&b1.x2==b2.x||b1.x==b2.x2&&b1.y2==b2.y){c=b2.y-b1.h, b=dx
}
else if (b1.x==b2.x2&&b1.y==b2.y2||b1.x2==b2.x&&b1.y==b2.y2){c=b2.y2; b=dx;}
else if (b1.y2==b2.y){(dy>=b2.y-b1.h) ? (c=b2.y-b1.h, b=dx): (b=dx, c=dy);}
else if (b1.y==b2.y2){(dy<=b1.y) ? (c=b2.y2, b=dx):(b=dx,c=dy);}
else if (b1.x2==b2.x){(dx>=b1.x) ? (b=b2.x-b1.width, c=dy):(b=dx, c=dy);}
else if (b1.x==b2.x2){(dx<=b1.x2) ? (b=b2.x2, c=dy):(b=dx, c=dy);}
else {b=dx; c=dy;}
}
this.attr({
transform: this.data('origTransform') + ((this.data('origTransform')) ? "t": "T") + [b,c]
});
}
var start = function() {
this.data('origTransform', this.transform().local );
b=0;
c=0;
}
rect.drag(move, start);
circle.drag(move, start);
</script>
</body>
</html>
这是出现的三个主要问题:
如果你拖得太快,引擎跟不上,拖拽项就会重叠。我希望有一种方法来防止重叠,无论多么快的拖动
碰撞只在rectr上拖拽rect时起作用。我可以很容易地为矩形添加另一个碰撞检测块,但我认为这会使引擎速度变慢太多。我的碰撞检测似乎过于复杂。因此,我希望有一种更有效的方法来测试碰撞。
如果rectr先被拖拽,然后rect被拖拽到rectr上,碰撞检测完全失败。这可能是一个问题。getbbox(),但我不能肯定地说。
在这三个问题上任何帮助都将是非常感激的。
谢谢!
抱歉,我只能提供另一种使用Javascript的方法。也许这在将来的某个时候会对你有所帮助。
这个例子创建了50(50)个随机位置的svg形状。每个形状都是可拖动的。如果被拖动的形状的边界框与另一个形状相交,则其不透明度将被更改,直到被拖动的形状移出相交范围。
祝你好运。
<head>
<title>Untitled</title>
</head>
<body onLoad=svgGLOB(50,800,800,30)>
<div style=font-family:arial>
Fifty(50) svg shapes are created and randomly located. Each shape is draggable. If the dragged shape's bounding box intersects another shape, its opacity is changed until the dragged shape moves out of intersect range.
</div>
<div id=svgDiv style='width:800px;height:800px;border:1px solid black'>
<svg id=mySVG width="800" height="800" onmousedown="startDrag(evt)" onmousemove="drag(evt)" onmouseup="endDrag()"></svg>
</div>
</body>
<script>
function intersectShape(target)
{
var r1 = target.getBoundingClientRect(); //BOUNDING BOX OF THE TARGET OBJECT
for(k=0;k<globG.childNodes.length;k++)
{
var shape=globG.childNodes.item(k)
if(shape!=target)
{
var r2=shape.getBoundingClientRect();
//CHECK IF ANY TWO BOUNDING BOXES OVERLAP
if(!(r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top))
shape.setAttribute("opacity",.5)
else
shape.setAttribute("opacity",1)
}
}
}
var TransformRequestObj
var TransList
var DragTarget=null;
var Dragging = false;
var OffsetX = 0;
var OffsetY = 0;
//---mouse down over element---
function startDrag(evt)
{
if(!Dragging) //---prevents dragging conflicts on other draggable elements---
{
if(evt.target.getAttribute("class")=="dragTarget")
{
DragTarget = evt.target;
DragTarget.setAttribute("style","cursor:move")
//---reference point to its respective viewport--
var pnt = DragTarget.ownerSVGElement.createSVGPoint();
pnt.x = evt.clientX;
pnt.y = evt.clientY;
//---elements transformed and/or in different(svg) viewports---
var sCTM = DragTarget.getScreenCTM();
var Pnt = pnt.matrixTransform(sCTM.inverse());
TransformRequestObj = DragTarget.ownerSVGElement.createSVGTransform()
//---attach new or existing transform to element, init its transform list---
var myTransListAnim=DragTarget.transform
TransList=myTransListAnim.baseVal
OffsetX = Pnt.x
OffsetY = Pnt.y
Dragging=true;
}
}
}
//---mouse move---
function drag(evt)
{
if(Dragging)
{
var pnt = DragTarget.ownerSVGElement.createSVGPoint();
pnt.x = evt.clientX;
pnt.y = evt.clientY;
//---elements in different(svg) viewports, and/or transformed ---
var sCTM = DragTarget.getScreenCTM();
var Pnt = pnt.matrixTransform(sCTM.inverse());
Pnt.x -= OffsetX;
Pnt.y -= OffsetY;
TransformRequestObj.setTranslate(Pnt.x,Pnt.y)
TransList.appendItem(TransformRequestObj)
TransList.consolidate()
intersectShape(DragTarget)
}
}
//--mouse up---
function endDrag()
{
Dragging = false;
DragTarget.setAttribute("style","cursor:default")
}
//==================add a bunch of SVG elements============
//---onload: svgGLOB(50,800,800,30)---
function svgGLOB(elems,svgWidth,svgHeight,elemSize)
{
/* ---fill empty inline SVG element---
<div id="svgDiv"><svg id="mySVG" /></div>
*/
var NS="http://www.w3.org/2000/svg"
mySVG.setAttribute("width",svgWidth)
mySVG.setAttribute("height",svgHeight)
svgDiv.style.width=svgWidth+"px"
svgDiv.style.height=svgHeight+"px"
var globG=document.createElementNS(NS,"g")
globG.id="globG"
globG.setAttribute("stroke","black")
globG.setAttribute("stroke-width",1)
mySVG.appendChild(globG)
var points=randomPoints(elems,svgWidth,svgHeight,elemSize)
var n=points.length
var circleCnt=0
var ellipseCnt=0
var rectCnt=0
var polygonCnt=0
var RandomElems=[]
RandomElems[0]="circle"
RandomElems[1]="rect"
RandomElems[2]="ellipse"
RandomElems[3]="polygon_3"
RandomElems[4]="polygon_4"
RandomElems[5]="polygon_5"
RandomElems[6]="polygon_6"
RandomElems[7]="polygon_7"
RandomElems[8]="polygon_8"
RandomElems[9]="polygon_9"
RandomElems[10]="polygon_10"
RandomElems[11]="polygon_11"
RandomElems[12]="polygon_12"
for(var k=0;k<n;k++)
{
var rand=rdm(0,12)
var elemStr=RandomElems[rand]
if(!elemStr.indexOf("_"))
var elemSt=elemStr
else
var elemSt=elemStr.split("_")[0]
var elem=document.createElementNS(NS,elemSt)
if(elemSt=="circle")
{
elem.setAttribute("r",elemSize)
elem.setAttribute("fill",rcolor())
elem.setAttribute("cx",points[k][0])
elem.setAttribute("cy",points[k][1])
elem.id=elemSt+(circleCnt++)
}
else if(elemSt=="ellipse")
{
elem.setAttribute("rx",elemSize)
elem.setAttribute("ry",elemSize/2)
elem.setAttribute("fill",rcolor())
elem.setAttribute("cx",points[k][0])
elem.setAttribute("cy",points[k][1])
elem.id=elemSt+(ellipseCnt++)
}
else if(elemSt=="rect")
{
elem.setAttribute("width",elemSize)
elem.setAttribute("height",elemSize)
elem.setAttribute("fill",rcolor())
elem.setAttribute("x",points[k][0])
elem.setAttribute("y",points[k][1])
elem.id=elemSt+(rectCnt++)
}
else if(elemSt=="polygon")
{
var pgonSides=parseInt(elemStr.split("_")[1])
var pgonPnts=polygon(pgonSides,elemSize,points[k][0],points[k][1])
elem.setAttribute("fill",rcolor())
elem.setAttribute("points",pgonPnts.join())
elem.id=elemSt+(polygonCnt++)
}
elem.setAttribute("class","dragTarget")
globG.appendChild(elem)
}
//---obtain a random whole number from a thru b---
function rdm(a,b)
{
return a + Math.floor(Math.random()*(b-a+1));
}
function randomPoints(elems,svgWidth,svgHeight,elemSize)
{
//--return format:[ [x,y],[x,y],,, ]
//---Generate random points---
function times(n, fn)
{
var a = [], i;
for (i = 0; i < n; i++) {
a.push(fn(i));
}
return a;
}
var width=svgWidth-2*elemSize
var height=svgHeight-2*elemSize
return RandomPnts = times(elems, function() { return [Math.floor(width * Math.random()) + elemSize, Math.floor(height * Math.random()) + elemSize] });
}
//---random color---
function rcolor()
{
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ )
{
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
function polygon(vCnt,radius,centerX,centerY)
{
var myPoints=[]
var polyXPts = Array(vCnt);
var polyYPts = Array(vCnt);
var vertexAngle = 360/vCnt;
//---init polygon points processor---
for(var v=0; v<vCnt; v++)
{
theAngle = (v*vertexAngle)*Math.PI/180;
polyXPts[v] = radius*Math.cos(theAngle);
polyYPts[v] = -radius*Math.sin(theAngle);
}
//--note points are CCW---
for(var v=0;v<vCnt; v++)
{
var point=[centerX+polyXPts[v],centerY+polyYPts[v]]
myPoints.push(point)
}
return myPoints
}
}
</script>
好的,让我们从使用SVG的本机方法和javascript的示例开始。这个例子要么直接"粘"到另一个。无论涉及多少元素,阻力都不会降低。下一步是确定在矩形粘在一起后要做什么?
<head>
<title>Untitled</title>
</head>
<body>
<svg width="800" height="800" onmousedown="startDrag(evt)" onmousemove="drag(evt)" onmouseup="endDrag()">
<rect class="dragTarget" id=rect1 x=200 y=200 width=50 height=90 fill=red />
<rect class="dragTarget" id=rect2 x=400 y=400 width=50 height=90 fill=blue />
</svg>
</body>
<script>
function intersectRect(shape1, shape2) {
var r1 = shape1.getBoundingClientRect(); //BOUNDING BOX OF THE FIRST OBJECT
var r2 = shape2.getBoundingClientRect(); //BOUNDING BOX OF THE SECOND OBJECT
//CHECK IF THE TWO BOUNDING BOXES OVERLAP
return !(r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top);
}
var TransformRequestObj
var TransList
var DragTarget=null;
var Dragging = false;
var OffsetX = 0;
var OffsetY = 0;
//---mouse down over element---
function startDrag(evt)
{
if(!Dragging) //---prevents dragging conflicts on other draggable elements---
{
if(evt.target.getAttribute("class")=="dragTarget")
{
DragTarget = evt.target;
DragTarget.setAttribute("style","cursor:move")
//---reference point to its respective viewport--
var pnt = DragTarget.ownerSVGElement.createSVGPoint();
pnt.x = evt.clientX;
pnt.y = evt.clientY;
//---elements transformed and/or in different(svg) viewports---
var sCTM = DragTarget.getScreenCTM();
var Pnt = pnt.matrixTransform(sCTM.inverse());
TransformRequestObj = DragTarget.ownerSVGElement.createSVGTransform()
//---attach new or existing transform to element, init its transform list---
var myTransListAnim=DragTarget.transform
TransList=myTransListAnim.baseVal
OffsetX = Pnt.x
OffsetY = Pnt.y
Dragging=true;
}
}
}
//---mouse move---
function drag(evt)
{
if(Dragging)
{
if(intersectRect(rect1, rect2)==false)
{
var pnt = DragTarget.ownerSVGElement.createSVGPoint();
pnt.x = evt.clientX;
pnt.y = evt.clientY;
//---elements in different(svg) viewports, and/or transformed ---
var sCTM = DragTarget.getScreenCTM();
var Pnt = pnt.matrixTransform(sCTM.inverse());
Pnt.x -= OffsetX;
Pnt.y -= OffsetY;
TransformRequestObj.setTranslate(Pnt.x,Pnt.y)
TransList.appendItem(TransformRequestObj)
TransList.consolidate()
}
}
}
//--mouse up---
function endDrag()
{
Dragging = false;
DragTarget.setAttribute("style","cursor:default")
}
</script>
- 如何使用javascript从主svg对象动态创建svg视图框
- SVG/JavaScript:尝试选择和更改多边形点
- JavaScript-动态SVG-onload属性-未触发事件
- 使用SVG和JavaScript创建波浪动画
- 使用svg和javascript将一个类的元素动画化为另一个类
- SVG使用Javascript将形状平滑地变形为其他预定义的形状
- javascript中的SVG转换在IE 11中不起作用
- 如何使用javascript操作SVG节点,使其在MS Edge中工作
- Javascript SVG viewer library
- JavaScript + SVG :当它在样式之外声明时获取填充
- Javascript + SVG:将鼠标事件添加到对象中的 SVG
- 如何通过按 JavaScript/SVG 中的按钮将形状的半径设置为更大或更小
- JavaScript / SVG
- javascript svg onmouseover effect
- 画布上的Javascript SVG绘图在事件阶段2失败
- JavaScript SVG世界地图库离线工作
- javascript svg animation
- JavaScript SVG旋转没有按预期工作
- Javascript+svg,在两个给定点之间绘制正弦(波浪)线
- Javascript SVG动画在iPhone的CPU使用情况