Javascript 如何从SVG中的path元素获取X,Y坐标?
这里是一把小提琴的实际拥有。 我正在使用一个库来缩放和平移SVG。 我有一个按钮,当点击它放大西班牙的例子,所以我把坐标在:Javascript 如何从SVG中的path元素获取X,Y坐标?,javascript,jquery,svg,svgpanzoom,Javascript,Jquery,Svg,Svgpanzoom,这里是一把小提琴的实际拥有。 我正在使用一个库来缩放和平移SVG。 我有一个按钮,当点击它放大西班牙的例子,所以我把坐标在: $("#spain").on("click", function() { panZoom.zoomAtPoint(12, {x: 188, y: 185}); }); 问题是,当我调整页面大小时,坐标不再起作用,我需要重新计算它们,我发现一个可能起作用的函数,但我不知道如何使用它: var s = instance.getSizes()
$("#spain").on("click", function() {
panZoom.zoomAtPoint(12, {x: 188, y: 185});
});
问题是,当我调整页面大小时,坐标不再起作用,我需要重新计算它们,我发现一个可能起作用的函数,但我不知道如何使用它:
var s = instance.getSizes()
var p = instance.getPan()
var relativeX = s.width / 2 / (p.x + s.viewBox.width * s.realZoom)
// After resize
var s = instance.getSizes()
var p = instance.getPan()
var x = (s.width / 2 / relativeX) - s.viewBox.width * s.realZoom
instance.pan({x: x, y: 0})
还有一个问题,例如,是否可以从svg内部的路径ID获取坐标
编辑:似乎我必须从svg中计算实际的X和Y视口,然后重新计算,如果在0.0视口中给出我的点(X:188,Y:185),有人知道我可以看到的任何示例吗?对附加事件侦听器的方式做一个小改动怎么样 改为附加到每个国家
$(document).ready(function() {
var panZoom = svgPanZoom('#mapa-mundi', {
zoomEnabled: true,
controlIconsEnabled: true,
fit: true,
center: true,
minZoom: 1,
maxZoom: 200,
zoomScaleSensitivity: 1
});
$(window).resize(function(){
panZoom.resize();
panZoom.fit();
panZoom.center();
})
var svg_rect = document.querySelector('#mapa-mundi').getBoundingClientRect();
alert("svg: " + svg_rect.top + " " + svg_rect.right + " " + svg_rect.bottom + " " + svg_rect.left);
$("#spain").on("click", function() {
panZoom.zoomAtPoint(12, {x: 188, y: 185});
});
//Find your root SVG element
var svg = document.querySelector('#mapa-mundi');
//Create an SVGPoint for future math
var pt = svg.createSVGPoint();
//Get point in global SVG space
function cursorPoint(evt){
pt.x = evt.clientX; pt.y = evt.clientY;
return pt.matrixTransform(svg.getScreenCTM().inverse());
}
var country = document.querySelectorAll('.map-hover-svg');
var my_dict = {};
country.forEach(function(element){
var rect = element.getBoundingClientRect();
my_dict[element.id] = [rect.top, rect.right, rect.bottom, rect.left, rect.bottom - rect.top, rect.right - rect.left];
//console.log(element.id);
//console.log(rect.top, rect.right, rect.bottom, rect.left);
});
country.forEach(function(element){
element.addEventListener('click',function(evt){
var loc = cursorPoint(evt);
var rect = element.getBoundingClientRect();
var curr_pan = panZoom.getPan();
var curr_zoom = panZoom.getZoom();
var curr_sizes =panZoom.getSizes();
var real_zoom = curr_sizes.realZoom;
alert(curr_pan.x + " " + curr_pan.y + " " + curr_zoom + " " + real_zoom);
panZoom.reset();
var my_x = my_dict[evt.target.id][3] - svg_rect.left + (my_dict[evt.target.id][5] / 2);
var my_y = my_dict[evt.target.id][0] - svg_rect.top + (my_dict[evt.target.id][4] / 2);
//panZoom.zoomAtPoint(3, {x: loc.x - curr_pan.x - svg_rect.left, y: loc.y - curr_pan.y - svg_rect.top});
panZoom.zoomAtPoint(3, {x: my_x, y: my_y});
alert(evt.target.id + " at " + loc.x +" "+ loc.y);
},false);
});
///svg.addEventListener('click',function(evt){
///var loc = cursorPoint(evt);
///alert(loc.x+" "+loc.y);
///},false);
});
这样,只有在您单击红色国家/地区时才会触发事件。而且,点击的坐标对我来说似乎很精确,我玩了一下,得到了预期的值
尝试最初使用类“.map hover svg”遍历所有元素,并将它们的右上下左添加到以键为id的字典/哈希表中,然后可以使用event.target.id引用这些字典项
然后,您可以使用svg元素的顶部和左侧属性的偏移量以及country path元素的一半宽度和高度来始终缩放到单击的国家的中部:
回答实际问题: 您正在使用的插件通过更改
g.svg-pan-zoom_视口的矩阵来控制变换
,而不是svg
的viewBox
在函数cursorPoint()
中,您一直参照svg
变换鼠标坐标,但放弃了g.svg-pan-zoom\u视口上的基本变换。这就是为什么在调整svg的大小或移动(=转换)时会得到不同的坐标
如果将坐标引用到g.svg-pan-zoom_视口
,则会得到一致的结果
function cursorPoint(evt){
pt.x = evt.clientX; pt.y = evt.clientY;
//return pt.matrixTransform(svg.getScreenCTM().inverse());
var tGroup = document.querySelector('.svg-pan-zoom_viewport');
return pt.matrixTransform(tGroup.getScreenCTM().inverse());
}
另一种方法是更改svg
的viewBox
,而不是使用groups矩阵。然而,既然你的插件是这样工作的,你就应该继续使用它
更新
我玩了一下链接插件,对我来说,函数zoomAtPoint()
做错了什么。让我们假设西班牙在165:165。现在,要始终正确缩放到该位置,您需要在以下操作之前重置它:
panZoom.reset();
panZoom.zoomAtPoint(6, {x: 165, y: 165});
否则,该函数将不执行任何操作或缩放到其他位置
现在要获取“阿根廷”的坐标并缩放到它:
panZoom.reset();
//REM: Apparently the values need some time to adjust after reset() is called, yet is seems to have no callback.
window.setTimeout(function(){
var tViewport = document.querySelector('g.svg-pan-zoom_viewport');
var tMatrix = tViewport.transform.baseVal.getItem(0).matrix;
var tBBox = document.querySelector('#argentina').getBBox();
var tPoint = {x: (tBBox.x + tBBox.width / 2) * tMatrix.a + tMatrix.e, y: (tBBox.y + tBBox.height / 2) * tMatrix.d + tMatrix.f}
//REM: Approximate values, I leave the exact calculation up to you.
panZoom.zoomAtPoint(6, tPoint);
}, 500)
使用示例按钮进行操作:
事实上你很幸运,我开发了一个hugo快捷码来缩放作为url参数传递的SVG中的文本,因此我必须搜索文本,找到它的id,从那里它与你缩放该id的目标相同,因此找到边界框并应用缩放
这里有一个现场演示
源代码将svg平移缩放嵌入hugo短代码中,感兴趣的代码从这里开始
text\u highlight\u缩放(嵌入、svg、元素)
魔法就发生在这里
让e_box=element.getBoundingClientRect();
让svg_box=svg.getBBox();
常量x=(e_-box.x+e_-box.width/2)/svg_-box.width
常量y=(e_-box.y+e_-box.height/2)/svg_-box.height
然后,只需调用svg_pz.zoomAtPoint(z,{x:x,y:y},true)
让我知道这一级别的细节是否对您有帮助,或者如果您有更多问题,请毫不犹豫地询问
作为奖励,您可以为缩放操作获得平滑的css转换,否则用户无法理解发生了什么,您可以获得svg过滤器动画以突出显示目标文本。如果调整页面大小,svg坐标不应更改,除非您没有使用svg坐标(这将是不好的)。另外,路径坐标是什么?路径有分段,而不是x/y坐标。例如,在我的JSFIDLE上,我有一个svg地图,它包含每个国家的id路径,如果我能得到该路径的坐标就好了。你是说它的中心、它的质心、它的分段还是边界框?是的,对不起,该路径的中心,或者一些参考,可以帮助我设置缩放设置路径的bbox,并添加其矩阵以获得精确的边界框。看起来坐标不错,但我如何在我的按钮上实现它以使其缩放到全国?嘿,克里斯蒂安,我已经开始了,检查小提琴:然后让我知道?我想我们只是需要对当前的平移位置进行更多的数学修正。看起来如果你放大它,然后按下按钮,你就不会再以国家为中心了是的,我需要找出如何适应这种情况,对当前平移位置等进行一些数学修正。我认为这就是我们必须将函数放入的地方:var s=instance.getsize()var p=instance.getPan()var x=(s.width/2/relativeX)-s.viewBox.width*s.realZoom instance.pan({x:x,y:0})
等等,但我需要花更多的时间来理解这一点,然后再把它放进去。我希望今天晚些时候能有时间试试:)嘿,克里斯蒂安,我试着创建了一本关于乡村道路元素坐标、高度和宽度的字典,它似乎奏效了!但我最初的问题是在按钮上找到路径的坐标,例如,不是通过点击地图,我只是使用光标函数来显示坐标的变化