iMarh
iMarh

Reputation: 188

Appending non-nested elements

I'm building svg with D3. I want to use clipping for the path element, but I have problem appending the defs section for the clipPath.

Here is my code:

function build_svg(div,width,height) {
    var margin={left: 10, top: 20}; 
    return div.append("svg")
    .attr("width", "100%")
    .attr("height", "100%")
    .append("defs")
    .append("clipPath")
        .append("rect")
        .attr("x", margin.left)
        .attr("y", margin.top)
        .attr("width", width)
        .attr("height", height)
    .insert("g","defs")
    .attr("transform", "translate("+margin.left+","+margin.top+")");
}

I'm getting this:

<svg width="100%" height="100%">
    <defs>
        <clipPath>
            <rect x="40" y="10" width="651" height="214">
                <g transform="translate(40,10)">
                .....
                </g>
            </rect>
        </clipPath>
    </defs>
</svg>

But I want this:

<svg width="100%" height="100%">
    <defs>
        <clipPath>
            <rect x="40" y="10" width="651" height="214"></rect>
        </clipPath>
    </defs>
    <g transform="translate(40,10)">
       .......
    </g>
</svg>

Where is my mistake?

Upvotes: 2

Views: 63

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102218

Right now you have a single chain, and therefore the structure you're getting is the expected one.

So, instead of that, break your chain. First, name the SVG selection:

const svg = div.append("svg")
    .attr("width", "100%")
    .attr("height", "100%");

And then:

svg.append("defs")
    .append("clipPath")
    .append("rect")
    .attr("x", margin.left)
    .attr("y", margin.top)
    .attr("width", width)
    .attr("height", height);

svg.append("g", "defs")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

Pay attention to the fact that you want to append the group, not insert it.

Here is the demo, run it and inspect the SVG:

function build_svg(div, width, height) {
  var margin = {
    left: 10,
    top: 20
  };

  const svg = div.append("svg")
    .attr("width", "100%")
    .attr("height", "100%");

  svg.append("defs")
    .append("clipPath")
    .append("rect")
    .attr("x", margin.left)
    .attr("y", margin.top)
    .attr("width", width)
    .attr("height", height);

  svg.append("g", "defs")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
};

const div = d3.select("#myDiv");
build_svg(div, 200, 200)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="myDiv"></div>

You'll see this structure:

<svg width="100%" height="100%">
  <defs>
    <clipPath>
      <rect x="10" y="20" width="200" height="200"></rect>
    </clipPath>
  </defs>
  <g transform="translate(10,20)"></g>
</svg>

Upvotes: 4

Related Questions