【问题标题】:Finding Offset Position of SVG Element查找 SVG 元素的偏移位置
【发布时间】:2012-10-13 23:45:01
【问题描述】:

我在使用 D3 时经常遇到这个问题。很多时候我喜欢在我的 SVG 上覆盖 HTML 对象。

我当前的策略是在名为 .html-overlay 的 SVG 元素旁边创建一个空 DIV。我根据我在 SVG 中为主图形设置的内部填充来定位它(例如:20px)。然后我使用以下函数(使用 jQuery)来确定 HTML 元素的位置:

//element is the object returned by D3 .append()
var getOffset: function(element) {
        var $element = $(element[0][0]);
        return {
            left: $element.offset().left - $('.html-overlay').offset().left,
            top: $element.offset().top - $('.html-overlay').offset().top
        };
    }

我想知道,必须有一些内部(不依赖于 jQuery)的方法来快速获取元素的偏移量。它非常有用(尤其是在元素经过多次平移、旋转、缩放等之后)

如果有函数来计算元素“中心”的偏移量、元素的最高点、最底部、最左边、最右边等,那也是很棒的。

注意:

getBoundingClientRect() 由于某种原因没有给出正确的数字:

var $element = $(element[0][0]);

            console.log($element.offset(), element[0][0].getBoundingClientRect())
Object
left: 328
top: 248.8333282470703
__proto__: Object

ClientRect
bottom: 376.83331298828125
height: 139.99998474121094
left: 328
right: 478
top: 236.8333282470703
width: 150

【问题讨论】:

  • 你有没有得到一个好的答案?我也很感兴趣。
  • 不,刚刚结束了使用jQuery的偏移量。

标签: d3.js


【解决方案1】:

你试过了吗

var xywh =element[0][0].getBoundingClientRect();

好像什么都有? (原文在this post

【讨论】:

  • getBoundingClientRect() 由于某种原因没有给出正确的数字: var $element = $(element[0][0]); console.log($element.offset(), element[0][0].getBoundingClientRect()) ` ` Object left: 328 top: 248.8333282470703 proto: Object ClientRect bottom: 376.83331298828125 height: 139.99998474121094 left :328 右:478 上:236.8333282470703 宽度:150
  • 您的问题是 d3 特定的吗?当您遇到问题时,您能否提供一些简短版本(但完整)的代码。我创建了jsfiddle.net/hpHkb/13,其中显示所有 3 个函数 bRect、offset 和 position 显示相同的正确值(相对于文档)以及平移和旋转......甚至可能不需要包含 jquery 并将其与 d3 混合。跨度>
  • 只是在这里添加一个注释,而不是使用[0][0],你可以使用d3的node方法:element.node().getBoundingClientRect()
  • 添加scrollFirefoxOffset = document.documentElement.scrollTop;和 scrollOffsetChrome = document.body.scrollTop;到 getBoundingClientRect().top 以获取滚动偏移量。看来 Chrome 和 Firefox 需要不同的功能。
【解决方案2】:

问题在于getBoundingClientRect,它没有考虑滚动位置或元素相对于文档的容器位置。它只会报告那个项目相对于文档顶部和左侧坐标的确切位置。

我创建了一个 d3 方法,它将报告元素的位置。它的工作原理是遍历父元素,直到找到容器 SVG,然后考虑该项目在计算中的位置。它返回您通常会从getBoundingClientRect 收到的内容。

方法如下:

d3.selection.prototype.position = function() {

    var el = this.node();
    var elPos = el.getBoundingClientRect();
    var vpPos = getVpPos(el);

    function getVpPos(el) {
        if(el.parentElement.tagName === 'svg') {
            return el.parentElement.getBoundingClientRect();
        }
        return getVpPos(el.parentElement);
    }

    return {
        top: elPos.top - vpPos.top,
        left: elPos.left - vpPos.left,
        width: elPos.width,
        bottom: elPos.bottom - vpPos.top,
        height: elPos.height,
        right: elPos.right - vpPos.left
    };

};

你可以这样使用:

d3.select(element).position()

请注意,我实际上并没有在此处添加代码来考虑滚动位置。

【讨论】:

  • 缺少getPositionViewPort .. 你能补充一下吗
  • 更改 getPositionViewport(el.parentElement);返回 getVpPos(el.parentElement);
  • 很好的解决方案,也适用于我们这些不使用 D3.js,但仍在努力寻找 svg 元素的位置的人。请注意下面我对 IE 支持的回答。
  • 由于我只是自己编写代码,您可以将 getVpPos 替换为:if (elem instanceof SVGElement && !(elem instanceof SVGSVGElement)) elem = elem.ownerSVGElement;
【解决方案3】:

扩展 James Lai 的答案以支持现代版本的 IE:

function getVpPos(el) {
    if(el.parentNode.nodeName === 'svg') {
        return el.parentNode.getBoundingClientRect();
    }
    return getVpPos(el.parentNode);
}

注意:parentElement 改为 parentNode tagName 更改为 nodeName

【讨论】:

    猜你喜欢
    • 2011-06-11
    • 2013-03-07
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    相关资源
    最近更新 更多