J'ai un petit problème avec mon graphique treemap D3. Lorsque je clique sur l'élément, mon graphique zoome sur cet élément mais le graphique est sorti de ma div. Je veux que le graphique reste dans mon bloc de navigation Voici mon code graphique :

function showtreemap(data, target) {


  //console.log(d3.schemeCategory20c)
  const tileWidth = 100
  const tileHeight = 100
  const tileScale = d3.scaleOrdinal().range(d3.schemeAccent)



  var tileXscale = d3.scaleLinear().domain([0, tileWidth]).range([0, tileWidth])
  var tileYscale = d3.scaleLinear().domain([0, tileHeight]).range([0, tileHeight])

  var div = d3.select(target)
  //var div = $(target);


  var treemap = d3.treemap()
    .size([tileWidth, tileHeight])

  var root = d3.hierarchy(data)
    // For equal representation
    .sum(function(d) {
      return d.value ? 1 : 0
    })



  // .sum((d) => d.value)
  var tree = treemap(root)

  var cells = div.selectAll(".node")
    .data(root.descendants())
    .enter()
    .append("div")
    .attr("class", function(d) {
      return "node level-" + d.depth
    })
    .attr("title", function(d) {
      return d.data.name
    })

  cells.style("left", function(d) {
      return tileXscale(d.x0) + "%"
    })
    .style("top", function(d) {
      return tileYscale(d.y0) + "%"
    })
    .style("width", function(d) {
      return tileXscale(d.x1) - tileXscale(d.x0) + "%"
    })
    .style("height", function(d) {
      return tileYscale(d.y1) - tileYscale(d.y0) + "%"
    })
    .style("background-color", function(d) {
      while (d.depth > 2) {
        d = d.parent
      }
      return tileScale(d.data.name)
    })
    .on("click", zoom)
    .append("p")
    .attr("class", "label")
    .text(function(d) {
      return d.data.name ? d.data.name : "---"
    })

  var parent = d3.select(".up")
    .datum(root)
    .on("click", zoom)

  // The zooming behavior was based off of here: https://codepen.io/znak/pen/qapRkQ?editors=0010
  function zoom(d) {
    var currentDepth = d.depth
    parent.datum(d.parent || root)
    tileXscale.domain([d.x0, d.x1])
    tileYscale.domain([d.y0, d.y1])

    var t = d3.transition()
      .duration(800)
      .ease(d3.easeCubicOut)

    cells.transition(t)
      .style("left", function(d) {
        return tileXscale(d.x0) + "%"
      })
      .style("top", function(d) {
        return tileYscale(d.y0) + "%"
      })
      .style("width", function(d) {
        return tileXscale(d.x1) - tileXscale(d.x0) + "%"
      })
      .style("height", function(d) {
        return tileYscale(d.y1) - tileYscale(d.y0) + "%"
      })

    // Hide this depth and above
    cells.filter(function(d) {
        return d.ancestors()
      })
      .classed("hide", function(d) {
        return d.children ? true : false
      })

    cells.filter(function(d) {
        return d.depth > currentDepth
      })
      .classed("hide", false)
  }
}

Et voici mon code de page :

{% extends 'layouts/base.html.twig' %} {% block title %}My IT Maps {% endblock %} {% block body %}
<!-- Begin Page Content -->
<div class="container-fluid body1">
  <!-- Page Heading -->
  <div class="d-sm-flex align-items-center justify-content-center mb-4">
    <h1 class="h3 mb-0 text-gray-800">Navigation</h1>
  </div>
  <div class="col-md-12 row">
    <div class="col-md-3">
      <!-- Default Card -->
      <div class="card mb-4">
        <div class="card-header"></div>
        <div class="card-body">
          <form action="" method="post">
            <label>
                            <input id="graph" name="graph" type="radio" value="treemap" checked>Treemap
                        </label>
            <label>
                            <input id="graph" name="graph" type="radio" value="donuts">Donuts
                        </label>
            <label>
                            <input id="graph" name="graph" type="radio" value="list">List
                        </label>
            <hr>
            <div class="form-group">
              <select id="inputState" class="form-control">
                <option selected>Fonctions métiers</option>
                <option>Sociétés</option>
                <option>Sites</option>
              </select>
            </div>
          </form>
        </div>
      </div>
      <!-- Default Card Example -->
      <div class="card mb-4">
        <div class="card-header">
          Sociétés
        </div>
        <div class="card-body tree">
          <div id="jstree1">
            <ul>
              <li>
                <i class="jstree-icon jstree-ocl"></i>
                <a href="#">
                  <i class="jstree-icon jstree-themeicon"></i>Root node 1</a>
                <ul>
                  <li>
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor  jstree-clicked" href="#">
                      <i class="jstree-icon jstree-themeicon"></i>
                      <em>initially</em>
                      <strong>selected</strong>
                    </a>
                  </li>
                  <li role="treeitem" data-jstree="{ &quot;icon&quot; : &quot;https://jstree.com/tree-icon.png&quot; }" id="j1_3" class="jstree-node  jstree-leaf" aria-selected="false">
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor" href="#">
                      <i class="jstree-icon jstree-themeicon jstree-themeicon-custom" style="background-image: url(https://jstree.com/tree-icon.png); background-size: auto; background-position: 50% 50%;"></i>custom icon URL</a>
                  </li>
                  <li role="treeitem" data-jstree="{ &quot;opened&quot; : true }" aria-expanded="true" id="j1_4" class="jstree-node  jstree-open" aria-selected="false">
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor" href="#">
                      <i class="jstree-icon jstree-themeicon"></i>initially open
                    </a>
                    <ul role="group" class="jstree-children">
                      <li role="treeitem" id="j1_5" class="jstree-node  jstree-leaf jstree-last">
                        <i class="jstree-icon jstree-ocl"></i>
                        <a class="jstree-anchor" href="#">
                          <i class="jstree-icon jstree-themeicon"></i>Another node
                        </a>
                      </li>
                    </ul>
                  </li>
                  <li role="treeitem" data-jstree="{ &quot;icon&quot; : &quot;glyphicon glyphicon-leaf&quot; }" id="j1_6" class="jstree-node  jstree-leaf jstree-last">
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor" href="#">
                      <i class="jstree-icon jstree-themeicon glyphicon glyphicon-leaf jstree-themeicon-custom"></i>Custom icon class (bootstrap)</a>
                  </li>
                </ul>
              </li>
              <li role="treeitem" id="j1_7" class="jstree-node  jstree-leaf jstree-last">
                <i class="jstree-icon jstree-ocl"></i>
                <a class="jstree-anchor" href="https://www.jstree.com">
                  <i class="jstree-icon jstree-themeicon"></i>Root node 2
                </a>
              </li>
            </ul>
          </div>
        </div>
      </div>
      <!-- Default Card Example -->
      <div class="card mb-4">
        <div class="card-header">
          Sites
        </div>
        <div class="card-body">
          <div id="jstree2">
            <ul>
              <li>
                <i class="jstree-icon jstree-ocl"></i>
                <a href="#">
                  <i class="jstree-icon jstree-themeicon"></i>Root node 1</a>
                <ul>
                  <li>
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor  jstree-clicked" href="#">
                      <i class="jstree-icon jstree-themeicon"></i>
                      <em>initially</em>
                      <strong>selected</strong>
                    </a>
                  </li>
                  <li role="treeitem" data-jstree="{ &quot;icon&quot; : &quot;https://jstree.com/tree-icon.png&quot; }" id="j1_3" class="jstree-node  jstree-leaf" aria-selected="false">
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor" href="#">
                      <i class="jstree-icon jstree-themeicon jstree-themeicon-custom" style="background-image: url(https://jstree.com/tree-icon.png); background-size: auto; background-position: 50% 50%;"></i>custom icon URL</a>
                  </li>
                  <li role="treeitem" data-jstree="{ &quot;opened&quot; : true }" aria-expanded="true" id="j1_4" class="jstree-node  jstree-open" aria-selected="false">
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor" href="#">
                      <i class="jstree-icon jstree-themeicon"></i>initially open
                    </a>
                    <ul role="group" class="jstree-children">
                      <li role="treeitem" id="j1_5" class="jstree-node  jstree-leaf jstree-last">
                        <i class="jstree-icon jstree-ocl"></i>
                        <a class="jstree-anchor" href="#">
                          <i class="jstree-icon jstree-themeicon"></i>Another node
                        </a>
                      </li>
                    </ul>
                  </li>
                  <li role="treeitem" data-jstree="{ &quot;icon&quot; : &quot;glyphicon glyphicon-leaf&quot; }" id="j1_6" class="jstree-node  jstree-leaf jstree-last">
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor" href="#">
                      <i class="jstree-icon jstree-themeicon glyphicon glyphicon-leaf jstree-themeicon-custom"></i>Custom icon class (bootstrap)</a>
                  </li>
                </ul>
              </li>
              <li role="treeitem" id="j1_7" class="jstree-node  jstree-leaf jstree-last">
                <i class="jstree-icon jstree-ocl"></i>
                <a class="jstree-anchor" href="https://www.jstree.com">
                  <i class="jstree-icon jstree-themeicon"></i>Root node 2
                </a>
              </li>
            </ul>
          </div>

        </div>
      </div>
      <!-- Default Card Example -->
      <div class="card mb-4">
        <div class="card-header">
          Fonctions métiers
        </div>
        <div class="card-body">
          <div id="jstree3">
            <ul>
              <li>
                <i class="jstree-icon jstree-ocl"></i>
                <a href="#">
                  <i class="jstree-icon jstree-themeicon"></i>Root node 1</a>
                <ul>
                  <li>
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor  jstree-clicked" href="#">
                      <i class="jstree-icon jstree-themeicon"></i>
                      <em>initially</em>
                      <strong>selected</strong>
                    </a>
                  </li>
                  <li role="treeitem" data-jstree="{ &quot;icon&quot; : &quot;https://jstree.com/tree-icon.png&quot; }" id="j1_3" class="jstree-node  jstree-leaf" aria-selected="false">
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor" href="#">
                      <i class="jstree-icon jstree-themeicon jstree-themeicon-custom" style="background-image: url(https://jstree.com/tree-icon.png); background-size: auto; background-position: 50% 50%;"></i>custom icon URL</a>
                  </li>
                  <li role="treeitem" data-jstree="{ &quot;opened&quot; : true }" aria-expanded="true" id="j1_4" class="jstree-node  jstree-open" aria-selected="false">
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor" href="#">
                      <i class="jstree-icon jstree-themeicon"></i>initially open
                    </a>
                    <ul role="group" class="jstree-children">
                      <li role="treeitem" id="j1_5" class="jstree-node  jstree-leaf jstree-last">
                        <i class="jstree-icon jstree-ocl"></i>
                        <a class="jstree-anchor" href="#">
                          <i class="jstree-icon jstree-themeicon"></i>Another node
                        </a>
                      </li>
                    </ul>
                  </li>
                  <li role="treeitem" data-jstree="{ &quot;icon&quot; : &quot;glyphicon glyphicon-leaf&quot; }" id="j1_6" class="jstree-node  jstree-leaf jstree-last">
                    <i class="jstree-icon jstree-ocl"></i>
                    <a class="jstree-anchor" href="#">
                      <i class="jstree-icon jstree-themeicon glyphicon glyphicon-leaf jstree-themeicon-custom"></i>Custom icon class (bootstrap)</a>
                  </li>
                </ul>
              </li>
              <li role="treeitem" id="j1_7" class="jstree-node  jstree-leaf jstree-last">
                <i class="jstree-icon jstree-ocl"></i>
                <a class="jstree-anchor" href="https://www.jstree.com">
                  <i class="jstree-icon jstree-themeicon"></i>Root node 2
                </a>
              </li>
            </ul>
          </div>

        </div>
      </div>
    </div>
    <div class="col-md-9">
      <!-- Default Card Example -->
      {% block cardnavigation %}
      <div class="card" id="card-graph-treemap">
        <div class="card-header">Treemap</div>
        <div class="card-body" id="treemap">
          <nav>
            <div class="up" id="graph-btn-previous">
              <input class="btn btn-secondary" type="button" value="Précédent">
            </div>
          </nav>
          <div id="treemap-body"></div>
        </div>
      </div>
      <div class="card" id="card-graph-donuts">
        <div class="card-header">Donuts</div>
        <div class="card-body">
          <div id="donuts-body"></div>
        </div>
      </div>
      <div class="card" id="card-graph-list">
        <div class="card-header">Liste</div>
        <div class="card-body">
          <div class="container">
            <div class="panel">
              <button id="loadData" class="btn btn-default">Load Data</button>

              <table id="dataTable" class="display" cellspacing="0" width="100%">
                <thead>
                  <tr>
                    <th>Name</th>
                    <th>Children</th>
                  </tr>
                </thead>
              </table>
            </div>
          </div>
        </div>
      </div>
      {% endblock %}
    </div>
  </div>
</div>
</div>
{% endblock %} {% block javascriptsp %}
<script src="{{asset('js/lib/jquery.easing.min.js')}}"></script>
<script src="{{ asset('js/lib/d3.v5.min.js') }}"></script>
<script src="{{ asset('js/lib/jstree.min.js') }}"></script>
<script src="{{ asset('js/jstree.js') }}"></script>
<script src="{{ asset('js/treemap.js') }}"></script>
<script src="{{ asset('js/donuts.js') }}"></script>
<script src="{{ asset('js/arbo.js')}}"></script>
<script src="{{ asset('js/datatables.min.js')}}"></script>


<script>
  function selectTreemap() {
    $('#treemap-body').empty();
    $('#card-graph-treemap').show();
    $('#card-graph-donuts').hide();
    $('#card-graph-list').hide();

    d3.json('/data/treemap').then(function(data) {
      console.log(data);
      showtreemap(data, "#treemap-body");
    });
  }

  function selectDonuts() {
    $('#donuts-body').empty();
    $('#card-graph-treemap').hide();
    $('#card-graph-donuts').show();
    $('#card-graph-list').hide();

    d3.json('/data/donuts').then(function(data) {
      console.log(data);
      donuts(data, '#donuts-body');
    });
  }

  function selectList() {
    $('#card-graph-donuts').hide();
    $('#card-graph-treemap').hide();
    $('#card-graph-list').show();

    $('#dataTable').DataTable({
      ajax: {
        url: '/data/list',
        dataSrc: 'data'
      },
      columns: [{
        data: 'name'
      }, {
        data: 'children'
      }]
    });
  }

  $("input[name='graph']").change(function() {
    var checkedValue = $("input[name='graph']:checked").val();
    switch (checkedValue) {
      case "treemap":
        selectTreemap();
        break;
      case "donuts":
        selectDonuts();
        break;
      case "list":
        selectList();
        break;
      default:
        console.error(`Unknown value for graph radio button {checkedValue}`);
    }
  });

  $(document).ready(function() {
    selectTreemap();
  });
</script>

{% endblock %}

Je cherche depuis longtemps la solution mais je ne trouve pas le bon problème. Merci de votre aide

0
Ewen 7 sept. 2020 à 10:18

1 réponse

Meilleure réponse

Puisque vous utilisez des éléments HTML normaux au lieu de SVG, vous pouvez simplement utiliser des propriétés CSS normales. Dans ce cas, l'ajout de overflow: hidden; au conteneur l'a résolu pour moi :

function showtreemap(data, target) {
  const tileWidth = 100
  const tileHeight = 100
  const tileScale = d3.scaleOrdinal().range(d3.schemeAccent)

  var tileXscale = d3.scaleLinear().domain([0, tileWidth]).range([0, tileWidth])
  var tileYscale = d3.scaleLinear().domain([0, tileHeight]).range([0, tileHeight])

  var div = d3.select(target)

  var treemap = d3.treemap()
    .size([tileWidth, tileHeight])

  var root = d3.hierarchy(data)
    // For equal representation
    .sum(function(d) {
      return d.value ? 1 : 0
    })

  var tree = treemap(root)

  var cells = div.selectAll(".node")
    .data(root.descendants())
    .enter()
    .append("div")
    .attr("class", function(d) {
      return "node level-" + d.depth
    })
    .attr("title", function(d) {
      return d.data.name
    })

  cells.style("left", function(d) {
      return tileXscale(d.x0) + "%"
    })
    .style("top", function(d) {
      return tileYscale(d.y0) + "%"
    })
    .style("width", function(d) {
      return tileXscale(d.x1) - tileXscale(d.x0) + "%"
    })
    .style("height", function(d) {
      return tileYscale(d.y1) - tileYscale(d.y0) + "%"
    })
    .style("background-color", function(d) {
      while (d.depth > 2) {
        d = d.parent
      }
      return tileScale(d.data.name)
    })
    .on("click", zoom)
    .append("p")
    .attr("class", "label")
    .text(function(d) {
      return d.data.name ? d.data.name : "---"
    })

  var parent = d3.select(".up")
    .datum(root)
    .on("click", zoom)

  // The zooming behavior was based off of here: https://codepen.io/znak/pen/qapRkQ?editors=0010
  function zoom(d) {
    var currentDepth = d.depth
    parent.datum(d.parent || root)
    tileXscale.domain([d.x0, d.x1])
    tileYscale.domain([d.y0, d.y1])

    var t = d3.transition()
      .duration(800)
      .ease(d3.easeCubicOut)

    cells.transition(t)
      .style("left", function(d) {
        return tileXscale(d.x0) + "%"
      })
      .style("top", function(d) {
        return tileYscale(d.y0) + "%"
      })
      .style("width", function(d) {
        return tileXscale(d.x1) - tileXscale(d.x0) + "%"
      })
      .style("height", function(d) {
        return tileYscale(d.y1) - tileYscale(d.y0) + "%"
      })

    // Hide this depth and above
    cells.filter(function(d) {
        return d.ancestors()
      })
      .classed("hide", function(d) {
        return d.children ? true : false
      })

    cells.filter(function(d) {
        return d.depth > currentDepth
      })
      .classed("hide", false)
  }
}

data = {
  "name": "Portfolio",
  "children": [{
      "name": "Identity",
      "children": [{
          "name": "Auto Lenart",
          "children": [{
              "name": "Photo 1",
              "value": "cgi-1.jpg"
            },
            {
              "name": "Photo 2",
              "value": "cgi-2.jpg"
            },
            {
              "name": "Photo 3",
              "value": "cgi-3.jpg"
            }
          ]
        },
        {
          "name": "PrintHouse",
          "children": [{
              "name": "Photo 1",
              "value": "photo-1.jpg"
            },
            {
              "name": "Photo 2",
              "value": "photo-2.jpg"
            },
            {
              "name": "Photo 3",
              "value": "photo-3.jpg"
            },
            {
              "name": "Photo 4",
              "value": "photo-4.jpg"
            },
            {
              "name": "Photo 5",
              "value": "photo-5.jpg"
            }
          ]
        },
        {
          "name": "Mertz",
          "children": [{
              "name": "Photo 1",
              "value": "epc-1.jpg"
            },
            {
              "name": "Photo 2",
              "value": "epc-2.jpg"
            },
            {
              "name": "Photo 3",
              "value": "epc-3.jpg"
            }
          ]
        },
        {
          "name": "Stanford",
          "children": [{
              "name": "Photo 1",
              "value": "floorplan-1.jpg"
            },
            {
              "name": "Photo 3",
              "value": "floorplan-2.jpg"
            }
          ]
        }
      ]
    },
    {
      "name": "Web",
      "children": [{
          "name": "AEG",
          "children": [{
              "name": "Photo 1",
              "value": "litho-1.jpg"
            },
            {
              "name": "Photo 2",
              "value": "litho-2.jpg"
            },
            {
              "name": "Photo 3",
              "value": "litho-3.jpg"
            },
            {
              "name": "Photo 4",
              "value": "litho-4.jpg"
            },
            {
              "name": "Photo 5",
              "value": "litho-5.jpg"
            },
            {
              "name": "Photo 6",
              "value": "litho-6.jpg"
            }
          ]
        },
        {
          "name": "Brent",
          "children": [{
              "name": "Photo 1",
              "value": "digital-1.jpg"
            },
            {
              "name": "Photo 2",
              "value": "digital-2.jpg"
            },
            {
              "name": "Photo 3",
              "value": "digital-3.jpg"
            },
            {
              "name": "Photo 4",
              "value": "digital-4.jpg"
            }
          ]
        }
      ]
    },
    {
      "name": "Print",
      "children": [{
          "name": "BvD",
          "children": [{
              "name": "Photo 1",
              "value": "folding-1.jpg"
            },
            {
              "name": "Photo 2",
              "value": "folding-2.jpg"
            },
            {
              "name": "Photo 3",
              "value": "folding-3.jpg"
            }
          ]
        },
        {
          "name": "Metalplast",
          "children": [{
              "name": "Photo 1",
              "value": "stitched-1.jpg"
            },
            {
              "name": "Photo 2",
              "value": "stitched-2.jpg"
            },
            {
              "name": "Photo 3",
              "value": "stitched-3.jpg"
            },
            {
              "name": "Photo 4",
              "value": "stitched-4.jpg"
            },
            {
              "name": "Photo 5",
              "value": "stitched-5.jpg"
            }
          ]
        },
        {
          "name": "Skylon",
          "children": [{
              "name": "Photo 1",
              "value": "sewn-1.jpg"
            },
            {
              "name": "Photo 2",
              "value": "sewn-2.jpg"
            },
            {
              "name": "Photo 3",
              "value": "sewn-3.jpg"
            }
          ]
        },
        {
          "name": "The O2",
          "children": [{
              "name": "Photo 1",
              "value": "softback-1.jpg"
            },
            {
              "name": "Photo 3",
              "value": "softback-2.jpg"
            }
          ]
        },
        {
          "name": "Trendy",
          "children": [{
              "name": "Photo 1",
              "value": "hardback-1.jpg"
            },
            {
              "name": "Photo 2",
              "value": "hardback-2.jpg"
            },
            {
              "name": "Photo 3",
              "value": "hardback-3.jpg"
            },
            {
              "name": "Photo 4",
              "value": "hardback-4.jpg"
            }
          ]
        }
      ]
    }
  ]
};

showtreemap(data, "div");
#mydiv {
  width: 500px;
  height: 300px;
  border: red 1px solid;
  position: relative;
  overflow: hidden;
}

p {
  margin: 0;
}

div.node {
  position: absolute;
  opacity: 0.4;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="mydiv"></div>
0
Ruben Helsloot 7 sept. 2020 à 08:39