Snap.svg:drag()问题,包含元素

时间:2017-03-27 13:19:35

标签: javascript jquery html svg snap.svg

我想要实现的目标:

我遵循了我想要实现的两个目标:

  1. 我需要嵌入SVG文档中的单行/多行可编辑文本输入字段。
  2. 这些字段必须具有拖动功能。
  3. 将文本字段作为SVG的一部分的目的是在缩放SVG文档以编写任何多余的代码时缩放它们。

    要完成这两项任务,请使用Snap.svg库。

    到目前为止我做了什么:

    SVG有一个foreignObject元素,允许我们在SVG中嵌入任何HTML标记。因此,使用此功能,我在SVG中添加了inputtextarea字段。

    以下是演示:

    
    
    var s = Snap('#demo');
    var defualtWidth = s.attr('width');
    var defualtHeight = s.attr('height');
    
    var fobjectSVG = '<foreignObject x="30" y="40" width="240" height="40"><input type="text" class="form-control"placeholder="Some dummy text here..." /></foreignObject>';
    
    s.append(Snap.parse(fobjectSVG));
    
    $('.select-zoom').change(function(event) {
    	var zoomRatio = $(this).val();
    
    	s.attr({
    		'width': defualtWidth * zoomRatio,
    		'height': defualtHeight * zoomRatio
    	});
    });
    &#13;
    .form-control {
    	border: 3px solid #000;
    	padding: 3px 10px;
    	background: #fff;
    	display: block;
    	height: 100%;
    	width: 100%;
    	margin: 0;
    }
    
    .select-zoom {
      position: absolute;
    	width: 100px;
    	height: 30px;
      right: 40px;
      top: 50px;
      z-index: 10;
    }
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
    <svg id="demo" width="700" height="550" viewBox="0 0 700 550">
      <image x="0" y="0" width="100%" height="550" href="https://i.imgur.com/waDgcnc.jpg" />
    </svg>
    <select class="select-zoom">
      <option value="0.5">50%</option>
      <option value="0.75">75%</option>
      <option value="1" selected="selected">100%</option>
      <option value="1.25">125%</option>
      <option value="1.5">150%</option>
      <option value="2">200%</option>
      <option value="2.5">250%</option>
      <option value="5">500%</option>
    </select>
    &#13;
    &#13;
    &#13;

    添加拖动功能

    Snap.svg有一个.drag()函数,可以在调用元素时将拖动功能附加到元素上。

    以下是演示:

    &#13;
    &#13;
    var s = Snap('#demo');
    var rect = s.rect(30, 30, 240, 120).attr({stroke: '#000', 'strokeWidth': 3, fill: '#2ecc40'});
    rect.drag();
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
    <svg id="demo" width="700" height="550" viewBox="0 0 700 550">
      <image x="0" y="0" width="100%" height="550" href="https://i.imgur.com/waDgcnc.jpg" />
    </svg>
    &#13;
    &#13;
    &#13;

    有什么问题?

    当我在此.drag()上调用foreignObject函数时,其中的input / textarea字段会停止其正常行为。似乎他们的默认行为以某种方式被取消。

    以下是问题的演示:

    &#13;
    &#13;
    var s = Snap('#demo');
    var defualtWidth = s.attr('width');
    var defualtHeight = s.attr('height');
    
    var fobjectSVG = '<foreignObject x="30" y="40" width="240" height="40"><input type="text" class="form-control"placeholder="Some dummy text here..." /></foreignObject>';
    
    var fobjectSVG2 = '<foreignObject x="30" y="100" width="240" height="120"><textarea class="form-control" placeholder="Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, "></textarea></foreignObject>';
    
    var field = s.group().append(Snap.parse(fobjectSVG));
    var field2 = s.group().append(Snap.parse(fobjectSVG2));
    field.drag();
    field2.drag();
    
    $('.select-zoom').change(function(event) {
    	var zoomRatio = $(this).val();
    
    	s.attr({
    		'width': defualtWidth * zoomRatio,
    		'height': defualtHeight * zoomRatio
    	});
    });
    &#13;
    .form-control {
    	border: 3px solid #000;
    	padding: 3px 10px;
    	background: #fff;
    	display: block;
    	height: 100%;
    	width: 100%;
    	margin: 0;
    }
    
    .select-zoom {
      position: absolute;
    	width: 100px;
    	height: 30px;
      right: 40px;
      top: 50px;
      z-index: 10;
    }
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
    <svg id="demo" width="700" height="550" viewBox="0 0 700 550">
      <image x="0" y="0" width="100%" height="550" href="https://i.imgur.com/waDgcnc.jpg" />
    </svg>
    <select class="select-zoom">
      <option value="0.5">50%</option>
      <option value="0.75">75%</option>
      <option value="1" selected="selected">100%</option>
      <option value="1.25">125%</option>
      <option value="1.5">150%</option>
      <option value="2">200%</option>
      <option value="2.5">250%</option>
      <option value="5">500%</option>
    </select>
    &#13;
    &#13;
    &#13;

    正如您在上面的演示中所看到的,字段是拖动的,但我无法像正常的输入/ textarea字段那样编辑文本。

    有什么问题?

    我想启用当前以某种方式禁用的默认行为。有人可以解释为什么会发生这种情况,我该如何解决这个问题?

    欢迎所有解决方案,无论它们属于此库还是其他一些。

    修改

    可以禁用文本字段的文本选择,在我的情况下不需要。

    注意:IE浏览器不支持 foreignObject,因此如果使用IE,上面的示例可能无效。不过确实如此 MS Edge浏览器支持。

1 个答案:

答案 0 :(得分:1)

使用contentEditable在foreignObject中尝试DIV。下面是没有Snap.drag()的示例,但使用标准的svg拖动方法: 注意:Edge浏览器需要foreignObject width / height = 100%

&#13;
&#13;
<!DOCTYPE HTML>

<html>
<head>
  <title>Drag foreignObject DIV</title>
</head>
<body>
<div style=background:gainsboro;width:300px;height:300px >
<svg id="mySVG" width="300" height="300"   onmouseup="endDrag()"   onmousemove="drag(evt)" >
<foreignObject id="dragTarget"  transform="translate(24 40)" width="100%" height="100%"><div id=myDiv onmousedown="startDrag();this.contentEditable='false'" style='border:2px solid black;width:150px;height:50px;overflow:auto' contentEditable="true" >This is my text</div></foreignObject>
</svg>
</div>
<script>
var TransformRequestObj
var TransList
var DragTarget=null;
var Dragging = false;
var DragStartGrabX = 0;
var DragStartGrabY = 0;
//---mouse down over element---
function startDrag()
{
	if(!Dragging) //---prevents dragging conflicts on other draggable elements---
	{

			DragTarget = document.getElementById("dragTarget")

			//---reference point to its respective viewport--
			var pnt = DragTarget.ownerSVGElement.createSVGPoint();
			pnt.x = event.clientX
			pnt.y = event.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
            //---the point on the element to grab as its dragging point---
			DragStartGrabX = Pnt.x
			DragStartGrabY = 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 -= DragStartGrabX;
		Pnt.y -= DragStartGrabY;

		TransformRequestObj.setTranslate(Pnt.x,Pnt.y)
		TransList.appendItem(TransformRequestObj)
		TransList.consolidate()
	}
}
//--mouse up---
function endDrag()
{
	Dragging = false ;
    myDiv.contentEditable="true"
   
}
</script>
</body>

</html>
&#13;
&#13;
&#13;