简体   繁体   中英

I'm having trouble getting multiple isotype graphs on one page. I think the problem may be with the svg <use> element .selectAll("use")

Here's a link to http://bl.ocks.org/alansmithy/d832fc03f6e6a91e99f4 This code uses a jquery slider to control the txt value and number of filled icons. I've hard-coded in an input value, but I would also like to be able to have multiple Isotype charts on one page. The text value correct, but the fill value (amount of icons filled) is the same for both charts.

var svgDoc=d3.select("body").append("svg").attr("viewBox","0 0 105 25");

svgDoc.append("defs")
.append("g")
.attr("id","iconCustom")
.append("path")
        .attr("d","M3.5,2H2.7C3,1.8,3.3,1.5,3.3,1.1c0-0.6-0.4-1-1-1c-0.6,0-1,0.4-1,1c0,0.4,0.2,0.7,0.6,0.9H1.1C0.7,2,0.4,2.3,0.4,2.6v1.9c0,0.3,0.3,0.6,0.6,0.6h0.2c0,0,0,0.1,0,0.1v1.9c0,0.3,0.2,0.6,0.3,0.6h1.3c0.2,0,0.3-0.3,0.3-0.6V5.3c0,0,0-0.1,0-0.1h0.2c0.3,0,0.6-0.3,0.6-0.6V2.6C4.1,2.3,3.8,2,3.5,2z");

svgDoc.append("rect").attr("width",105).attr("height",25);

var numCols = 25;
var numRows = 2;
var xPadding = 2;
var yPadding = 8;

var hBuffer = 8;
var wBuffer = 4;

var myIndex=d3.range(numCols*numRows);

svgDoc.append("text")
.attr("id","txtValue")
.attr("x",xPadding)
.attr("y",yPadding)
.attr("dy",-3)
.text("0");

svgDoc.append("g")
.attr("id","pictoLayer")
.selectAll("use")
.data(myIndex)
.enter()
.append("use")
    .attr("xlink:href","#iconCustom")
    .attr("id",function(d)    {
        return "icon"+d;
    })
    .attr("x",function(d) {
        var remainder=d % numCols;//calculates the x position (column number) using modulus
        return xPadding+(remainder*wBuffer);//apply the buffer and return value
    })
      .attr("y",function(d) {
        var whole=Math.floor(d/numCols)//calculates the y position (row number)
        return yPadding+(whole*hBuffer);//apply the buffer and return the value
    })
    .classed("iconPlain",true);

var data = { percent: 75 };

///function to draw the chart:

function drawIsotype(dataObject) {
valueLit = dataObject.percent;
total = numCols * numRows;
valuePict = total * (dataObject.percent / 100);

  d3.select("#txtValue").text(valueLit + '%');
  d3.selectAll("use").attr("class", function (d, i) {
  if (d < valuePict ) {
      return "iconSelected";
  } else {
      return "iconPlain";
  }
  });
  }

drawIsotype(data);

///This is a complete graph. If I make another with different variable names, I can get the 2nd graph, but the icons are filled incorrectly.

 var svgDoc2=d3.select("#svg2").append("svg").attr("viewBox","0 0 105 45");

svgDoc2.append("defs")
.append("g")
.attr("id","iconCustom")
.append("path")
        .attr("d","M3.5,2H2.7C3,1.8,3.3,1.5,3.3,1.1c0-0.6-0.4-1-1-1c-0.6,0-1,0.4-1,1c0,0.4,0.2,0.7,0.6,0.9H1.1C0.7,2,0.4,2.3,0.4,2.6v1.9c0,0.3,0.3,0.6,0.6,0.6h0.2c0,0,0,0.1,0,0.1v1.9c0,0.3,0.2,0.6,0.3,0.6h1.3c0.2,0,0.3-0.3,0.3-0.6V5.3c0,0,0-0.1,0-0.1h0.2c0.3,0,0.6-0.3,0.6-0.6V2.6C4.1,2.3,3.8,2,3.5,2z");

svgDoc2.append("rect").attr("width",105).attr("height",35);

var numCols2 = 25;
var numRows2 = 3;
var xPadding2 = 2;
var yPadding2 = 8;
var hBuffer2 = 8;
var wBuffer2 = 4;

var myIndex2=d3.range(numCols2*numRows2);

svgDoc2.append("text")
.attr("id","txtValue2")
.attr("x",xPadding2)
.attr("y",yPadding2)
.attr("dy",-3)
.text("0");

svgDoc2.append("g")
.attr("id","pictoLayer")
.selectAll("use")
.data(myIndex2)
.enter()
.append("use")
    .attr("xlink:href","#iconCustom")
    .attr("id",function(e)    {
        return "icon"+e;
    })
    .attr("x",function(e) {
        var remainder=e % numCols2;//calculates the x position (column number) using modulus
        return xPadding2+(remainder*wBuffer2);//apply the buffer and return value
    })
      .attr("y",function(e) {
        var whole=Math.floor(e/numCols2)//calculates the y position (row number)
        return yPadding2+(whole*hBuffer2);//apply the buffer and return the value
    })
    .classed("iconPlain2",true);

var data2 = { percent2: 55 };

function drawIsotype2(dataObject2) {
valueLit2 = dataObject2.percent2;
total2 = numCols2 * numRows2;
valuePict2 = total2 * (dataObject2.percent2 / 100);

    d3.select("#txtValue2").text(valueLit2 + '%');
d3.selectAll("use").attr("class", function (e, i) {
    if (e < valuePict2 ) {
        return "iconSelected2";
    } else {
        return "iconPlain2";
    }
});

}
drawIsotype2(data2);

There is not a big visual difference between the 2 path definitions.

Problem is that they have the same id . An id should be unique in an HTML DOM.

.attr("id","iconCustom2")  // for defs

and

.attr("xlink:href","#iconCustom2")  // for use

will solve the reference issue.

And you need to select the use tags in a particular svg. The following simplifies the class attribute setting. You can comment a few lines.

// .classed("iconPlain",true);
// .classed("iconPlain2",true);

svgDoc.selectAll("use").classed("selected", d => d < valuePict );

svgDoc2.selectAll("use").classed("selected", d => d < valuePict2 );

You need to change your CSS a bit

.selected {fill:steelblue;}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM