在下面的代码中,我创建了文本SVG元素,对其进行自动换行,然后基于新的(换行的)文本尺寸和矩形创建边界框.我只能用以下方式来做,我想知道代码是否不能简化,以便可能框创建在相同的功能作为文本?

 var a=settings.g.selectAll(".axislabel")
                .data(featureData)
                .join(
                    enter => enter.append("text")
                        .attr("x", d => d.label_coord.x)
                        .attr("y", d => d.label_coord.y)
                        .text(d => d.name)
                        .attr("dy", "0.35em")
                        .call(wrap, 60)
                )
    
    var x=settings.g.selectAll("text")
/getting the elements I just created
    for(let a of x['_groups'][0])
    {
        //iterating through and create bounding boxes
        var v=a.getBBox();
       //createing rectangles based on the boundinx boxes
        settings.g.selectAll("labelBack")
        .data([a.textContent])
        .join(
            enter => enter.append("rect")
                .attr("x", v.x)
                .attr("y", v.y)
                .attr("width", v.width)
                .attr("height", v.height)
                .attr("fill", "white")
                        .attr("opacity", 1)
                        .attr("stroke-width", 1)
                        .attr("stroke", "black")
        );

推荐答案

当您将selection.join与函数参数一起使用时,您传递的函数将构造您想要的DOM元素.因此,您在构建内容时具有很大的灵活性.具体地说,您可以执行如下操作

enter => {
  let g = enter.append("g");
  let rect = g.append("rect");
  let text = g.append("text")
     ...Code to set the text
  rect
    .attr('height', ...Code to set the height)
    .attr('width', ...Code to set the width)

这是可行的,因为文本是在调整矩形大小时设置的.您可以在下面的代码中看到这一点.

信用:虽然这有一点不同,但我的代码部分基于Gerardo's answer here.

  let pad = 2;
  let w = 200;
  let h = 100;
  let svg = d3
    .select('#viz')
    .append("svg")
    .attr("viewBox", [0, 0, w, h])
    .style("max-width", `${640}px`)
    .style('border', 'solid 1px black');
    
   let data = [
    { x: 10, y: 20, text: "This" },
    { x: 56, y: 50, text: "should" },
    { x: 120, y: 20, text: "work" }
  ];

  svg
    .append("g")
    .selectAll(null)
    .data(data)
    .join((enter) => {
      let g = enter.append("g");
      let rect = g.append("rect");
      let text = g
        .append("text")
        .attr("x", (d) => d.x)
        .attr("y", (d) => d.y)
        .text((d) => d.text)
        .call(wrap);
      rect
        .attr("x", (d) => d.x - pad)
        .attr("y", (d) => d.y - d.bbox.height + 2 * pad)
        .attr("width", (d) => d.bbox.width + 2 * pad)
        .attr("height", (d) => d.bbox.height + 2 * pad)
        .attr("fill", "#ddd")
        .attr("stroke", "black");
    });

  function wrap(selection) {
    selection.each(function (d) {
      d.bbox = this.getBBox();
    });
  }
<div id="viz"></div>
<script src="https://d3js.org/d3.v7.min.js"></script>

Javascript相关问答推荐

如何在加载的元数据上使用juserc和await中获得同步负载?

获取加载失败:获取[.]添加时try 将文档添加到Firerestore,Nuxt 3

如何获取转换字节的所有8位?

zoom svg以适应圆

在Angular中将样式应用于innerHTML

使用复选框在d3.js多折线图中添加或删除线条

将2D数组转换为图形

Angular material 拖放堆叠的牌副,悬停时自动展开&

WebRTC关闭navigator. getUserMedia正确

setcallback是什么时候放到macrotask队列上的?

如何从隐藏/显示中删除其中一个点击?

单个HTML中的多个HTML文件

Reaction组件在本应被设置隐藏时仍显示

将数组扩展到对象中

expo 联系人:如果联系人的状态被拒绝,则请求访问联系人的权限

OnClick更改Json数组JSX中的图像源

通过跳过某些元素的对象进行映射

使用props 将VUE 3组件导入JS文件

ReactJS在类组件中更新上下文

如何创建一个for循环,用于计算仪器刻度长度并将其放入一个HTML表中?