Anh Tuan Nguyen
Anh Tuan Nguyen

Reputation: 979

D3 draw different SVG shapes in one call, no visiblity

I have an Object to store information for svg shapes. It has the following structure:

  Shapes = {
        id: <Shape ID>,
        objType: <Tag Name of Shape e.g ellipse or line>,
        Coordinates: < Object Containing relevant data for drawing >,
        Style:  <Object Containing relevant data for styling>,
 }

Examples for Coordinates and Style could be:
 Shapes.Coordinates = {
     x1: 10, // for Lines
     y1: 10,
     x2: 100,
     y2: 100,
 }

 Shapes.Coordinates = {
     cx: 10 ,// for Circles
     cy: 10,
     r: 10,
 }

 Shapes.Style = {
    fill: "black",
    stroke: "red",
    "stroke-width": 10
 }

Now I want a D3 call to utilise the given data, to draw different shapes, according to the object data. My best idea so far would be the following code:

First I create every shape without attributes, only the ID and Events.

    let objectsRender = svg.selectAll("line") 
                       .data(data)
                       .enter()
                       .append(function(d) {
                         return document.createElement(d.objType);
                       })
                       .attr("id", function(d){ return prefix +d._id;})
                       .attr("class", "no-attr")
                       .on("click",(d)=>{this.modeClick(d);});

Then I add the attributes in a second call, by using a for loop to find the right id, which I think is not a good solution. I can find the "empty" svg tags, by looking for any tag with the class no-attr

let objectsAttributes=  svg.selectAll(".no-attr").each(function(){
    let id= d3.select(this).attr("id");
    let d = null;
    d = data[0];

    for(i = 0;i < props.data.length; i++){
      if(id == prefix +props.data[i]._id){
        d = props.data[i];
        break;
      }
    }

    if( d !== null){
    d3.select(this)
      .attr(d.coordinates)
      .attr(d.style)
      .attr("class", null);
    }

So far this temporary Solution creates all shapes with its relevant attributes. But the shapes are not visible, it's related to the append call.

                       .append(function(d) {
                         return document.createElement(d.objType);
                       })

Can anyone suggest a better solution or tell me, why my svg are not visible on my browser windows, but visible through the development tools?

Upvotes: 2

Views: 70

Answers (1)

Robert Longson
Robert Longson

Reputation: 123995

SVG elements cannot be created with document.createElement, that method can only create html elements.

SVG elements must be created in the SVG namespace via document.createElementNS('http://www.w3.org/2000/svg', <element name>) so I guess in your case you would want

.append(function(d) {
      return document.createElementNS('http://www.w3.org/2000/svg', d.objType);
})

The browser tools are showing you that you've created html elements with the same names as the SVG elements you really want but as they are html elements they are non-functional.

Upvotes: 2

Related Questions