javascript 使用 D3.js 计算 SVG 路径质心
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12062561/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calculate SVG Path Centroid with D3.js
提问by Zikes
I'm using the SVG located at http://upload.wikimedia.org/wikipedia/commons/3/32/Blank_US_Map.svgin a project and interacting with it with d3.js. I'd like to create a click to zoom effect like http://bl.ocks.org/2206590, however that example relies on path data stored in a JSON object to calculate the centroid. Is there any way to load path data in d3 from an existing SVG to get the centroid?
我在项目中使用位于http://upload.wikimedia.org/wikipedia/commons/3/32/Blank_US_Map.svg的 SVG并与 d3.js 进行交互。我想创建一个点击缩放效果,如http://bl.ocks.org/2206590,但是该示例依赖于存储在 JSON 对象中的路径数据来计算质心。有没有办法从现有的SVG加载d3中的路径数据以获得质心?
My (hackish) attempt so far:
到目前为止我的(hackish)尝试:
function get_centroid(sel){
var coords = d3.select(sel).attr('d');
coords = coords.replace(/ *[LC] */g,'],[').replace(/ *M */g,'[[[').replace(/ *z */g,']]]').replace(/ /g,'],[');
return d3.geo.path().centroid({
"type":"Feature",
"geometry":{"type":"Polygon","coordinates":JSON.parse(coords)}
});
}
This seems to work on some states, such as Missouri, but others like Washington fail because my SVG data parsing is so rudimentary. Does d3 support something like this natively?
这似乎适用于某些州,例如密苏里州,但其他州(例如华盛顿州)失败了,因为我的 SVG 数据解析非常初级。d3 本身是否支持这样的东西?
回答by nrabinowitz
The D3 functions all seem to assume you're starting with GeoJSON. However, I don't actually think you need the centroid for this - what you really need is the bounding box, and fortunately this is available directly from the SVG DOM interface:
D3 函数似乎都假设您从 GeoJSON 开始。然而,我实际上并不认为你需要质心——你真正需要的是边界框,幸运的是,这可以直接从 SVG DOM 界面获得:
function getBoundingBoxCenter (selection) {
// get the DOM element from a D3 selection
// you could also use "this" inside .each()
var element = selection.node();
// use the native SVG interface to get the bounding box
var bbox = element.getBBox();
// return the center of the bounding box
return [bbox.x + bbox.width/2, bbox.y + bbox.height/2];
}
This is actually slightly better than the true centroid for the purpose of zooming, as it avoids some projection issues you might otherwise run into.
就缩放而言,这实际上比真正的质心略好,因为它避免了一些您可能会遇到的投影问题。
回答by Neil Ruud
The accepted answer was working great for me until I tested in Edge. I can't comment since I don't have enough karma or whatever but was using this solution and found an issue with Microsoft Edge, which does not use x or y, just top/left/bottom/right, etc.
在我在 Edge 中进行测试之前,接受的答案对我来说非常有用。我无法发表评论,因为我没有足够的 karma 或其他什么,但是正在使用此解决方案并发现 Microsoft Edge 存在问题,它不使用 x 或 y,仅使用顶部/左侧/底部/右侧等。
So the above code should be:
所以上面的代码应该是:
function getBoundingBoxCenter (selection) {
// get the DOM element from a D3 selection
// you could also use "this" inside .each()
var element = selection.node();
// use the native SVG interface to get the bounding box
var bbox = element.getBBox();
// return the center of the bounding box
return [bbox.left + bbox.width/2, bbox.top + bbox.height/2];
}