我尝试写一些代码,允许SVG元素被上拖动。 这是与jQuery,jQuery UI的和jQuery SVG很容易,而在Firefox中工作正常,但在Chrome中,当我拖动SVG元素,偏移显然加入到它的坐标。 我什么都看不到我做错了,或者发现这方面的任何已知的bug。
我已经构造说明该问题的一个小例子:
<html>
<head>
<title>Foo</title>
<style type="text/css">
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://keith-wood.name/js/jquery.svg.js"></script>
<script type="text/javascript">
$(function() {
var svgOnLoad = function () {
var svg = $('#canvas').svg('get');
$('#piece')
.draggable()
.bind('drag', function (event, ui) {
// Update transform manually, since top/left style props don't work on SVG
var t = event.target.transform.baseVal;
if (t.numberOfItems == 0) {
t.appendItem(svg.root().createSVGTransform());
}
t.getItem(0).setTranslate(ui.position.left, ui.position.top);
});
}
$('#canvas').svg({loadURL: "foo.svg", onLoad: svgOnLoad});
});
</script>
</head>
<body>
<div id="canvas" style="width: 100%; height: 100%;"></div>
</body>
</html>
其中foo.svg就是:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="450" height="450">
<rect id="piece" width="50" height="50" x="100" y="100" />
</svg>
在线版本,可以发现:
http://jsfiddle.net/rrthomas/v477X/2/
Answer 1:
问题是,你是不是开始在SVG画布的位置0,0。 可以实现通过减去来自物体的x和y的属性所期望的结果。 当你计算出你的拖累手册您要重新定位整个SVG元素,而不仅仅是矩形。
在这里看到: http://jsfiddle.net/v477X/6/
注:不同的浏览器似乎要尝试翻译的元素将被返回不同的对象。 该解决方案工作在WebKit浏览器。 在这一点上,看来你有2种选择。 修改您的选择器选择相同的元件,(特别是线t.getItem(0)),或确定所述用户是在当前观看该浏览器中,并添加偏移量,如果它是webkit的。 就个人而言,我会用后者去,因为这样你可以设置一个变量,并检查它。
在这里看到如何检测浏览器引擎: 如果浏览器Chrome的使用jQuery如何检测?
Answer 2:
似乎是在jQueryUI的这里的错误:在非WebKit浏览器,该ui.position对象使用绝对坐标,而在其他浏览器中它是一个从ui.originalPosition偏移。 我不知道这是正确的; 这个bug是该行为是不一致的。 我已提起诉讼,在错误报告:
http://bugs.jqueryui.com/ticket/8335
因此,该解决方法是存储顶级元素的原始坐标,并设置坐标 - 设定WebKit浏览器的平移变换时(ui.position ui.originalPosition + origCoords)。 (Jlange的答案使用x和我的小例子,它在那里工作蛮好用的矩形Y的属性,但不与更复杂的对象工作一)不得有x和y的属性(例如,如果顶层元素是AG元素)和b)在返回的坐标似乎不是那些顶级元素的反正(我怕我不知道为什么))最小的代码如下:
var svgOnLoad = function () {
var svg = $('#canvas').svg('get');
$('#piece')
.draggable()
.on({
dragstart: function (event, ui) {
var tlist = this.transform.baseVal;
if (tlist.numberOfItems == 0) {
tlist.appendItem(svg.root().createSVGTransform());
}
var tm = tlist.getItem(0).matrix;
var pos = {left: tm.e, top: tm.f};
$.data(this, 'originalPosition', pos);
},
drag: function (event, ui) {
// Update transform manually, since top/left style props don't work on SVG
var tlist = this.transform.baseVal;
var CTM = this.getCTM();
var p = svg.root().createSVGPoint();
p.x = ui.position.left + CTM.e;
p.y = ui.position.top + CTM.f;
if ($.browser.webkit) { // Webkit gets SVG-relative coords, not offset from element
var origPos = $.data(this, 'originalPosition');
p.x -= ui.originalPosition.left - origPos.left;
p.y -= ui.originalPosition.top - origPos.top;
}
p = p.matrixTransform(CTM.inverse());
tlist.getItem(0).setTranslate(p.x, p.y);
}});
};
$('#canvas').svg({onLoad: svgOnLoad});
真人版在: http://jsfiddle.net/rrthomas/v477X/
Answer 3:
最近,我花了几天这个问题锤击,我想出了工作得相当好,我的解决方案。 这绝对是一个黑客,并且将无法正常工作在所有情况下。
此链接有如何在一般的解决这个问题一个很好的描述,那绝对是“更好”的解决方案。 不过,我想使用jQuery的可拖动的优秀API保持。
你可以看到我在小提琴做了一个快速模拟了这里 。 其核心思想是使用你保持在您想要拖动SVG元素正好徘徊代理股利。 然后,你改变SVG元素的x,y坐标为拖动代理股利。 事情是这样的:
$('#proxy').on('drag', function(e)
{
t = $('#background');
prox = $('#proxy');
t.attr('x', t.attr('x')*1
+ prox.css('left').slice(0,-2)*1
- prox.data('position').left)
.attr('y', t.attr('y')*1
+ prox.css('top').slice(0,-2)*1
- prox.data('position').top);
prox.data('position',{top : prox.css('top').slice(0,-2)*1,
left: prox.css('left').slice(0,-2)*1}
);
});
在我的情况下,SVG元素,我想拖总是充满整个屏幕上的某个广场上,所以这是很容易在目标定位代理股利。 在其他情况下,它可能会更加困难。 它也不会太难用了“遏制”选项,以确保您不要拖到框架外的背景...它只是需要一些细致的数学,你必须遏制重置每个阻力之间。
Answer 4:
用这个:
<html>
<head>
<title>Foo</title>
<style type="text/css">
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.8.18/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://keith-wood.name/js/jquery.svg.js"></script>
<script type="text/javascript">
$(function ()
{
var svg = $('#canvas').svg().svg('get');
$('#piece')
.draggable()
.on({
dragstart: function (event, ui)
{
var t = this.transform.baseVal;
if (t.numberOfItems == 0)
{ t.appendItem(svg.root().createSVGTransform()); }
var tm = t.getItem(0).matrix;
var dx = tm.e - ui.position.left;
var dy = tm.f - ui.position.top;
$.data(this, 'dragTo', function dragTo(newPos)
{
tm.e = newPos.left + dx;
tm.f = newPos.top + dy;
});
},
drag: function (event, ui)
{ $.data(this, 'dragTo')(ui.position); }});
});
</script>
</head>
<body>
<div id="canvas" style="width: 100%; height: 100%;">
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
width="450" height="450">
<rect id="piece" width="50" height="50" x="0" y="0" style="position:absolute"/>
</svg>
</div>
</body>
</html>
Answer 5:
我有一个类似的问题。 我发现,由于某些原因,Chrome的转换变换属性为CSS样式属性。 因此,它创建了一个CSS样式- CSS的引擎调整坐标-那么SVG引擎然后尝试应用转换:转换。 之后,两人彼此干扰。
在CSS似乎有优先权。 这里是在这个codepen。
http://codepen.io/dax006/pen/ONNWXv
我的理论是,当CSS样式是由Chrome的更新,它不断地被破坏和重建,以及SVG有时那些时刻之间溜进在变换分析:翻译()。 Chrome会抓住新的转换值,并将其应用于CSS,现在您的转换,因为CSS是在路上将无法正常工作。
从理论上讲变换:翻译应该在创建CSS完全一样的瞬间被摧毁,但事实并非如此。 简单地检查元素,你会看到的CSS样式改变的坐标都存在着和变换属性。
<rect y="100" x="100" height="50" width="50" id="piece" style="position: relative; left: -15px; top: -13px;" transform="translate(-15, -13)"/>
一定要看看这篇文章,并在底部的链接。 https://css-tricks.com/svg-animation-on-css-transforms/
文章来源: How do I make dragging SVG elements in Chrome with jQuery work without getting offsets? (Firefox is OK)