0

Trouble with laying two D3 treemaps on one page.

Hello, I am new to D3.js and SVG and I had trouble laying two SVG Treemaps on one page. I got a hint from this. text

What I want to do is lay two zoomable treemaps on one page. (The sample above is for one treemap.) I implemented the code myself, but not working properly.treemap appears on the leftside but not on right side. I guess it it due to using the same scaleX for both of treemaps but don't have enough knowledge about this.

Please help me if you are familiar with SVG and have experience with the zoomable D3 treemap.

I attached all my files.(js, html, json)

chart1.js



fetch('../data/chart1.json')
  .then((response) => response.json())
  .then((json) => {
    render(json, 'investicija');
    render(json, 'proizvod');
  })
  .catch((error) => console.error('Error fetching data:', error));

function render(treemapData, selector) {
  const renderData = treemapData[selector][0]; // Ensure this key exists in your JSON data

  (function () {
    const margin = { top: 20, right: 0, bottom: 0, left: 0 };
    const container = document.getElementById(selector);
    const width = container.clientWidth;
    const height = container.clientHeight;

    let svg, grandparent, scaleX, scaleY, treemap;

    function createSvg() {
      scaleX = d3.scale.linear()
        .domain([0, width])
        .range([0, width]);

      scaleY = d3.scale.linear()
        .domain([0, height])
        .range([0, height]);

      treemap = d3.layout.treemap()
        .children((d, depth) => depth ? null : d._children)
        .sort((a, b) => a.amount - b.amount)
        .ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
        .round(false)
        .value(d => d.value);

      svg = d3.select(`#${selector}`).append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.bottom + margin.top)
        .style("margin-left", -margin.left + "px")
        .style("margin-right", -margin.right + "px")
        .append("g")
        .attr("transform", `translate(${margin.left},${margin.top})`)
        .style("shape-rendering", "geometricPrecision");

      grandparent = svg.append("g")
        .attr("class", "grandparent");

      grandparent.append("rect")
        .attr("y", -margin.top)
        .attr("width", width)
        .attr("height", margin.top + 10);

      grandparent.append("text")
        .attr("x", 25)
        .attr("y", 6 - margin.top + 3)
        .attr("dy", ".75em");
    }

    function initialize(d) {
      d.x = d.y = 0;
      d.dx = width;
      d.dy = height;
      d.depth = 0;
    }

    function accumulate(d) {
      return (d._children = d.children) ? d.amount = d.children.reduce((p, v) => p + accumulate(v), 0) : d.amount;
    }

    function layout(d) {
      if (d._children) {
        treemap.nodes({ _children: d._children });

        d._children.forEach(c => {
          c.x = d.x + c.x * d.dx;
          c.y = d.y + c.y * d.dy;
          c.dx *= d.dx;
          c.dy *= d.dy;
          c.parent = d;
        });
      }
    }

    function display(d) {
      grandparent
        .datum(d.parent)
        .on("click", transition)
        .select("text")
        .text(selector);

      const g1 = svg.insert("g", ".grandparent")
        .datum(d)
        .attr("class", "depth");

      const g = g1.selectAll("g")
        .data(d._children)
        .enter().append("g");

      g.filter(d => d._children)
        .classed("children", true)
        .on("click", transition);

      g.append("rect")
        .attr("class", "parent")
        .call(rect)
        .style("fill", d => d.color)
        .append("title")
        .text(d => d.fullname);

      g.selectAll(".child")
        .data(d => {
          layout(d);
          return d._children || [d];
        })
        .enter().append("rect")
        .attr("class", "child")
        .call(rect);

      g.append("text")
        .classed("overlaidText1", true)
        .text(d => d.name)
        .call(middletext1);

      g.append("text")
        .classed("overlaidText", true)
        .text(d => d.text)
        .call(middletext);

      function transition(d) {
        if (!d || this.transitioning) return;
        this.transitioning = true;

        const g2 = display(d),
          t1 = g1.transition().duration(1000),
          t2 = g2.transition().duration(1000);

        scaleX.domain([d.x, d.x + d.dx]);
        scaleY.domain([d.y, d.y + d.dy]);

        svg.style("shape-rendering", null);

        svg.selectAll(".depth").sort((a, b) => a.depth - b.depth);

        g2.selectAll("text")
          .style("fill-opacity", 0);

        t1.selectAll("text:not(.overlaidText)").call(middletext1).style("fill-opacity", 0);
        t2.selectAll("text:not(.overlaidText)").call(middletext1).style("fill-opacity", 1);
        t1.selectAll(".overlaidText").call(middletext).style("fill-opacity", 0);
        t2.selectAll(".overlaidText").call(middletext).style("fill-opacity", 1);
        t1.selectAll("rect").call(rect);
        t2.selectAll("rect").call(rect);

        t1.remove().each("end", () => {
          svg.style("shape-rendering", "geometricPrecision");
          this.transitioning = false;
        });
      }

      return g;
    }

    function text(text) {
      text.attr("x", d => scaleX(d.x) + 6)
        .attr("y", d => scaleY(d.y) + 2);
    }

    function middletext(text) {
      text.attr("x", d => scaleX(d.x + d.dx / 2))
        .attr("y", d => scaleY(d.y + d.dy / 2) + 18);
    }

    function middletext1(text) {
      text.attr("x", d => scaleX(d.x + d.dx / 2))
        .attr("y", d => scaleY(d.y + d.dy / 2) - 3.5);
    }

    function rect(rect) {
      rect.attr("x", d => scaleX(d.x))
        .attr("y", d => scaleY(d.y) - 6)
        .attr("width", d => {
          const x0 = scaleX(d.x);
          const x1 = scaleX(d.x + d.dx);
          const w = x1 - x0;
          console.log(`Width for ${d.name} in ${selector}: x0=${x0}, x1=${x1}, width=${w}`);
          return w;
        })
        .attr("height", d => scaleY(d.y + d.dy) - scaleY(d.y))
        .attr("rx", "0px");
    }


    // Debug logs
    createSvg();
    initialize(renderData);
    accumulate(renderData);
    layout(renderData);
    display(renderData);
  })();
}


chart1.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>D3-Stacked-Bar-Chart (Percentage)</title>
    <link href="css/chart1.css" rel="stylesheet" type="text/css" />
</head>

<body>
    <div>
        <div id="investicija" style="display: inline-block; width: 500px; height: 300px;"  ></div>
        <div id="proizvod" style="display: inline-block; width: 500px; height: 300px;"></div>
    </div>
</body>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="script/chart1.js" charset="utf-8"></script>

</html>

chart1.json

{
    "investicija": [
        {
            "value": 3500000,
            "children": [
                {
                    "name": "PLAC",
                    "value": 1300000,
                    "color": "#6060e0"
                },
                {
                    "name": "SOFTCOST",
                    "value": 300000,
                    "color": "#ff8259",
                    "children": [
                        {
                            "name": "Nadzor",
                            "value": 100000
                        },
                        {
                            "name": "Dozvola",
                            "value": 100000
                        },
                        {
                            "name": "Direkcija",
                            "value": 100000
                        }
                    ]
                },
                {
                    "name": "HARDCOST",
                    "value": 1900000,
                    "color": "#fff214",
                    "children": [
                        {
                            "name": "Izvodjenje",
                            "value": 600000,
                            "children": [
                                {
                                    "name": "Obezbedjenje temeljne jame",
                                    "value": 200000
                                },
                                {
                                    "name": "Iskop",
                                    "value": 200000
                                },
                                {
                                    "name": "Temeljna ploca",
                                    "value": 200000
                                }
                            ]
                        },
                        {
                            "name": "Materijal",
                            "value": 1300000,
                            "children": [
                                {
                                    "name": "Armaturna mreza",
                                    "value": 300000
                                },
                                {
                                    "name": "Plocice",
                                    "value": 300000
                                },
                                {
                                    "name": "Lepak za fasadu",
                                    "value": 700000
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ],
    "proizvod": [
        {
            "value": 5100000,
            "children": [
                {
                    "name": "Stanovi",
                    "color": "#6060e0",
                    "children": [
                        {
                            "name": "Stan 1",
                            "value": 1200000
                        },
                        {
                            "name": "Stan 2",
                            "value": 2300000
                        },
                        {
                            "name": "Stan 3",
                            "value": 3300000
                        }
                    ]
                },
                {
                    "name": "Lokali",
                    "kvadrata": 480,
                    "color": "#ff8259",
                    "children": [
                        {
                            "name": "Lokal 1",
                            "value": 4300000
                        },
                        {
                            "name": "Lokal 2",
                            "value": 1300000
                        },
                        {
                            "name": "Lokal 3",
                            "value": 1300000
                        }
                    ]
                },
                {
                    "name": "Garažna mesta",
                    "color": "#fff214",
                    "children": [
                        {
                            "name": "Garažno mesto 1",
                            "value": 20000
                        },
                        {
                            "name": "Garažno mesto 2",
                            "value": 20000
                        },
                        {
                            "name": "Garažno mesto 3",
                            "value": 20000
                        },
                        {
                            "name": "Garažno mesto 4",
                            "value": 20000
                        }
                    ]
                }
            ]
        }
    ]
}

0

Browse other questions tagged or ask your own question.