javascript - how to render svg element of d3.js using react.js? - Stack Overflow

I'm trying to render graph using react.js. In which I'm trying to use simple ReactDOM.render(

I'm trying to render graph using react.js. In which I'm trying to use simple ReactDOM.render() method on html page. when I'm appending this graph content to the body it will work for me well but I want to render this using react.js.

program-code:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<!--react js url here -->
</head>
<body>
<script>
var csv_data = "date,bucket,count\n19:37:1 164,30000,12\n19:37:1 283,30000,8\n19:37:1 349,80000,2\n19:37:1 421,30000,16\n19:37:1 599,30000,2\n19:37:1 608,40000,4\n19:37:1 755,30000,4\n19:37:1 857,30000,2\n19:37:1 915,40000,6";
var margin = {
        top : 20,
        right : 90,
        bottom : 30,
        left : 50
    }, width = 960 - margin.left - margin.right, height = 500 - margin.top
            - margin.bottom;

var svg = d3.select("#svg").attr("width",
            width + margin.left + margin.right).attr("height",
            height + margin.top + margin.bottom).append("g").attr(
            "transform",
            "translate(" + margin.left + "," + margin.top + ")");
var buckets = d3.csv.parse(csv_data);

    buckets.forEach(function(d) {
        d.date = new Date(timeFormat.parse(d.date));
        d.bucket = +d.bucket;
        d.count = +d.count;
    });

    x.domain(d3.extent(buckets, function(d) {
        return d.date;
    }));

    y.domain(d3.extent(buckets, function(d) {
        return d.bucket;
    }));

    z.domain([ 0, d3.max(buckets, function(d) {
        return d.count;
    }) ]);
x.domain([ x.domain()[0], +x.domain()[1] + xStep ]);
    y.domain([ y.domain()[0], y.domain()[1] + yStep ]);

    // Display the tiles for each non-zero bucket.
    svg.selectAll(".tile").data(buckets).enter().append("rect").attr(
            "class", "tile").attr("x", function(d) {
        return x(d.date);
    }).attr("y", function(d) {
        return y(d.bucket + yStep);
    }).attr("width", x(xStep) - x(0)).attr("height", y(0) - y(yStep))
            .style("fill", function(d) {
                return z(d.count);
            });

    // Add a legend for the color values.
    var legend = svg.selectAll(".legend").data(
            z.ticks(6).slice(1).reverse()).enter().append("g").attr(
            "class", "legend").attr("transform", function(d, i) {
        return "translate(" + (width + 20) + "," + (20 + i * 20) + ")";
    });

    legend.append("rect").attr("width", 20).attr("height", 20).style(
            "fill", z);

    legend.append("text").attr("x", 26).attr("y", 10).attr("dy", ".35em")
            .text(String);

    svg.append("text").attr("class", "label").attr("x", width + 20).attr(
            "y", 10).attr("dy", ".35em").text("Count");

    // Add an x-axis with label.
    svg.append("g").attr("class", "x axis").attr("transform",
            "translate(0," + height + ")").call(xAxis).append("text").attr(
            "class", "label").attr("x", width).attr("y", -6).attr(
            "text-anchor", "end").text("Time");

    // Add a y-axis with label.
    svg.append("g").attr("class", "y axis").call(yAxis).append("text")
            .attr("class", "label").attr("y", 6).attr("dy", ".71em").attr(
                    "text-anchor", "end").attr("transform", "rotate(-90)")
            .text("Latency");
</script>
<div id="container"></div>
<script type="text/jsx">
    ReactDOM.render(<svg id="svg"></svg>,document.getElementById('container'));     
</script>
</body>
</html>

But graph is not visible in the browser when I'm requesting to this page. what is that I'm missing here?

I'm trying to render graph using react.js. In which I'm trying to use simple ReactDOM.render() method on html page. when I'm appending this graph content to the body it will work for me well but I want to render this using react.js.

program-code:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<!--react js url here -->
</head>
<body>
<script>
var csv_data = "date,bucket,count\n19:37:1 164,30000,12\n19:37:1 283,30000,8\n19:37:1 349,80000,2\n19:37:1 421,30000,16\n19:37:1 599,30000,2\n19:37:1 608,40000,4\n19:37:1 755,30000,4\n19:37:1 857,30000,2\n19:37:1 915,40000,6";
var margin = {
        top : 20,
        right : 90,
        bottom : 30,
        left : 50
    }, width = 960 - margin.left - margin.right, height = 500 - margin.top
            - margin.bottom;

var svg = d3.select("#svg").attr("width",
            width + margin.left + margin.right).attr("height",
            height + margin.top + margin.bottom).append("g").attr(
            "transform",
            "translate(" + margin.left + "," + margin.top + ")");
var buckets = d3.csv.parse(csv_data);

    buckets.forEach(function(d) {
        d.date = new Date(timeFormat.parse(d.date));
        d.bucket = +d.bucket;
        d.count = +d.count;
    });

    x.domain(d3.extent(buckets, function(d) {
        return d.date;
    }));

    y.domain(d3.extent(buckets, function(d) {
        return d.bucket;
    }));

    z.domain([ 0, d3.max(buckets, function(d) {
        return d.count;
    }) ]);
x.domain([ x.domain()[0], +x.domain()[1] + xStep ]);
    y.domain([ y.domain()[0], y.domain()[1] + yStep ]);

    // Display the tiles for each non-zero bucket.
    svg.selectAll(".tile").data(buckets).enter().append("rect").attr(
            "class", "tile").attr("x", function(d) {
        return x(d.date);
    }).attr("y", function(d) {
        return y(d.bucket + yStep);
    }).attr("width", x(xStep) - x(0)).attr("height", y(0) - y(yStep))
            .style("fill", function(d) {
                return z(d.count);
            });

    // Add a legend for the color values.
    var legend = svg.selectAll(".legend").data(
            z.ticks(6).slice(1).reverse()).enter().append("g").attr(
            "class", "legend").attr("transform", function(d, i) {
        return "translate(" + (width + 20) + "," + (20 + i * 20) + ")";
    });

    legend.append("rect").attr("width", 20).attr("height", 20).style(
            "fill", z);

    legend.append("text").attr("x", 26).attr("y", 10).attr("dy", ".35em")
            .text(String);

    svg.append("text").attr("class", "label").attr("x", width + 20).attr(
            "y", 10).attr("dy", ".35em").text("Count");

    // Add an x-axis with label.
    svg.append("g").attr("class", "x axis").attr("transform",
            "translate(0," + height + ")").call(xAxis).append("text").attr(
            "class", "label").attr("x", width).attr("y", -6).attr(
            "text-anchor", "end").text("Time");

    // Add a y-axis with label.
    svg.append("g").attr("class", "y axis").call(yAxis).append("text")
            .attr("class", "label").attr("y", 6).attr("dy", ".71em").attr(
                    "text-anchor", "end").attr("transform", "rotate(-90)")
            .text("Latency");
</script>
<div id="container"></div>
<script type="text/jsx">
    ReactDOM.render(<svg id="svg"></svg>,document.getElementById('container'));     
</script>
</body>
</html>

But graph is not visible in the browser when I'm requesting to this page. what is that I'm missing here?

Share Improve this question asked Aug 25, 2016 at 11:43 ketanketan 2,91411 gold badges41 silver badges84 bronze badges 6
  • Have a look at this – Igorsvee Commented Aug 25, 2016 at 11:45
  • @Gerardo Furtado- yeah right. corrected this mistake. In other way can I render this svg variable itself by selecting div or something like that? – ketan Commented Aug 25, 2016 at 11:53
  • I'm not sure if I understand your question... Do you mean if you can choose a div to render the SVG inside it? – Gerardo Furtado Commented Aug 25, 2016 at 11:56
  • @Gerardo Furtado- yeah like that. But I'm tried with that also but still not working for me. – ketan Commented Aug 25, 2016 at 11:58
  • Do you have anything in the page with an ID named "svg"? If not, just create a div with that ID, or simply select the "body". – Gerardo Furtado Commented Aug 25, 2016 at 11:59
 |  Show 1 more ment

3 Answers 3

Reset to default 4

Since the d3 code is executed before the React code, the svg element doesn't exist yet. You can create a react class which renders the svg element, and then place your d3 code ponentDidMount and/or ponentDidUpdate method. React renders everything in a shadow DOM before adding it to the actual DOM so you need to make sure the element is available before you can select it with d3 (or jQuery, etc.)

class MySVG extends React.Component {

  ponentDidMount() {
    var svg = d3.select('#my-svg');
    //Do svg stuff
  }

  render() {
    return (
      <svg id="my-svg"></svg>
    );
  }

}

export default MySVG;

and then render mySVG with ReactDOM.render()

I published a tiny npm package to resolve this. npm i hook-use-d3 and then use like so:

In sample below I added some d3 code to show you animated green dot, to make sure you will have visual to confirm it works. As an extra, it's also animated :)

import * as d3 from "d3";
import React from "react";
import useD3 from "hook-use-d3";

export default function SomeComponent() {
  const d3ref = useD3((svg) => {
    const circle = svg
      .append("circle")
      .attr("cx", 50)
      .attr("cy", 50)
      .attr("r", 1)
      .attr("fill", "#4CAF50");

    function animate() {
      let radius = 5;
      let distance = 35;
      circle
        .transition()
        .duration(2000)
        .attrTween("r", () => d3.interpolate(radius, radius + distance))
        .on("end", () => {
          radius = circle.attr("r");
          distance = 35;

          circle
            .transition()
            .duration(2000)
            .attrTween("r", () => d3.interpolate(radius, radius - distance))
            .on("end", animate);
        });
    }
    animate();
  }, []);

  return <svg ref={d3ref} style={{ height: 100, width: 100 }}></svg>;
}

If you want to see the code of the hook, posted it on github: https://github./liesislukas/hook-use-d3/tree/main

Unless "svg" is the ID of an existing svg in the page, it seems to me that you forgot to append the SVG in your variable svg:

var svg = d3.select("#svg")
    .append("svg")//this appends the SVG
    .attr("width", width + margin.left + margin.right)
    .attr("height",  height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744177705a4561833.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信