Search code examples
javascriptd3.jsword-wrapd3plus

d3Plus and wrapping text


I'm trying to use D3plus to wrap text - i'm starting to understand how it is to make text in a SVG wrap. However, i keep getting errors that are either to do with d3Plus or my code - the documentation with D3 is pretty sparse, so i'm looking to get some assistance on where i have been going wrong. Cheers.

JS

<script>

var dataPoints = [
    ["Arsenal", -0.0032967741593940836, 0.30399753945657115],
    ["Chelsea", 0.2752159801936051, -0.0389675484210763],
    ["Liverpool", -0.005096951348655329, 0.026678627680541075],
    ["Manchester City", -0.004715381791104284, -0.12338379196523988],
    ["Manchester United", 0.06877966010653305, -0.0850615090351779],
    ["Tottenham", -0.3379518099485709, -0.09933664174939877]
];

var teamData = [
    ["Arsenal", "@arsenal", "world", "cup", "arsenal", "💭", "@sahil_adhikaari", "win", "@hectorbellerin", "man", "season"],
    ["Chelsea", "f", "g", "h", "i", "j"],
    ["Liverpool", "l", "m", "m", "o", "p"],
    ["Manchester City", "q", "r", "s", "t", "u"],
    ["Manchester United", "v", "w", "x", "y", "z"],
    ["Tottenham", "1", "2", "3 ", "4", "5"]
];

const colours = d3.scaleOrdinal()
    .domain(dataPoints)
    .range(["#F8B195", "#F67280", "#C06C84", "#6C5B7B", "#355C7D", "#2A363B"]);

var canvasW = 700;
var canvasH = 600;   
var w = 365;
var h = 365;
var xPadding = 30;
var yPadding = 20;
var padding = 10;
var border = 0.5;
var bordercolor = 'black';

var xScale = d3.scaleLinear()
    .range([xPadding, w - padding])
    .domain([-1, 1]);

var yScale = d3.scaleLinear()
    .range([h - yPadding, padding])
    .domain([-1, 1]);

var svg = d3.select('body')
    .append("svg")
    .attr('width', canvasW)
    .attr('height', canvasH);

var circles = svg.selectAll("circle")
    .data(dataPoints)
    .enter()
    .append("circle")
    .attr("r", 7)
    .attr("cx", function(d) { return xScale(d[1]); })
    .attr("cy", function(d) { return yScale(d[2]); })
    .on('click', function(d, i) {
        console.log("click", d[0]);
    })
    .attr("fill", function(d) {
        var result = null;

        if (dataPoints.indexOf(d) >= 0) {
            result = colours(d);
        } else {
            result = "white";
        }
        return result;               
    });

var legend = svg.selectAll(".legend")
    .data(colours.domain())
    .enter()
    .append("g")
    .attr("class", "legend")
    .attr("transform", function(d, i) { return "translate(0," + i * 29 + ")"; });

legend.append("rect")
    .attr("x", canvasW - 184)
    .attr("y", 11)
    .attr("width", 18)
    .attr("height", 18)
    .style("fill", colours);

legend.append("text")
    .attr("x", canvasW - 194)
    .attr("y", 20)
    .attr("dy", ".35em")
    .style("text-anchor", "end")
    .text(function(d) { return d[0];})

var borderPath = svg.append("rect")
    .attr("x", 5)
    .attr("y", 5)
    .attr("height", h)
    .attr("width", w)
    .style("stroke", bordercolor)
    .style("fill", "none")
    .style("stroke-width", border);

var textBox = svg.append("g")
    .attr("transform", "translate(5,385)");

textBox.append("rect")
    .attr("id", "target")
    .attr("height", 150)
    .attr("width", 529)
    .style("stroke", bordercolor)
    .style("fill", "none")
    .style("stroke-width", border);

    filter();
    function filter(d) {
    d3.select("body").selectAll(null);
        circles.on("click", filter);
        var filterss = teamData.filter(e => e[0] === d[0])[0];
        var team = filterss.slice(0, 1);
        filterss = filterss.slice(1, filterss.length);
        team = team + ": "
        filterss = filterss.join(", ")
        console.log(team + filterss);

  new d3plus.TextBox()
    .select(textBox.node())
    .data(team + filterss)
    .text( function(d){ return d; })
    .width(textBox.select('rect').attr("width"))
    .fontSize(20)
    .render();
}

The Error


Solution

  • If you look at the line the error is occurring at when importing d3plus, you'll see this;

     d3.scale.ordinal()
    

    That's d3 version 3 syntax, while it looks like you are using d3 version 4.

    It looks like you want this library for version 4 (and it's specific to text-wrapping).

    And here's an example merging the new API with your code snippet:

    <!DOCTYPE html>
    <html>
    
    <head>
      <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
      <script src="https://d3plus.org/js/d3plus-text.v0.9.full.min.js"></script>
    </head>
    
    <body>
      <script>
        var dataPoints = [
          ["Arsenal", -0.0032967741593940836, 0.30399753945657115],
          ["Chelsea", 0.2752159801936051, -0.0389675484210763],
          ["Liverpool", -0.005096951348655329, 0.026678627680541075],
          ["Manchester City", -0.004715381791104284, -0.12338379196523988],
          ["Manchester United", 0.06877966010653305, -0.0850615090351779],
          ["Tottenham", -0.3379518099485709, -0.09933664174939877]
        ];
    
        teamData = [
          ["Arsenal", "@arsenal", "world", "cup", "arsenal", "💭", "@sahil_adhikaari", "win", "@hectorbellerin", "man", "season"],
          ["Chelsea", "f", "g", "h", "i", "j"],
          ["Liverpool", "l", "m", "m", "o", "p"],
          ["Manchester City", "q", "r", "s", "t", "u"],
          ["Manchester United", "v", "w", "x", "y", "z"],
          ["Tottenham", "1", "2", "3 ", "4", "5"]
        ];
    
        const colours = d3.scaleOrdinal()
          .domain(dataPoints)
          .range(["#F8B195", "#F67280", "#C06C84", "#6C5B7B", "#355C7D", "#2A363B"]);
    
        var canvasW = 700;
        var canvasH = 600;
        var w = 365;
        var h = 365;
        var xPadding = 30;
        var yPadding = 20;
        var padding = 10;
        var border = 0.5;
        var bordercolor = 'black';
    
        var xScale = d3.scaleLinear()
          .range([xPadding, w - padding])
          .domain([-1, 1]);
    
        var yScale = d3.scaleLinear()
          .range([h - yPadding, padding])
          .domain([-1, 1]);
    
        var svg = d3.select('body')
          .append("svg")
          .attr('width', canvasW)
          .attr('height', canvasH);
    
        var circles = svg.selectAll("circle")
          .data(dataPoints)
          .enter()
          .append("circle")
          .attr("r", 7)
          .attr("cx", function(d) {
            return xScale(d[1]);
          })
          .attr("cy", function(d) {
            return yScale(d[2]);
          })
          .on('click', function(d, i) {
            console.log("click", d[0]);
          })
          .attr("fill", function(d) {
            var result = null;
    
            if (dataPoints.indexOf(d) >= 0) {
              result = colours(d);
            } else {
              result = "white";
            }
            return result;
          });
    
        var legend = svg.selectAll(".legend")
          .data(colours.domain())
          .enter()
          .append("g")
          .attr("class", "legend")
          .attr("transform", function(d, i) {
            return "translate(0," + i * 29 + ")";
          });
    
        legend.append("rect")
          .attr("x", canvasW - 184)
          .attr("y", 11)
          .attr("width", 18)
          .attr("height", 18)
          .style("fill", colours);
    
        legend.append("text")
          .attr("x", canvasW - 194)
          .attr("y", 20)
          .attr("dy", ".35em")
          .style("text-anchor", "end")
          .text(function(d) {
            return d[0];
          })
    
        var borderPath = svg.append("rect")
          .attr("x", 5)
          .attr("y", 5)
          .attr("height", h)
          .attr("width", w)
          .style("stroke", bordercolor)
          .style("fill", "none")
          .style("stroke-width", border);
    
        var textBox = svg.append("g")
          .attr("transform", "translate(5,385)");
    
        textBox.append("rect")
          .attr("id", "target")
          .attr("height", 150)
          .attr("width", 529)
          .style("stroke", bordercolor)
          .style("fill", "none")
          .style("stroke-width", border);
    
        circles.on("click", filter);
    
        filter(["Arsenal"]);
    
        function filter(d) {
          d3.select("body").selectAll(null);
    
          var filterss = teamData.filter(e =>e[0] === d[0])[0];
          var team = filterss.slice(0, 1);
          filterss = filterss.slice(1, filterss.length);
          team = team + ": "
          filterss = filterss.join(", ")
          console.log(team + filterss);
    
          new d3plus.TextBox()
            .select(textBox.node())
            .data([team + filterss])
            .text(function(d) {
              return d;
            })
            .width(textBox.select('rect').attr("width"))
            .fontSize(20)
            .render();
        }
      </script>
    </body>
    
    </html>