如何调整React组件中的d3元素

时间:2019-05-04 18:29:23

标签: reactjs d3.js dom

我在调整React中d3图表的大小时遇到​​问题。我可以让SVG本身更改大小,但是SVG内部的图表没有更改。我在这里浏览了所有类似的问题,但无法弄清楚。

我尝试了viewbox和perserveaspectratio方法,但它没有更改图表的元素。现在,我添加了CS来更改SVG大小。我认为我走在正确的道路上,但缺少一些地方。

此处提供了组件代码:

class Chart extends Component {

    componentDidMount() {
        this.createChart();
    }


    createChart() {
          var svg = d3.select("svg"),
        margin = {top: 20, right: 20, bottom: 30, left: 40},
        width = +svg.attr("width") - margin.left - margin.right,
        height = +svg.attr("height") - margin.top - margin.bottom,
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

    // The scale spacing the groups:
    var x0 = d3.scaleBand()
        .rangeRound([0, width])
        .paddingInner(0.1);

    // The scale for spacing each group's bar:
    var x1 = d3.scaleBand()
        .padding(0.05);

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

    var z = d3.scaleOrdinal()
        .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

    const teamRef = {
        "packers": packers,
        "bears": bears,
        "chargers": chargers
    }

    d3.csv(teamRef[this.props.team], function(d, i, columns) {
        for (var i = 1, n = columns.length; i < n; ++i) d[columns[i]] = +d[columns[i]];
        return d;
    }).then(function(data) {
        // console.log(data);


        var keys = data.columns.slice(1);

        // console.log('keys');
        // console.log(keys);
        x0.domain(data.map(function(d) { return d.Year; }));
        x1.domain(keys).rangeRound([0, x0.bandwidth()]);
        y.domain([0, d3.max(data, function(d) { return d3.max(keys, function(key) { return d[key]; }); })]).nice();

        g.append("g")
            .selectAll("g")
            .data(data)
            .enter().append("g")
            .attr("class","bar")
            .attr("transform", function(d) { return "translate(" + x0(d.Year) + ",0)"; })
            .selectAll("rect")
            .data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
            .enter().append("rect")
            .attr("x", function(d) { return x1(d.key); })
            .attr("y", function(d) { return y(d.value); })
            .attr("width", x1.bandwidth())
            .attr("height", function(d) { return height - y(d.value); })
            .attr("fill", function(d) { return z(d.key); });

        g.append("g")
            .attr("class", "axis")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(x0));

        g.append("g")
            .attr("class", "y axis")
            .call(d3.axisLeft(y).ticks(null, "s"))
            .append("text")
            .attr("x", 2)
            .attr("y", y(y.ticks().pop()) + 0.5)
            .attr("dy", "0.32em")
            .attr("fill", "#000")
            .attr("font-weight", "bold")
            .attr("text-anchor", "start")
            .text("Population");

        var legend = g.append("g")
            .attr("font-family", "sans-serif")
            .attr("font-size", 10)
            .attr("text-anchor", "end")
            .selectAll("g")
            .data(keys.slice().reverse())
            .enter().append("g")
            .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

        legend.append("rect")
            .attr("x", width - 17)
            .attr("width", 15)
            .attr("height", 15)
            .attr("fill", z)
            .attr("stroke", z)
            .attr("stroke-width",2)
            .on("click",function(d) { update(d) });

        legend.append("text")
            .attr("x", width - 24)
            .attr("y", 9.5)
            .attr("dy", "0.32em")
            .text(function(d) { return d; });

        var filtered = [];

        ////
        //// Update and transition on click:
        ////

        function update(d) {

            //
            // Update the array to filter the chart by:
            //

            // add the clicked key if not included:
            if (filtered.indexOf(d) === -1) {
                filtered.push(d);
                // if all bars are un-checked, reset:
                if(filtered.length === keys.length) filtered = [];
            }
            // otherwise remove it:
            else {
                filtered.splice(filtered.indexOf(d), 1);
            }

            //
            // Update the scales for each group(/states)'s items:
            //
            var newKeys = [];
            keys.forEach(function(d) {
                if (filtered.indexOf(d) === -1 ) {
                    newKeys.push(d);
                }
            })
            x1.domain(newKeys).rangeRound([0, x0.bandwidth()]);
            y.domain([0, d3.max(data, function(d) { return d3.max(keys, function(key) { if (filtered.indexOf(key) === -1) return d[key]; }); })]).nice();

            // update the y axis:
            svg.select(".y")
                .transition()
                .call(d3.axisLeft(y).ticks(null, "s"))
                .duration(500);


            //
            // Filter out the bands that need to be hidden:
            //
            var bars = svg.selectAll(".bar").selectAll("rect")
                .data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })

            bars.filter(function(d) {
                    return filtered.indexOf(d.key) > -1;
                })
                .transition()
                .attr("x", function(d) {
                    return (+d3.select(this).attr("x")) + (+d3.select(this).attr("width"))/2;
                })
                .attr("height",0)
                .attr("width",0)
                .attr("y", function(d) { return height; })
                .duration(500);

            //
            // Adjust the remaining bars:
            //
            bars.filter(function(d) {
                    return filtered.indexOf(d.key) === -1;
                })
                .transition()
                .attr("x", function(d) { return x1(d.key); })
                .attr("y", function(d) { return y(d.value); })
                .attr("height", function(d) { return height - y(d.value); })
                .attr("width", x1.bandwidth())
                .attr("fill", function(d) { return z(d.key); })
                .duration(500);


            // update legend:
            legend.selectAll("rect")
                .transition()
                .attr("fill",function(d) {
                    if (filtered.length) {
                        if (filtered.indexOf(d) === -1) {
                            return z(d);
                        }
                        else {
                            return "white";
                        }
                    }
                    else {
                        return z(d);
                    }
                })
                .duration(100);



        }

    });
    }

    render() {

        return (
            <div>
                <div id="container" className="svg-container">
                    <svg className="svg-content" width="900" height="500">
                    </svg>
                </div>
                <a onClick={this.props.onBack} className="col-xs-1 pt3 black b navbar-left">Back</a>
            </div>
        )
    }
}

export default Chart;

和CS:

.svg-container {
    display: inline-block;
    position: relative;
    width: 100%;
    padding-bottom: 100%;
    vertical-align: top;
    overflow: hidden;
}
.svg-content {
    display: inline-block;
    position: absolute;
    top: 0;
    left: 0;
}

当前结果显示在gh页上。 https://rksnyder7.github.io/SalaryCards/

请参阅左上方的图表,svg会发生变化,但条形不会发生变化。

感谢您的帮助!我已经坚持了很长时间。

0 个答案:

没有答案