Search code examples
javascriptd3.js3dbar-chart

D3.js bar chart into 3D conversion


I am new in d3.js and trying to create a 3d view bar chart using someone custom function to generate 3d bar . Bar is generation and display in svg but not touching to x axis, seems like already bar is there and 3d bar is on the top of same. I want only 3D bar with x and y scale in chart.

Thanks in advance.

<script src="https://d3js.org/d3.v7.min.js"></script>
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>D3.js 3D Bar Chart</title>
  <script src="https://d3js.org/d3.v7.min.js"></script>
</head>

<body>

  <div id="my_dataviz"></div>

  <script>
    const add3DBar = (parent, xPos, yPos, width, height, depth, duration) => {
      console.log("yes it calling", parent, xPos, yPos, width, height, depth, duration);
      const g = parent.append('g').attr('transform', `translate(${xPos}, ${yPos})`);

      g.append('path')
        .attr('d', `M 0,0 V ${0} H ${width} V 0 H 0 Z`)
        .style('fill', '#000081')
        .transition()
        .duration(duration)
        .attr('d', `M 0,0 V ${-height} H ${width} V 0 H 0 Z`);

      g.append('path')
        .attr('d', `M 0,${0} L ${depth},${-depth} H ${depth + width} L ${width},0 Z`)
        .style('fill', '#0000FF')
        .transition()
        .duration(duration)
        .attr('d', `M 0,${-height} L ${depth},${-height-depth} H ${depth + width} L ${width},${-height} Z`);

      g.append('path')
        .attr('d', `M ${width},0 L ${width + depth},${-depth}, V ${-depth} L ${width},0 Z`)
        .style('fill', '#0000C0')
        .transition()
        .duration(duration)
        .attr('d', `M ${width},0 L ${width + depth},${-depth}, V ${-height-depth} L ${width},${-height} Z`);
    }

    // set the dimensions and margins of the graph
    var margin = {
        top: 30,
        right: 30,
        bottom: 70,
        left: 60
      },
      width = 460 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;

    // append the svg object to the body of the page
    var svg = d3.select("#my_dataviz")
      .append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform",
        "translate(" + margin.left + "," + margin.top + ")");

    // X and Y scales
    var x = d3.scaleBand()
      .range([0, width])
      .padding(0.1);

    var y = d3.scaleLinear()
      .range([height, 0]);

    // Parse the Data
    d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/7_OneCatOneNum_header.csv")
      .then(function(data) {
        // Set domains for scales
        x.domain(data.map(function(d) {
          return d.Country;
        }));
        y.domain([0, d3.max(data, function(d) {
          return +d.Value;
        })]);

        // Call add3DBar for each data point
        data.forEach(function(d) {
          const xPos = x(d.Country) + x.bandwidth() / 2; // Adjust xPos to center bars
          const yPos = y(d.Value); // Set yPos using y scale
          const barHeight = height - y(d.Value); // Calculate bar height
          add3DBar(svg, xPos, yPos, x.bandwidth(), barHeight, 10, 1500);
        });

        // Draw X axis
        svg.append("g")
          .attr("transform", "translate(0," + height + ")")
          .call(d3.axisBottom(x))
          .selectAll("text")
          .attr("transform", "translate(-10,0)rotate(-45)")
          .style("text-anchor", "end");

        // Draw Y axis
        svg.append("g")
          .call(d3.axisLeft(y));

      })
      .catch(function(error) {
        console.log("Error loading the data:", error);
      });
  </script>

</body>

</html>


Solution

  • Your yPos is not needed. That argument into add3DBar represents the position of the base of the bar. It is the constant height.

    <script src="https://d3js.org/d3.v7.min.js"></script>
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>D3.js 3D Bar Chart</title>
      <script src="https://d3js.org/d3.v7.min.js"></script>
    </head>
    
    <body>
    
      <div id="my_dataviz"></div>
    
      <script>
        const add3DBar = (parent, xPos, yPos, width, height, depth, duration) => {
          const g = parent.append('g').attr('transform', `translate(${xPos}, ${yPos})`);
    
          g.append('path')
            .attr('d', `M 0,0 V ${0} H ${width} V 0 H 0 Z`)
            .style('fill', '#000081')
            .transition()
            .duration(duration)
            .attr('d', `M 0,0 V ${-height} H ${width} V 0 H 0 Z`);
    
          g.append('path')
            .attr('d', `M 0,${0} L ${depth},${-depth} H ${depth + width} L ${width},0 Z`)
            .style('fill', '#0000FF')
            .transition()
            .duration(duration)
            .attr('d', `M 0,${-height} L ${depth},${-height-depth} H ${depth + width} L ${width},${-height} Z`);
    
          g.append('path')
            .attr('d', `M ${width},0 L ${width + depth},${-depth}, V ${-depth} L ${width},0 Z`)
            .style('fill', '#0000C0')
            .transition()
            .duration(duration)
            .attr('d', `M ${width},0 L ${width + depth},${-depth}, V ${-height-depth} L ${width},${-height} Z`);
        }
    
        // set the dimensions and margins of the graph
        var margin = {
            top: 30,
            right: 30,
            bottom: 70,
            left: 60
          },
          width = 460 - margin.left - margin.right,
          height = 400 - margin.top - margin.bottom;
    
        // append the svg object to the body of the page
        var svg = d3.select("#my_dataviz")
          .append("svg")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom)
          .append("g")
          .attr("transform",
            "translate(" + margin.left + "," + margin.top + ")");
    
        // X and Y scales
        var x = d3.scaleBand()
          .range([0, width])
          .padding(0.1);
    
        var y = d3.scaleLinear()
          .range([height, 0]);
    
        // Parse the Data
        d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/7_OneCatOneNum_header.csv")
          .then(function(data) {
            // Set domains for scales
            x.domain(data.map(function(d) {
              return d.Country;
            }));
            y.domain([0, d3.max(data, function(d) {
              return +d.Value;
            })]);
    
            // Call add3DBar for each data point
            data.forEach(function(d) {
              const xPos = x(d.Country) + x.bandwidth() / 2; // Adjust xPos to center bars
              const barHeight = height - y(d.Value); // Calculate bar height
              add3DBar(svg, xPos, height, x.bandwidth(), barHeight, 10, 1500);
            });
    
            // Draw X axis
            svg.append("g")
              .attr("transform", "translate(0," + height + ")")
              .call(d3.axisBottom(x))
              .selectAll("text")
              .attr("transform", "translate(-10,0)rotate(-45)")
              .style("text-anchor", "end");
    
            // Draw Y axis
            svg.append("g")
              .call(d3.axisLeft(y));
    
          })
          .catch(function(error) {
            console.log("Error loading the data:", error);
          });
      </script>
    
    </body>
    
    </html>