【问题标题】:Centering D3 chart + adding responsiveness居中 D3 图表 + 增加响应能力
【发布时间】:2016-02-20 18:53:43
【问题描述】:

一点背景知识,总的来说,我对 JS 和开发还很陌生,所以我可能会遗漏一些明显的东西。我使用 d3 使这张图表工作得很好,但无论我做什么,我都无法正确定位。我试过用 CSS 来操作它,但它似乎并没有以一种合乎逻辑的方式表现。我将显示设置为块,边距设置为自动,它根本不影响它。我可以更改定位的唯一方法是调整 d3 代码中的边距,但这对响应性没有太大作用。我也尝试过使用 text-align ,但也没有用。我想要做的是将它居中并随着屏幕尺寸的增加而扩大。这在理论上应该在 CSS 中很容易做到,但它似乎根本不起作用。感谢您的帮助。

这里是JS代码:

            // Set the dimensions of the canvas / graph
            var margin = {top: 20, right: 0, bottom: 70, left: 70},
                width = 300 - margin.left - margin.right,
                height = 300 - margin.top - margin.bottom;

            // Parse the date / time
            var parseDate = d3.time.format("%-m/%-d/%Y").parse;

            // Set the ranges
            var x = d3.time.scale().range([0, width]);
            var y = d3.scale.linear().range([height, 0]);

            // Define the axes
            var xAxis = d3.svg.axis().scale(x)
                .orient("bottom").ticks(10);

            var yAxis = d3.svg.axis().scale(y)
                .orient("left").ticks(5);

            // chart area fill

            var area = d3.svg.area()
                .x(function(d) { return x(d.Date); })
                .y0(height)
                .y1(function(d) { return y(d.Forecast); });

            // Define the line
            var valueline = d3.svg.line()
                .interpolate("cardinal")
                .x(function(d) { return x(d.Date); })
                .y(function(d) { return y(d.Orders); });

            var valueline2 = d3.svg.line()
                .interpolate("cardinal")
                .x(function(d) { return x(d.Date); })
                .y(function(d) { return y(d.Forecast); });

            // Adds the svg canvas
            var svg = d3.select("body")
                .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 + ")");


            // Get the data
            d3.csv("csv/Forecast.csv", function(error, data) {
                data.forEach(function(d) {
                    d.Date = parseDate(d.Date);
                    d.Orders = +d.Orders;
                });
             // Scale the range of the data
                x.domain(d3.extent(data, function(d) { return d.Date; }));
                y.domain([0, d3.max(data, function(d) { return d.Orders; })]);


                // Area

                svg.append("path")
                    .datum(data)
                    .attr("class", "area")
                    .attr("d", area);

                // Add the valueline path.

                svg.append("path")
                    .attr("class", "line")
                    .attr("d", valueline2(data))
                    .style("stroke", "#A7A9A6");

                svg.append("path")
                    .attr("class", "line")
                    .attr("d", valueline(data));

                // Add the X Axis
                svg.append("g")
                    .attr("class", "x axis")
                    .attr("transform", "translate(0," + height + ")")
                    .call(xAxis)
                    .selectAll("text")
                        .style("text-anchor", "end")
                        .attr("dx", "-.8em")
                        .attr("dy", ".15em")
                        .attr("transform", "rotate(-65)");

                // Add the Y Axis
                svg.append("g")
                    .attr("class", "y axis")
                    .call(yAxis);

            });

【问题讨论】:

    标签: javascript css d3.js


    【解决方案1】:

    JSFIDDLES

    响应式和居中: https://jsfiddle.net/sladav/6fyjhmne/3/

    没有回应: https://jsfiddle.net/sladav/7tp5vdkr/

    为了提高响应速度,请利用 SVG viewBox:

    一些链接:

    设置视图框:

    var margin = {top: 100, right: 150, bottom: 100, left: 150}
    
    var outerWidth  = 1600,
        outerHeight = 900;
    
    var width  = outerWidth - margin.right - margin.left,
        height = outerHeight - margin.top - margin.bottom;
    
    
    d3.select(".plot-div").append("svg")
        .attr("class", "plot-svg")
        .attr("width", "100%")
        .attr("viewBox", "0 0 " + outerWidth + " " + outerHeight)
        .append("g")
          .attr("class", "plot-space")
          .attr("transform", 
            "translate(" + margin.left + "," + margin.top + ")"
          );
    

    以上注意事项:

    1. SVG 被放在一个 div 中——我将调整 div 而不是 svg 的大小和位置
    2. SVG 宽度设置为父/div 的百分比,而不是绝对值。
    3. 您现在在 SVG 中绘制的所有内容都与 outerWidth x outerHeight 相关,并且无单位参数由 viewBox 重新缩放。

    看看我的 JSFIDDLE 示例中的 rect...

    d3.select(".plot-svg").append("rect")
        .attr("x", 0)
        .attr("y", 3*outerHeight/4)
        .attr("width", 800)
        .attr("height", outerHeight/4)
        .attr("fill", "grey")
    

    调整窗口大小,矩形将始终填充 svg 的 1/2,因为 800/1600(注意:1600 是外宽度)。

    用于调整位置/居中:

    操作包含您的 SVG/图表的 div 以将其定位到您想要的位置。在我的示例中,它占据了页面的 50%,并且由于 margin: auto 而居中。

    .plot-div{
      width: 50%;
      display: block;
      margin: auto;
     }
    

    无论您使用什么方法来缩放/定位您的 div,您的图表都应该效仿。

    【讨论】:

    • 现在完美运行;包括响应式缩放。我犯了一个菜鸟错误...我使用的是:var svg = d3.select(".plot-div") 而不是 var svg = d3.select("div.plot-div")。我没有意识到您必须专门调出 div 然后是类名,这解释了为什么我的 CSS 没有效果。谢谢!
    • @trevor_bye,很高兴它正在工作。没有看到你的代码很难说,但听起来你可能会得出一个关于必须先调用 div 的错误结论(这不是一般规则)。如果您的 css 看起来像: .plot-div{ } ,第一个仅限类的 d3 选择应该可以正常工作。如果您遇到问题,可能是由于您的 d3 选择和 css 选择器中的一些不协调,其中特异性有点偏离,并且您没有按照您的意图应用 css(有关特异性的更多信息,请参见此处:developer.mozilla.org/en-US/docs/Web/CSS/Specificity )。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    • 2013-09-28
    • 1970-01-01
    • 2016-09-02
    • 2013-07-11
    • 1970-01-01
    相关资源
    最近更新 更多