Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何从SVG中的path元素获取X,Y坐标?_Javascript_Jquery_Svg_Svgpanzoom - Fatal编程技术网

Javascript 如何从SVG中的path元素获取X,Y坐标?

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()

这里是一把小提琴的实际拥有。

我正在使用一个库来缩放和平移SVG。 我有一个按钮,当点击它放大西班牙的例子,所以我把坐标在:

   $("#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})
等等,但我需要花更多的时间来理解这一点,然后再把它放进去。我希望今天晚些时候能有时间试试:)嘿,克里斯蒂安,我试着创建了一本关于乡村道路元素坐标、高度和宽度的字典,它似乎奏效了!但我最初的问题是在按钮上找到路径的坐标,例如,不是通过点击地图,我只是使用光标函数来显示坐标的变化