D3 Force Directed Graph: why don’t the flags appear?

In your code above you are attempting to parent an HTML img tag to an SVG parent. This will never work. In the question I linked to in the comments, that OP attempted to solve this problem by using the foreignObject tag (which then allows HTML content inside it). As you mentioned, this is evil and should be avoided. So, my solution in the linked question was to set up some svg patterns that allow you to take your single sprite image and transform it to the proper coordinates for each flag. Here is that approach with your code base…

Full code here (that stack snippet was too big so I had to remove some flags).

<html>

<head>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
  <link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
  <style>
    body {
      font-family: Lato;
      background-color: #F5F5F5;
    }
  </style>
</head>

<body>
  <div class="body">
    <div class="container-fluid">
      <h1 class="text-center title">Countries linked by Border</h1>
      <div class="text-center">
        <div id="results"></div>
      </div>
    </div>
  </div>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>

  <script type="text/javascript">
    d3.json("https://raw.githubusercontent.com/DealPete/forceDirected/master/countries.json", function(error, json) {

          if (error) {
            return console.warn(error);
          }

          const data = json;
          const nodes = data.nodes;
          const links = data.links;

          var imagePos = [{
              "c": "td",
              "x": -240,
              "y": -132
            }, {
              "c": "pw",
              "x": 0,
              "y": -121
            }, {
              "c": "fk",
              "x": -32,
              "y": -44
            }, {
              "c": "im",
              "x": -48,
              "y": -66
            }, {
              "c": "fr",
              "x": -80,
              "y": -44
            }, {
              "c": "sh",
              "x": -240,
              "y": -121
            }, {
              "c": "bg",
              "x": -64,
              "y": -11
            }, {
              "c": "ly",
              "x": -48,
              "y": -88
            }, {
              "c": "tk",
              "x": -64,
              "y": -143
            }, {
              "c": "re",
              "x": -48,
              "y": -121
            }, {
              "c": "nl",
              "x": -240,
              "y": -99
            }, {
              "c": "sv",
              "x": -160,
              "y": -132
            }, {
              "c": "sa",
              "x": -128,
              "y": -121
            }, {
              "c": "ck",
              "x": -128,
              "y": -22
            }, {
              "c": "tr",
              "x": -144,
              "y": -143
            }, {
              "c": "pr",
              "x": -224,
              "y": -110
            }, {
              "c": "tv",
              "x": -176,
              "y": -143
            }, {
              "c": "sd",
              "x": -192,
              "y": -121
            }, {
              "c": "uy",
              "x": -16,
              "y": -154
            }, {
              "c": "bb",
              "x": 0,
              "y": -11
            }, {
              "c": "za",
              "x": -256,
              "y": -154
            }, {
              "c": "vu",
              "x": -144,
              "y": -154
            }, {
              "c": "ba",
              "x": -256,
              "y": 0
            }, {
              "c": "kr",
              "x": -80,
              "y": -77
            }, {
              "c": "tf",
              "x": -256,
              "y": -132
            }, {
              "c": "cl",
              "x": -144,
              "y": -22
            }, {
              "c": "ki",
              "x": -16,
              "y": -77
            }, {
              "c": "lr",
              "x": -240,
              "y": -77
            }, {
              "c": "do",
              "x": -96,
              "y": -33
            }, {
              "c": "dz",
              "x": -112,
              "y": -33
            }, {
              "c": "cr",
              "x": -208,
              "y": -22
            }, {
              "c": "ar",
              "x": -144,
              "y": 0
            }, {
              "c": "sb",
              "x": -144,
              "y": -121
            }, {
              "c": "tj",
              "x": -48,
              "y": -143
            }, {
              "c": "cw",
              "x": -256,
              "y": -22
            }, {
              "c": "bv",
              "x": -224,
              "y": -11
            }, {
              "c": "pn",
              "x": -208,
              "y": -110
            }, {
              "c": "so",
              "x": -80,
              "y": -132
            }, {
              "c": "la",
              "x": -160,
              "y": -77
            }, {
              "c": "me",
              "x": -112,
              "y": -88
            }, {
              "c": "sx",
              "x": -176,
              "y": -132
            }, {
              "c": "sy",
              "x": -192,
              "y": -132
            }, {
              "c": "gq",
              "x": -32,
              "y": -55
            }, {
              "c": "ro",
              "x": -64,
              "y": -121
            }, {
              "c": "ku",
              "x": -96,
              "y": -77
            }, {
              "c": "si",
              "x": -256,
              "y": -121
            }, {
              "c": "mh",
              "x": -144,
              "y": -88
            }, {
              "c": "ky",
              "x": -128,
              "y": -77
            }, {
              "c": "eh",
              "x": -176,
              "y": -33
            }, {
              "c": "ru",
              "x": -96,
              "y": -121
            }, {
              "c": "tz",
              "x": -208,
              "y": -143
            }, {
              "c": "np",
              "x": 0,
              "y": -110
            }, {
              "c": "pg",
              "x": -128,
              "y": -110
            }, {
              "c": "lb",
              "x": -176,
              "y": -77
            }, {
              "c": "sn",
              "x": -64,
              "y": -132
            }, {
              "c": "gw",
              "x": -112,
              "y": -55
            }, {
              "c": "tt",
              "x": -160,
              "y": -143
            }, {
              "c": "eg",
              "x": -160,
              "y": -33
            }, {
              "c": "gn",
              "x": 0,
              "y": -55
            }, {
              "c": "al",
              "x": -80,
              "y": 0
            }, {
              "c": "jm",
              "x": -192,
              "y": -66
            }, {
              "c": "be",
              "x": -32,
              "y": -11
            }, {
              "c": "kn",
              "x": -48,
              "y": -77
            }, {
              "c": "mu",
              "x": -48,
              "y": -99
            }, {
              "c": "az",
              "x": -240,
              "y": 0
            }, {
              "c": "gh",
              "x": -208,
              "y": -44
            }, {
              "c": "vg",
              "x": -96,
              "y": -154
            }, {
              "c": "ug",
              "x": -240,
              "y": -143
            }, {
              "c": "rw",
              "x": -112,
              "y": -121
            }, {
              "c": "pl",
              "x": -176,
              "y": -110
            }, {
              "c": "at",
              "x": -176,
              "y": 0
            }, {
              "c": "bs",
              "x": -192,
              "y": -11
            }, {
              "c": "ee",
              "x": -144,
              "y": -33
            }, {
              "c": "no",
              "x": -256,
              "y": -99
            }, {
              "c": "ca",
              "x": -16,
              "y": -22
            }, {
              "c": "ml",
              "x": -176,
              "y": -88
            }, {
              "c": "vc",
              "x": -64,
              "y": -154
            }, {
              "c": "mc",
              "x": -80,
              "y": -88
            }, {
              "c": "vi",
              "x": -112,
              "y": -154
            }, {
              "c": "fj",
              "x": -16,
              "y": -44
            }, {
              "c": "sj",
              "x": 0,
              "y": -132
            }, {
              "c": "ic",
              "x": -240,
              "y": -55
            }, {
              "c": "fo",
              "x": -64,
              "y": -44
            }, {
              "c": "lu",
              "x": -16,
              "y": -88
            }, {
              "c": "nf",
              "x": -192,
              "y": -99
            }, {
              "c": "mm",
              "x": -192,
              "y": -88
            }, {
              "c": "er",
              "x": -208,
              "y": -33
            }, {
              "c": "so",
              "x": -96,
              "y": -132
            }, {
              "c": "lc",
              "x": -192,
              "y": -77
            }, {
              "c": "cd",
              "x": -48,
              "y": -22
            }, {
              "c": "ma",
              "x": -64,
              "y": -88
            }, {
              "c": "mp",
              "x": -240,
              "y": -88
            }, {
              "c": "mx",
              "x": -96,
              "y": -99
            }, {
              "c": "na",
              "x": -144,
              "y": -99
            }, {
              "c": "gs",
              "x": -64,
              "y": -55
            }, {
              "c": "tw",
              "x": -192,
              "y": -143
            }, {
              "c": "ae",
              "x": -16,
              "y": 0
            }, {
              "c": "cu",
              "x": -224,
              "y": -22
            }, {
              "c": "id",
              "x": -256,
              "y": -55
            }, {
              "c": "ht",
              "x": -208,
              "y": -55
            }, {
              "c": "kw",
              "x": -112,
              "y": -77
            }, {
              "c": "by",
              "x": -256,
              "y": -11
            }, {
              "c": "il",
              "x": -16,
              "y": -66
            }, {
              "c": "ps",
              "x": -240,
              "y": -110
            }, {
              "c": "tl",
              "x": -80,
              "y": -143
            }, {
              "c": "ai",
              "x": -64,
              "y": 0
            }, {
              "c": "gp",
              "x": -16,
              "y": -55
            }, {
              "c": "pt",
              "x": -256,
              "y": -110
            }, {
              "c": "gr",
              "x": -48,
              "y": -55
            }, {
              "c": "bw",
              "x": -240,
              "y": -11
            }, {
              "c": "kp",
              "x": -64,
              "y": -77
            }, {
              "c": "mq",
              "x": -256,
              "y": -88
            }, {
              "c": "ad",
              "x": 0,
              "y": 0
            }, {
              "c": "gu",
              "x": -96,
              "y": -55
            }, {
              "c": "cf",
              "x": -64,
              "y": -22
            }, {
              "c": "ni",
              "x": -224,
              "y": -99
            }, {
              "c": "ke",
              "x": -240,
              "y": -66
            }, {
              "c": "mz",
              "x": -128,
              "y": -99
            }, {
              "c": "kh",
              "x": 0,
              "y": -77
            }, {
              "c": "us",
              "x": 0,
              "y": -154
            }, {
              "c": "wf",
              "x": -176,
              "y": -154
            }, {
              "c": "hk",
              "x": -144,
              "y": -55
            }, {
              "c": "ph",
              "x": -144,
              "y": -110
            }, {
              "c": "de",
              "x": -32,
              "y": -33
            }, {
              "c": "sc",
              "x": -160,
              "y": -121
            }, {
              "c": "ti",
              "x": -32,
              "y": -143
            }, {
              "c": "cy",
              "x": 0,
              "y": -33
            }, {
              "c": "sc",
              "x": -176,
              "y": -121
            }, {
              "c": "ws",
              "x": -192,
              "y": -154
            }, {
              "c": "ci",
              "x": -112,
              "y": -22
            }, {
              "c": "bf",
              "x": -48,
              "y": -11
            }, {
              "c": "tn",
              "x": -112,
              "y": -143
            }, {
              "c": "my",
              "x": -112,
              "y": -99
            }, {
              "c": "mw",
              "x": -80,
              "y": -99
            }, {
              "c": "an",
              "x": -112,
              "y": 0
            }, {
              "c": "nr",
              "x": -16,
              "y": -110
            }, {
              "c": "pm",
              "x": -192,
              "y": -110
            }, {
              "c": "xk",
              "x": -208,
              "y": -154
            }, {
              "c": "es",
              "x": -224,
              "y": -33
            }, {
              "c": "pa",
              "x": -80,
              "y": -110
            }, {
              "c": "jp",
              "x": -224,
              "y": -66
            }, {
              "c": "mr",
              "x": 0,
              "y": -99
            }, {
              "c": "pf",
              "x": -112,
              "y": -110
            }, {
              "c": "cn",
              "x": -176,
              "y": -22
            }, {
              "c": "au",
              "x": -192,
              "y": 0
            }, {
              "c": "cv",
              "x": -240,
              "y": -22
            }, {
              "c": "ao",
              "x": -128,
              "y": 0
            }, {
              "c": "fi",
              "x": 0,
              "y": -44
            }, {
              "c": "nc",
              "x": -160,
              "y": -99
            }, {
              "c": "ag",
              "x": -48,
              "y": 0
            }, {
              "c": "gy",
              "x": -128,
              "y": -55
            }, {
              "c": "nu",
              "x": -32,
              "y": -110
            }, {
              "c": "to",
              "x": -128,
              "y": -143
            }, {
              "c": "qa",
              "x": -32,
              "y": -121
            }, {
              "c": "dm",
              "x": -80,
              "y": -33
            }, {
              "c": "aw",
              "x": -208,
              "y": 0
            }, {
              "c": "cz",
              "x": -16,
              "y": -33
            }, {
              "c": "mk",
              "x": -160,
              "y": -88
            }, {
              "c": "ax",
              "x": -224,
              "y": 0
            }, {
              "c": "pk",
              "x": -160,
              "y": -110
            }, {
              "c": "st",
              "x": -144,
              "y": -132
            }, {
              "c": "bz",
              "x": 0,
              "y": -22
            }, {
              "c": "br",
              "x": -176,
              "y": -11
            }, {
              "c": "am",
              "x": -96,
              "y": 0
            }, {
              "c": "bh",
              "x": -80,
              "y": -11
            }, {
              "c": "gg",
              "x": -192,
              "y": -44
            }, {
              "c": "um",
              "x": -256,
              "y": -143
            }, {
              "c": "ga",
              "x": -96,
              "y": -44
            }, {
              "c": "yt",
              "x": -240,
              "y": -154
            }, {
              "c": "gd",
              "x": -128,
              "y": -44
            }, {
              "c": "dj",
              "x": -48,
              "y": -33
            }, {
              "c": "ss",
              "x": -128,
              "y": -132
            }, {
              "c": "gt",
              "x": -80,
              "y": -55
            }, {
              "c": "sk",
              "x": -16,
              "y": -132
            }, {
              "c": "sm",
              "x": -48,
              "y": -132
            }, {
              "c": "bd",
              "x": -16,
              "y": -11
            }, {
              "c": "jo",
              "x": -208,
              "y": -66
            }, {
              "c": "iq",
              "x": -96,
              "y": -66
            }, {
              "c": "bt",
              "x": -208,
              "y": -11
            }, {
              "c": "it",
              "x": -144,
              "y": -66
            }, {
              "c": "mg",
              "x": -128,
              "y": -88
            }, {
              "c": "sr",
              "x": -112,
              "y": -132
            }, {
              "c": "sg",
              "x": -224,
              "y": -121
            }, {
              "c": "ec",
              "x": -128,
              "y": -33
            }, {
              "c": "ge",
              "x": -144,
              "y": -44
            }, {
              "c": "ie",
              "x": 0,
              "y": -66
            }, {
              "c": "kz",
              "x": -144,
              "y": -77
            }, {
              "c": "tc",
              "x": -224,
              "y": -132
            }, {
              "c": "tg",
              "x": 0,
              "y": -143
            }, {
              "c": "lv",
              "x": -32,
              "y": -88
            }, {
              "c": "mo",
              "x": -224,
              "y": -88
            }, {
              "c": "mv",
              "x": -64,
              "y": -99
            }, {
              "c": "sz",
              "x": -208,
              "y": -132
            }, {
              "c": "va",
              "x": -48,
              "y": -154
            }, {
              "c": "bn",
              "x": -144,
              "y": -11
            }, {
              "c": "bj",
              "x": -112,
              "y": -11
            }, {
              "c": "zm",
              "x": -16,
              "y": -165
            }, {
              "c": "co",
              "x": -192,
              "y": -22
            }];

            const margin = {
              top: 10,
              right: 85,
              bottom: 65,
              left: 70
            }

            const w = 1250 - margin.left - margin.right;
            const h = 500 - margin.top - margin.bottom;

            const svg = d3.select("#results")
              .append("svg")
              .attr("width", w + margin.left + margin.right)
              .attr("height", h + margin.top + margin.bottom);

            var defs = svg.append("defs")
              .selectAll("pattern")
              .data(imagePos)
              .enter()
              .append("pattern")
              .attr("width", 16)
              .attr("height", 11)
              .attr("id", function(d) {
                return "pattern_" + d.c;
              });

            defs.append("image")
            .attr("xlink:href", "https://image.ibb.co/gMUNBQ/flags.png")
            .attr("x", (d) => d.x)
            .attr("y", (d) => d.y)
            .attr("width", "272")
            .attr("height", "176");

            const simulation = d3.forceSimulation()
              .nodes(nodes);

            simulation
            .force("charge_force", d3.forceManyBody().strength(-3))
            .force("center_force", d3.forceCenter(w / 2, h / 2));

            const link = svg.append("g")
              .attr("class", "links")
              .selectAll("line")
              .data(links)
              .enter().append("line")
              .attr('stroke', 'black')
              .attr("stroke-width", 2);

            const node = svg.append("g")
              .attr("class", "nodes")
              .selectAll("g")
              .data(nodes)
              .enter()
              .append("g")

            node.append("rect")
            .attr("x", 0)
            .attr("Y", 0)
            .attr("width", 16)
            .attr("height", 11)
            .attr("fill", function(d) {
              return "url(#pattern_" + d.code + ")";
            });

            const link_force = d3.forceLink(links)

            simulation.force("links", link_force)

            simulation.on("tick", tickActions);

            function tickActions() {
              node
                .attr("transform", function(d) {
                  return "translate(" + d.x + "," + d.y + ")"
                });

              link
                .attr("x1", function(d) {
                  return d.source.x;
                })
                .attr("y1", function(d) {
                  return d.source.y;
                })
                .attr("x2", function(d) {
                  return d.target.x;
                })
                .attr("y2", function(d) {
                  return d.target.y;
                });
            }

          });
  </script>
</body>

</html>

Leave a Comment