我有一个问题是使用D3一个接一个地定位css web-font样式,svg文本元素。当我第一次在加载时定位文本元素时,它们将重叠。
然而,当我稍后使用在延迟或按钮上触发的相同功能定位元素时,它们不会重叠。
该问题似乎与getBBox()
和getBoundingClientRect()
一起出现,但两者都没有首先返回元素的正确宽度。
关于如何获得正确宽度的任何想法?
JS如下,一个例子在这里: http://bl.ocks.org/yanofsky/6618496 和完整的代码: https://gist.github.com/yanofsky/6618496
//helper function to grab transform coordinates
function transformCoordOf(elem) {
var separator = elem.attr("transform").indexOf(",") > -1 ? "," : " ";
var trans = elem.attr("transform").split(separator);
return { x: (trans[0] ? parseFloat(trans[0].split("(")[1]) : 0), y: (trans[1] ? parseFloat(trans[1].split(")")[0] ): 0) };
}
//position the elements based on the one before it
function positionElements() {
txts.filter(function(d,i){return i != 0}) //filter out the first element
.attr("transform",function(d,i){
var prev = d3.select(txts[0][i]), //use i b/c the list shifts on filter
prevWidth = parseFloat(prev.node().getBoundingClientRect().width)
prevCoords = transformCoordOf(prev);
var cur = d3.select(this),
curWidth = parseFloat(cur.node().getBoundingClientRect().width)
curCoords = transformCoordOf(cur);
var y = prevCoords.y,
x = prevCoords.x + prevWidth + 10;
return "translate("+x+","+y+")";
})
}
var names = ["apples","oranges","bananas"]
var canvas = d3.select("#content")
.append("svg")
.attr("width","600px")
.attr("height","100px");
var txts = canvas.selectAll("text").data(names)
.enter()
.append("text")
.attr("transform","translate(10,50)")
.text(function(d){return d});
positionElements()
d3.select("button").on("click",function(){positionElements()})
答案 0 :(得分:2)
我还没有尝试过浏览器加载事件(我几乎也不了解网络字体),但是当我们遇到这个问题时(尽管仍在使用Chartbuilder),我们使用WebFontLoader解决了这个问题并等待对于active event。这有一个问题:文本必须出现在页面上才能加载,所以你需要一个使用你的字体的隐藏跨度(或其他)。
这是我们的代码(我们从fonts.com加载字体:
WebFont.load({
monotype: {
projectId: '65980087-55e2-40ca-85ae-729fca359467',
},
active: function(name) {
$(document).ready(function() {
ChartBuilder.start();
});
}
});
附录:我认为它确实没有任何实际意义,但我们也转而使用getComputedTextLength()
而不是测量边界框,只是因为它似乎更正确。请参阅the code here。
答案 1 :(得分:1)
在您首次呈现<text>
元素并测量其宽度时,尚未下载您引用的字体。所以在这个时间点你得到一个较小的宽度,你可以在加载引用的字体之后得到它。
等待浏览器的加载事件(如Robert suggests)是值得尝试的,但我不确定它是否适用于所有浏览器。我之前读到的一些内容暗示某些浏览器实际上并没有加载远程@ font-face字体,直到遇到第一个用法而不仅仅是CSS声明。但我没有任何经验,所以我不肯定。
这是一个related SO question,它有很多关于@ font-face和下载时间的完整答案。