[英]Positioning SVG elements via .getBoundingClientRect() in variable-width div
我有一個煩人的問題。
我正在嘗試根據一堆共享相似屬性的SVG文本元素來定位一堆SVG圓形元素。
circle元素的創建過程與文本元素的創建過程非常不同,因此,僅使用與舊元素相同的變換等方式來放置新元素不是可行的選擇。
我正在嘗試使用.getBoundingClientRect()來獲取位置,因為文本元素已轉換為位置(因此.getBBox()不是一個選擇),而不是通過x和y屬性進行定位。
使用.getBoundingClientRect(),我可以獲取新元素的正確大小/排列,但是由於包含svg的div的寬度是可變的,因此總有些奇怪的偏移量,我無法完全解決。
我在這里創建了我的問題的簡化示例。 調整頁面大小並刷新,以查看實際存在的問題。
我用來放置圓形元素的代碼復制如下。
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) + ")";
})
編輯:
這是一個非常延遲的更新,只是要注意,盡管我無法回答我所說的問題,但我能夠根據Paul LeBeau的建議從目標元素中提取轉換,從而提出了可行的解決方案。
就我而言,我不得不使用一系列連續的轉換,而不是轉換和更改x / y位置的組合(由於鏈接示例中未顯示的項目的某些實際情況)。 但我很高興找到答案!
您的示例在Chrome上對我來說效果很好。 但這確實是因為SVG是頁面上唯一的內容。 如果我在SVG上方添加一些文本,一切都會出錯。
https://jsfiddle.net/rrpfmm6d/1/
這是您正在談論的問題嗎?
如果是這樣,原因是因為您在使用getBoundingClientRect()
選擇錯誤。 它在屏幕空間中提供坐標。 它的原點是窗口的左上角(如果是jsfiddle,則為iframe)。
您應該使用getBBox()
。 它返回的值與SVG元素在同一坐標空間中。 它的起源(通常)在SVG的左上方。
總之,請使用在<text>
元素上調用getBBox()
返回的坐標來計算圓的位置。 如果將圓插入到與文本相同的SVG中,則無需對div或svg偏移進行任何調整。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.