首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >D3js:查找路径的边界框(没有getBBox() )?

D3js:查找路径的边界框(没有getBBox() )?
EN

Stack Overflow用户
提问于 2015-04-20 11:36:48
回答 2查看 2.5K关注 0票数 6

以下代码适用于铬:

代码语言:javascript
复制
var node = window.d3.selectAll('#L1 > *:nth-child(2)');
var bbox = node.node().getBBox();
console.log(bbox) // {height: 44, width: 44, y: -13, x: 144}

但与nodejs +jsdom不同:

代码语言:javascript
复制
"TypeError: Object [ PATH ] has no method 'getBBox' "

M. Bostock指出JSDOM 不支持 getBBox()

D3js替换以获得D3js 的边框

过去的努力引领我实现了目标:基于getBBox()小提琴

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-21 07:15:08

路径包围盒

直接挖掘元素的路径数据d="..."应该可以工作。svg行基本上是一组x,y点。假设绝对坐标没有平移,也没有大的bezier曲线,这是我的D3js生成的svg行的情况,我在这个数据中找到xy的最小和最大值。

为此,我将获得d="..." svg行或多行代码。为了简单起见,我粗鲁地删除了可能的相对跳转( h30v20 ),因为我在D3js输出中从未见过这样的跳,然后清除字母(又名svg commands:M、L、H、V、C、S、Q、T、A、Z),简化空格和行跳转,然后再除以其余空格。我得到了一个清晰的坐标阵列。

需要注意的是,我的选择器直接将作为非翻译路径的目标.

代码语言:javascript
复制
var getBBox = function(selector){
    var xmin, xmax, ymin, ymax,p;
    // clean up path
    var t = d3.select(selector).attr("d");  // get svg line's code
    console.log(t)
   t = t.replace(/[a-z].*/g," ") // remove relative coords, could rather tag it for later processing to absolute!
        .replace(/[\sA-Z]+/gi," ").trim().split(" ");  // remove letters and simplify spaces.
    console.log(t)
    
    for(var i in t){    // set valid initial values
        if(t[i].length>1){ 
            p = t[i].split(","); 
            xmin = xmax = p[0]; ymin = ymax = p[1]; }
    }
    for(var i in t){ // update xmin,xmax,ymin,ymax
      p = t[i].split(",");
      if(!p[1]){ p[0]=xmin; p[1] = ymin;} // ignore relative jumps such h20 v-10
      xmin = Math.min(xmin, p[0]);
      xmax = Math.max(xmax, p[0]);
      ymin = Math.min(ymin, p[1]);
      ymax = Math.max(ymax, p[1]);
    } return [[xmin,ymax],[xmax,ymin]]; //  [[left, bottom], [right, top]] as for https://github.com/mbostock/d3/wiki/Geo-Paths#bounds
}
var bb = getBBox("path");

JSfiddle演示

分组包围盒

对于多路径组,您可能需要遍历svg,在组的每个路径上循环,以便更新xmin、ymin、xmax、ymax。

翻译元素

要处理翻译好的元素,请进一步调整。

备选方案

可能还有其他更好的办法。请记住检查getBBox()getBoundingClientRect()在您的上下文中是否可用,因为它们是本地的,非常方便。

票数 4
EN

Stack Overflow用户

发布于 2018-02-21 15:23:59

getBBox/getBoundingClientRect/getClientRect不能在NodeJS+JSDOM中工作的原因是,计算SVG (或NodeJS+JSDOM)元素的这些值需要大量的计算。

首先,必须解析<style>元素中的所有CSS代码(这已经不简单了)。然后,必须应用CSS选择器、级联和继承规则来知道元素的大小、位置或线宽。即使知道了所有的样式属性值,也需要做一些非平凡的数学来计算边框:不同SVG变换函数的定义、这些函数的组合、SVG原语的边框和Bezier曲线。浏览器支持所有这些(为了绘制元素,它们必须支持JSDOM ),但是JSDOM并不是所有这些都要支持的。

但幸运的是,拉布是大部分SVG的JavaScript实现,它使用<canvas>元素绘制图像。它确实支持上面的大部分内容,虽然它没有提供这些数据的接口,但幸运的是它有非常好的(和MIT授权的)代码,所以希望您可以复制和重用其中的部分。到目前为止,代码是在一个文件中编写的,它有CSS解析应用级联规则路径数据解析SVG变换的定义应用变换bezier曲线包围盒计算。也就是说,计算边框所需的几乎所有东西:)但是,它不支持CSS选择器,而是支持可以重用另一个库。但不幸的是,据我所知,还没有准备好在NodeJS中运行,您可能需要进行一些调整。

但是,拉票是一个SVG编译器,它包含旧版的画布是能够在NodeJS中运行的。所以从这个开始就更容易了。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29746785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档