1

I'm displaying the word cloud inside a div container. But as you can see the svg is not centered.

enter image description here

Does anyone know how to fix this issue?
Here is my code (based on Julien Renaux solution)

<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">

        <style>
            #wordcloud {width: 1000px; height: 600px; border: 1px solid red}
        </style>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

        <script type="text/javascript" src="bower_components/d3/d3.min.js"></script>
        <script type="text/javascript" src="bower_components/d3-cloud/d3.layout.cloud.js"></script>
        <script type="text/javascript" src="tags.js"></script>

    </head>

    <body>
        <div id="wordcloud">

        </div>

        <script>
var fill = d3.scale.category20b();

var w = $('#wordcloud').innerWidth(), h = $('#wordcloud').innerHeight();

var svg_location = "#wordcloud";

var fontSize;

var layout = d3.layout.cloud()
        .timeInterval(Infinity)
        .size([w, h])
        .fontSize(function(d) {
            return fontSize(+d.value);
        })
        .text(function(d) {
            return d.key;
        })
        .on("end", draw);

var svg = d3.select(svg_location).append("svg")
        .attr("width", w)
        .attr("height", h);

var vis = svg.append("g").attr("transform", "translate(" + [w >> 1, h >> 1] + ")");

update();

if(window.attachEvent) {
    window.attachEvent('onresize', update);
}
else if(window.addEventListener) {
    window.addEventListener('resize', update);
}

function draw(data, bounds) {
    var w = window.innerWidth,
        h = window.innerHeight;

//   ***          
        svg.remove();
        svg = d3.select(svg_location).append("svg")
                .attr("width", w)
                .attr("height", h);

        vis = svg.append("g").attr("transform", "translate(" + [w >> 1, h >> 1] + ")");
//   ***   

    svg.attr("width", w).attr("height", h);

    scale = bounds ? Math.min(
            w / Math.abs(bounds[1].x - w / 2),
            w / Math.abs(bounds[0].x - w / 2),
            h / Math.abs(bounds[1].y - h / 2),
            h / Math.abs(bounds[0].y - h / 2)) / 2 : 1;

    var text = vis.selectAll("text")
            .data(data, function(d) {
                return d.text.toLowerCase();
            });
    text.transition()
            .duration(1000)
            .attr("transform", function(d) {
                return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
            })
            .style("font-size", function(d) {
                return d.size + "px";
            });
    text.enter().append("text")
            .attr("text-anchor", "middle")
            .attr("transform", function(d) {
                return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
            })
            .style("font-size", function(d) {
                return d.size + "px";
            })
            .style("opacity", 1e-6)
            .transition()
            .duration(1000)
            .style("opacity", 1);
    text.style("font-family", function(d) {
        return d.font;
    })
            .style("fill", function(d) {
                return fill(d.text.toLowerCase());
            })
            .text(function(d) {
                return d.text;
            });

    vis.transition().attr("transform", "translate(" + [w >> 1, h >> 1] + ")scale(" + scale + ")");
}

function update() {
    layout.font('impact').spiral('archimedean');
    fontSize = d3.scale['sqrt']().range([10, 100]);
    if (tags.length){
        fontSize.domain([+tags[tags.length - 1].value || 1, +tags[0].value]);
    }
    layout.stop().words(tags).start();
}

function changeWords(newTags) {
    tags = newTags;
    update();
}

</script>

    </body>
</html>

Thanks for any help.

Xavier Guihot
  • 32,132
  • 15
  • 193
  • 118
codyLine
  • 407
  • 1
  • 7
  • 18

3 Answers3

0

The statements var w = window.innerWidth, h = window.innerHeight; in the draw method are resetting the w and h variables to the width and height of the entire window and not the width and height of the div wordcloud defined using the CSS #wordcloud {width: 1000px; height: 600px; border: 1px solid red}. That's why the word cloud is being drawn at the center of the screen and not the div.

If your objective is to have a responsive centered word cloud, you can ignore the div and the code snippet below should suffice. As you will resize the window you will see the word cloud resize and stay at the center of the window.

<!DOCTYPE html>
<html>
  <head>
    <title>TODO supply a title</title>
    <meta charset="UTF-8" />

    <style>
      #wordcloud {
        width: 1000px;
        height: 600px;
      }
    </style>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.js"></script>
    <script
      type="text/javascript"
      src="https://cdnjs.cloudflare.com/ajax/libs/d3-cloud/1.2.5/d3.layout.cloud.js"
    ></script>
  </head>

  <body>
    <div id="wordcloud"></div>

    <script>
      var fill = d3.scale.category20b();

      //   var w = $("#wordcloud").innerWidth(),
      //     h = $("#wordcloud").innerHeight();
      var w = window.innerWidth,
        h = window.innerHeight;

      var svg_location = "#wordcloud";

      var fontSize;

      var layout = d3.layout
        .cloud()
        .timeInterval(Infinity)
        .size([w, h])
        .fontSize(function(d) {
          return fontSize(+d.value);
        })
        .text(function(d) {
          return d.key;
        })
        .on("end", draw);

      var svg = d3
        .select(svg_location)
        .append("svg")
        .attr("width", w)
        .attr("height", h);

      var vis = svg
        .append("g")
        .attr("transform", "translate(" + [w >> 1, h >> 1] + ")");

      update();

      if (window.attachEvent) {
        window.attachEvent("onresize", update);
      } else if (window.addEventListener) {
        window.addEventListener("resize", update);
      }

      function draw(data, bounds) {
        var w = window.innerWidth,
          h = window.innerHeight;

        $("#wordcloud").innerWidth = w;
        $("#wordcloud").index = h;
        //   ***
        svg.remove();
        svg = d3
          .select(svg_location)
          .append("svg")
          .attr("width", w)
          .attr("height", h);

        vis = svg
          .append("g")
          .attr("transform", "translate(" + [w >> 1, h >> 1] + ")");
        //   ***

        svg.attr("width", w).attr("height", h);

        var scale = bounds
          ? Math.min(
              w / Math.abs(bounds[1].x - w / 2),
              w / Math.abs(bounds[0].x - w / 2),
              h / Math.abs(bounds[1].y - h / 2),
              h / Math.abs(bounds[0].y - h / 2)
            ) / 2
          : 1;

        var text = vis.selectAll("text").data(data, function(d) {
          return d.text.toLowerCase();
        });
        text
          .transition()
          .duration(1000)
          .attr("transform", function(d) {
            return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
          })
          .style("font-size", function(d) {
            return d.size + "px";
          });
        text
          .enter()
          .append("text")
          .attr("text-anchor", "middle")
          .attr("transform", function(d) {
            return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
          })
          .style("font-size", function(d) {
            return d.size + "px";
          })
          .style("opacity", 1e-6)
          .transition()
          .duration(1000)
          .style("opacity", 1);
        text
          .style("font-family", function(d) {
            return d.font;
          })
          .style("fill", function(d) {
            return fill(d.text.toLowerCase());
          })
          .text(function(d) {
            return d.text;
          });

        vis
          .transition()
          .attr(
            "transform",
            "translate(" + [w >> 1, h >> 1] + ")scale(" + scale + ")"
          );
      }

      function update() {
        layout.font("impact").spiral("archimedean");
        fontSize = d3.scale["sqrt"]().range([10, 100]);
        var tags = [
          { key: "Cat", value: 26 },
          { key: "fish", value: 19 },
          { key: "things", value: 18 },
          { key: "look", value: 16 },
          { key: "two", value: 15 },
          { key: "like", value: 14 },
          { key: "hat", value: 14 },
          { key: "Oh", value: 13 },
          { key: "mother", value: 12 },
          { key: "One", value: 12 },
          { key: "Now", value: 12 },
          { key: "Thing", value: 12 },
          { key: "house", value: 10 },
          { key: "fun", value: 9 },
          { key: "know", value: 9 },
          { key: "good", value: 9 },
          { key: "saw", value: 9 },
          { key: "bump", value: 8 },
          { key: "hold", value: 7 },
          { key: "fear", value: 6 },
          { key: "game", value: 6 },
          { key: "play", value: 6 },
          { key: "Sally", value: 6 },
          { key: "wet", value: 6 },
          { key: "little", value: 6 },
          { key: "box", value: 6 },
          { key: "came", value: 6 },
          { key: "away", value: 6 },
          { key: "sit", value: 5 },
          { key: "ran", value: 5 },
          { key: "big", value: 5 },
          { key: "something", value: 5 },
          { key: "put", value: 5 },
          { key: "fast", value: 5 },
          { key: "go", value: 5 },
          { key: "ball", value: 5 },
          { key: "pot", value: 5 },
          { key: "show", value: 4 },
          { key: "cup", value: 4 },
          { key: "get", value: 4 },
          { key: "cake", value: 4 },
          { key: "pick", value: 4 },
          { key: "went", value: 4 },
          { key: "toy", value: 4 },
          { key: "ship", value: 4 },
          { key: "net", value: 4 },
          { key: "tell", value: 4 },
          { key: "fan", value: 4 },
          { key: "wish", value: 4 },
          { key: "day", value: 4 },
          { key: "new", value: 4 },
          { key: "tricks", value: 4 },
          { key: "way", value: 4 },
          { key: "sat", value: 4 },
          { key: "books", value: 3 },
          { key: "hook", value: 3 },
          { key: "mess", value: 3 },
          { key: "kites", value: 3 },
          { key: "rake", value: 3 },
          { key: "red", value: 3 },
          { key: "shame", value: 3 },
          { key: "bit", value: 3 },
          { key: "hands", value: 3 },
          { key: "gown", value: 3 },
          { key: "call", value: 3 },
          { key: "cold", value: 3 },
          { key: "fall", value: 3 },
          { key: "milk", value: 3 },
          { key: "shook", value: 3 },
          { key: "tame", value: 2 },
          { key: "deep", value: 2 },
          { key: "Sank", value: 2 },
          { key: "head", value: 2 },
          { key: "back", value: 2 },
          { key: "fell", value: 2 },
          { key: "hop", value: 2 },
          { key: "shut", value: 2 },
          { key: "dish", value: 2 },
          { key: "trick", value: 2 },
          { key: "take", value: 2 },
          { key: "tip", value: 2 },
          { key: "top", value: 2 },
          { key: "see", value: 2 },
          { key: "let", value: 2 },
          { key: "shake", value: 2 },
          { key: "bad", value: 2 },
          { key: "another", value: 2 },
          { key: "come", value: 2 },
          { key: "fly", value: 2 },
          { key: "want", value: 2 },
          { key: "hall", value: 2 },
          { key: "wall", value: 2 },
          { key: "Thump", value: 2 },
          { key: "Make", value: 2 },
          { key: "lot", value: 2 },
          { key: "hear", value: 2 },
          { key: "find", value: 2 },
          { key: "lots", value: 2 },
          { key: "bet", value: 2 },
          { key: "dear", value: 2 },
          { key: "looked", value: 2 },
          { key: "gone", value: 2 },
          { key: "sun", value: 2 },
          { key: "asked", value: 1 },
          { key: "shine", value: 1 },
          { key: "mind", value: 1 },
          { key: "bite", value: 1 },
          { key: "step", value: 1 },
          { key: "mat", value: 1 },
          { key: "gave", value: 1 },
          { key: "pat", value: 1 },
          { key: "bent", value: 1 },
          { key: "funny", value: 1 },
          { key: "give", value: 1 },
          { key: "games", value: 1 },
          { key: "high", value: 1 },
          { key: "hit", value: 1 },
          { key: "run", value: 1 },
          { key: "stand", value: 1 },
          { key: "fox", value: 1 },
          { key: "man", value: 1 },
          { key: "string", value: 1 },
          { key: "kit", value: 1 },
          { key: "Mothers", value: 1 },
          { key: "tail", value: 1 },
          { key: "dots", value: 1 },
          { key: "pink", value: 1 },
          { key: "white", value: 1 },
          { key: "kite", value: 1 },
          { key: "bed", value: 1 },
          { key: "bumps", value: 1 },
          { key: "jumps", value: 1 },
          { key: "kicks", value: 1 },
          { key: "hops", value: 1 },
          { key: "thumps", value: 1 },
          { key: "kinds", value: 1 },
          { key: "book", value: 1 },
          { key: "home", value: 1 },
          { key: "wood", value: 1 },
          { key: "hand", value: 1 },
          { key: "near", value: 1 },
          { key: "Think", value: 1 },
          { key: "rid", value: 1 },
          { key: "made", value: 1 },
          { key: "jump", value: 1 },
          { key: "yet", value: 1 },
          { key: "PLOP", value: 1 },
          { key: "last", value: 1 },
          { key: "stop", value: 1 },
          { key: "pack", value: 1 },
          { key: "nothing", value: 1 },
          { key: "got", value: 1 },
          { key: "sad", value: 1 },
          { key: "kind", value: 1 },
          { key: "fishHe", value: 1 },
          { key: "sunny", value: 1 },
          { key: "Yes", value: 1 },
          { key: "bow", value: 1 },
          { key: "tall", value: 1 },
          { key: "always", value: 1 },
          { key: "playthings", value: 1 },
          { key: "picked", value: 1 },
          { key: "strings", value: 1 },
          { key: "Well", value: 1 },
          { key: "lit", value: 1 }
        ];
        if (tags.length) {
          fontSize.domain([+tags[tags.length - 1].value || 1, +tags[0].value]);
        }
        layout
          .stop()
          .words(tags)
          .start();
      }

      function changeWords(newTags) {
        tags = newTags;
        update();
      }
    </script>
  </body>
</html>
Surabhi
  • 1
  • 1
  • Thanks for replying Surabhi. But my objective is to get the cloud centered in a container of my choice not in the whole window. – codyLine Dec 17 '19 at 22:40
0

This jQuery solution posted here is solving my problem.

I just had to add this piece of code:

jQuery.fn.center = function(parent) {
    if (parent) {
        parent = this.parent();
    } else {
        parent = window;
    }
    this.css({
        "position": "absolute",
        "top": ((($(parent).height() - this.outerHeight()) / 2) + $(parent).scrollTop() + "px"),
        "left": ((($(parent).width() - this.outerWidth()) / 2) + $(parent).scrollLeft() + "px")
    });
return this;
}

And use it at the end of the draw function: $("svg").center(true);

codyLine
  • 407
  • 1
  • 7
  • 18
0

This worked for me:

          #wordcloud {
            width: 100%;
            height: 500px;
          }

with

            var w = window.innerWidth,
                h = window.innerHeight;
brianfit
  • 1,511
  • 1
  • 14
  • 31