我在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
答案 0 :(得分:16)
var xywh =element[0][0].getBoundingClientRect();
似乎拥有一切吗? (原始解决方案在this post)
答案 1 :(得分:11)
问题在于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()
请注意,我实际上并未在此处添加代码来考虑滚动位置。
答案 2 :(得分:0)
扩展James Lai的答案以支持IE的现代版本:
function getVpPos(el) {
if(el.parentNode.nodeName === 'svg') {
return el.parentNode.getBoundingClientRect();
}
return getVpPos(el.parentNode);
}
注意: parentElement 更改为 parentNode tagName 更改为 nodeName 。