【问题标题】:Snap.svg: drag() issue with default behavior of ElementsSnap.svg:元素默认行为的拖动()问题
【发布时间】:2017-08-20 05:34:25
【问题描述】:

我想要达到的目标:

我正在努力实现两个目标:

  1. 我需要在 SVG 文档中嵌入单行/多行可编辑文本输入字段。
  2. 这些字段必须具有拖动功能。

使文本字段成为 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
	});
});
.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;
}
<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>

添加拖动功能:

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

下面是一个演示:

var s = Snap('#demo');
var rect = s.rect(30, 30, 240, 120).attr({stroke: '#000', 'strokeWidth': 3, fill: '#2ecc40'});
rect.drag();
<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>

有什么问题?

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

下面是问题的演示:

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
	});
});
.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;
}
<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>

正如您在上面的演示中看到的那样,字段正在拖动,但我无法像普通输入/文本区域字段那样编辑它们的文本。

问题是什么?

我想启用他们当前以某种方式禁用的默认行为。有人能解释一下为什么会这样吗?我该如何解决这个问题?

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

编辑:

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

注意: IE 浏览器不支持 foreignObject,因此如果您使用 IE,上述示例可能无法正常工作。然而它是 MS Edge 浏览器支持。

【问题讨论】:

  • 我认为问题在于 Snaps 拖动有一个 preventDefault 。但是,解决这个问题可能会引入更大的用户界面问题。您希望在单击鼠标时发生什么。您希望它成为拖动的一部分,还是编辑文本区域(而不是拖动的一部分)。其他拖动处理程序可能会有同样的问题,因为这可能是用户设计问题?
  • @Ian 单击一次,用户应该能够编辑字段内的文本。虽然他/她也应该能够拖动该字段。
  • 但是要开始文本区域编辑,它是鼠标按下,而不是单击。所以要么 mousedown = textarea 编辑,要么 mousedown = 开始拖动。如果你想拖动 textarea 中的文本会发生什么?也许你可以捏造一些东西,但它可能永远是一个容易引发问题的捏造。
  • @Ian 好的,有没有可能做到这一点?这是我正在从事的项目的要求。我需要以某种方式实现它。如果我编写一些自定义拖动处理程序,您怎么看?
  • 如果您可以解释您希望在不与另一个冲突的鼠标按下时发生的逻辑,则可能取决于此。但是感觉项目的需求可能不对。

标签: javascript jquery html svg snap.svg


【解决方案1】:

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

<!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>

【讨论】:

    猜你喜欢
    • 2016-06-21
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    • 2015-01-20
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多