通过.getBoundingClientRect()在可变宽度div中定位SVG元素 [英] Positioning SVG elements via .getBoundingClientRect() in variable-width div

查看:867
本文介绍了通过.getBoundingClientRect()在可变宽度div中定位SVG元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个恼人的问题。

我试图根据现有的一组SVG文本元素定位一堆SVG圆圈元素类似的属性。

I'm trying to position a bunch of SVG circle elements according to an existing bunch of SVG text elements that share similar properties.

圆形元素在一个非常独立的过程中创建,而不是文本元素,因此,使用与旧的元素相同的变换等定位新的元素。是一个可行的选项。

The circle elements are created in a very separate process than the text elements, so positioning the new elements just using the same transforms etc. as the old one isn't a viable option.

我试图使用.getBoundingClientRect()获取位置,因为文本元素被转换为位置(所以.getBBox

I'm trying to use .getBoundingClientRect() to get the positions since the text elements are transformed into position (so .getBBox() isn't an option) rather than positioned by x and y attributes.

使用.getBoundingClientRect(),我可以得到新元素的正确大小/排列,但是由于包含svg的div的宽度是可变的,总是有一些奇怪的偏移,我不能说明。

With .getBoundingClientRect(), I can get the correct size/arrangement of the new elements, but since the width of the svg-containing div is variable, there's always a bit of a weird offset that I can't quite account for.

我创建了一个简单的例子请在此发布。调整页面大小并刷新页面以查看操作中的问题。

I created a simplified example of my issue here. Resize and refresh the page to see the issue in action.

下面复制了用于定位圆形元素的代码。

The code I use to position the circle elements is replicated below.

var circs = theSvg.selectAll("circle")
    .data(theCircles)
    .enter()
    .append("circle")
    .attr("r", 15)
    .attr("fill", "#f00")
    .style("opacity", 0.3)
    .attr("transform", function(d){

      var sizeDif = 800/(d3.select(".svgTestHolder")[0][0].getBoundingClientRect()["width"]);

      var theNum = parseInt(d.split("&")[1]);
      var thePosition = theSvg.selectAll("text").filter(function(e){
      return e == theNum;})[0];
      var theCoords = thePosition[0].getBoundingClientRect();

      var leftOffset = d3.select(".svgTestHolder")[0][0].getBoundingClientRect()["left"];
      var leftOffset2 = d3.select(".svgTest")[0][0].getBoundingClientRect()["left"];
      var bottomOffset = d3.select(".svgTestHolder")[0][0].getBoundingClientRect()["top"];
      var bottomOffset2 = d3.select(".svgTest")[0][0].getBoundingClientRect()["top"];

      return
      "translate(" + ((theCoords["left"] - leftOffset - leftOffset2)  
       * sizeDif) + "," + ((theCoords["top"] - bottomOffset - bottomOffset2) 
       * sizeDif) + ")";
 })

编辑:

这是一个非常延迟的更新,只是要注意,虽然我无法回答我的问题,我说的是,我能够基于保罗LeBeau的建议提取目标元素的变换一个可行的解决方案。

This is a very delayed update just to note that while I was unable to answer my question as stated, I was able to make a workable solution based on Paul LeBeau's suggestion to extract the transforms from the target element.

在我的例子中,我不得不使用一系列连续的变换而不是变换和改变x / y位置的组合(由于项目的某些现实情况, )。但我很高兴找到了答案。

In my case, I had to use a series of consecutive transforms rather than a combination of transforming and changing the x/y position (due to certain realities of the project not represented in the linked example). But I'm happy to have found an answer!

推荐答案

您的示例在Chrome上适用于我。但是真的只是因为SVG是页面上唯一的东西。如果我在SVG上面添加一些文本,一切都会出错。

Your example works fine for me on Chrome. But really that's only because the SVG is the only thing on the page. If I add some text above the SVG everything goes wrong.

https://jsfiddle.net/rrpfmm6d/1/

这是你所说的问题吗?

如果是这样,原因是因为您在使用 getBoundingClientRect()时做错了选择。它提供屏幕空间中的坐标。它的起源是窗口的左上角(或者在jsfiddle的情况下是iframe)。

If so, the reason is because you are making the wrong choice in using getBoundingClientRect(). It provides coordinates in screen space. It's origin is the top left of the window (or iframe in the case of jsfiddle).

你应该使用 getBBox c $ c>。返回的值与SVG元素位于相同的坐标空间中。

You should be using getBBox(). The values it returns are in the same coordinate space as the SVG elements. It's origin is (normally) at the top left of the SVG.

总之,使用调用 getBBox()< text> 元素上计算您圈子的位置。如果圆圈插入到与文本相同的SVG中,则不需要使用div或svg偏移量进行任何调整。

In summary, use the coordinates returned by calling getBBox() on your <text> element to calculate the position for your circle. If the circles are inserted into the same SVG as the text, there will be no need to do any adjusting with the div or svg offsets.

这篇关于通过.getBoundingClientRect()在可变宽度div中定位SVG元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆