javascript - 根据窗口大小调整 D3 中的线图大小

标签 javascript d3.js svg

我很难根据窗口大小调整折线图的大小。在这里查看我的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        svg {
            font: 10px "Times New Roman";
        }

        path {
            stroke-width: 2;
            fill: none;
        }

        .axis path, .axis line {
            fill: none;
            stroke: grey;
            stroke-width: 1;
            shape-rendering: crispEdges;
        }

        .overlay {
            fill: none;
            pointer-events: all;
        }

    </style>

</head>

<div class="chart-container"></div>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>

<body>
    <script>
        // Set the dimensions of the canvas / graph
        var margin = {top: 30, right: 20, bottom: 30, left: 50},
            width = 600 - margin.left - margin.right,
            height = 270 - margin.top - margin.bottom;

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

        // Parse the time for the Day
        var parseMinute = d3.time.format("%H:%M").parse,
            bisectDate = d3.bisector(function(d) { return d.date; }).left,
            formatValue = d3.format(",.2f"),
            formatCurrency = function(d) { return "$" + formatValue(d);};

        // 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(5);

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

        // Define the line
        var valueline = d3.svg.line()
        //.interpolate("basis")
            .x(function(d) { return x(d.date); })
            .y(function(d) { return y(d.close); });

        // 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 minumum Value from the array to add space at the bottom of the graph
        Array.min = function (array) {
            return Math.min.apply(Math, array);
        };

        var url = "https://api.iextrading.com/1.0/stock/aapl/chart/5y";

        // Get the data
        $.ajax({
            url: url,
            success: function(data) {

                // Setting global variable
                var arrayClose = [];
                var firstPrice = null;
                var lastPrice = null;
                var minimum = null;
                var result = null;
                var lineColor = null;

                // Get the data
                d3.json(url, function (error, data) {
                    data.forEach(function (d) {
                        d.date = parseDate(d.date);
                        d.close = +d.close;

                        // Adding each result to the end of the array
                        arrayClose.push(d.close);

                        // Finding the minimum value in the close price in the JSON File
                        minimum = Array.min(arrayClose);

                        // Taking .05% off of graph to dynamically show white space at the bottom of the minimum value
                        result = (10 / 100) * minimum;
                        result = minimum - result;

                        // Finding first elm in array
                        firstPrice = arrayClose[0];

                        // Finding last elm in array
                        lastPrice = arrayClose[arrayClose.length - 1];
                    });

                    if (firstPrice > lastPrice){
                        lineColor = "red";
                    } else {
                        lineColor = "green";
                    }

                    // Scale the range of the data
                    x.domain(d3.extent(data, function (d) {
                        return d.date;
                    }));
                    y.domain([result, d3.max(data, function (d) {
                        return d.close;
                    })]);

                    // Add the valueline path.
                    svg.append("path")
                        .transition()
                        .attr("class", "line")
                        .attr("stroke", lineColor)
                        .attr("d", valueline(data))
                    ;

                    // Add the X Axis
                    svg.append("g")
                        .attr("class", "x axis")
                        .attr("transform", "translate(0," + height + ")")
                        .call(xAxis);

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

                    // Add the text label for the X axis
                    svg.append("text")
                        .attr("x", width / 2)               //Dynamically moves with the graph
                        .attr("y", height + margin.bottom)
                        .style("text-anchor", "middle")
                        .text("Date");

                    // Add the text label for the Y axis
                    svg.append("text")
                        .attr("transform", "rotate(-90)")
                        .attr("x", 0 - (height / 2))
                        .attr("y", 0 - margin.left)
                        .attr("dy", "1em")
                        .style("text-anchor", "middle")
                        .text("Price");

                    // Adding the Title
                    svg.append("text")
                        .attr("x", (width / 2))
                        .attr("y", 0 - (margin.top / 2))
                        .attr("text-anchor", "middle")
                        .style("font-size", "16px")
                        .style("text-decoration", "underline")
                        .text("Price to Date");

                    //Mouseover
                    var focus = svg.append("g")
                        .attr("class", "focus")
                        .style("display", "none");

                    focus.append("line")
                        .attr("class", "x-hover-line hover-line")
                        .attr("y1", 0)
                        .attr("y2", height);

                    focus.append("line")
                        .attr("class", "y-hover-line hover-line")
                        .attr("x1", width)
                        .attr("x2", width);

                    focus.append("circle")
                        .attr("r", 4.5);

                    focus.append("text")
                        .attr("x", 9)
                        .attr("dy", ".35em");

                    svg.append("rect")
                        .attr("class", "overlay")
                        .attr("width", width)
                        .attr("height", height)
                        .on("mouseover", function() { focus.style("display", null); })
                        .on("mouseout", function() { focus.style("display", "none"); })
                        .on("mousemove", mousemove);

                    function mousemove() {
                        var x0 = x.invert(d3.mouse(this)[0]),
                            i = bisectDate(data, x0, 1),
                            d0 = data[i - 1],
                            d1 = data[i],
                            d = x0 - d0.date > d1.date - x0 ? d1 : d0;
                        focus.attr("transform", "translate(" + x(d.date) + "," + y(d.close) + ")");
                        focus.select(".x-hover-line").attr("y2", height - y(d.close));
                        focus.select(".y-hover-line").attr("x2", width + width);


                    }
                });
            }
        });
    </script>

</body>
</html>

当我更改添加一个viewbox 时,svg 完全消失了。我尝试围绕 svg 创建一个 class 但由于某种原因它无法识别它。我对此的灵感来自 Stack Example

最佳答案

删除 widthheight 属性,设置 viewBox:

.attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " 
    + (height + margin.top + margin.bottom))

下面是修改后的代码:

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

  <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
      svg {
        font: 10px "Times New Roman";
      }
      
      path {
        stroke-width: 2;
        fill: none;
      }
      
      .axis path,
      .axis line {
        fill: none;
        stroke: grey;
        stroke-width: 1;
        shape-rendering: crispEdges;
      }
      
      .overlay {
        fill: none;
        pointer-events: all;
      }

    </style>

  </head>

  <div class="chart-container"></div>
  <script src="https://d3js.org/d3.v3.min.js"></script>
  <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>

  <body>
    <script>
      // Set the dimensions of the canvas / graph
      var margin = {
          top: 30,
          right: 20,
          bottom: 30,
          left: 50
        },
        width = 600 - margin.left - margin.right,
        height = 270 - margin.top - margin.bottom;

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

      // Parse the time for the Day
      var parseMinute = d3.time.format("%H:%M").parse,
        bisectDate = d3.bisector(function(d) {
          return d.date;
        }).left,
        formatValue = d3.format(",.2f"),
        formatCurrency = function(d) {
          return "$" + formatValue(d);
        };

      // 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(5);

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

      // Define the line
      var valueline = d3.svg.line()
        //.interpolate("basis")
        .x(function(d) {
          return x(d.date);
        })
        .y(function(d) {
          return y(d.close);
        });

      // Adds the svg canvas
      var svg = d3.select("body")
        .append("svg")
        .attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom))
        .append("g")
        .attr("transform",
          "translate(" + margin.left + "," + margin.top + ")");


      // Get the minumum Value from the array to add space at the bottom of the graph
      Array.min = function(array) {
        return Math.min.apply(Math, array);
      };

      var url = "https://api.iextrading.com/1.0/stock/aapl/chart/5y";

      // Get the data
      $.ajax({
        url: url,
        success: function(data) {

          // Setting global variable
          var arrayClose = [];
          var firstPrice = null;
          var lastPrice = null;
          var minimum = null;
          var result = null;
          var lineColor = null;

          // Get the data
          d3.json(url, function(error, data) {
            data.forEach(function(d) {
              d.date = parseDate(d.date);
              d.close = +d.close;

              // Adding each result to the end of the array
              arrayClose.push(d.close);

              // Finding the minimum value in the close price in the JSON File
              minimum = Array.min(arrayClose);

              // Taking .05% off of graph to dynamically show white space at the bottom of the minimum value
              result = (10 / 100) * minimum;
              result = minimum - result;

              // Finding first elm in array
              firstPrice = arrayClose[0];

              // Finding last elm in array
              lastPrice = arrayClose[arrayClose.length - 1];
            });

            if (firstPrice > lastPrice) {
              lineColor = "red";
            } else {
              lineColor = "green";
            }

            // Scale the range of the data
            x.domain(d3.extent(data, function(d) {
              return d.date;
            }));
            y.domain([result, d3.max(data, function(d) {
              return d.close;
            })]);

            // Add the valueline path.
            svg.append("path")
              .transition()
              .attr("class", "line")
              .attr("stroke", lineColor)
              .attr("d", valueline(data));

            // Add the X Axis
            svg.append("g")
              .attr("class", "x axis")
              .attr("transform", "translate(0," + height + ")")
              .call(xAxis);

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

            // Add the text label for the X axis
            svg.append("text")
              .attr("x", width / 2) //Dynamically moves with the graph
              .attr("y", height + margin.bottom)
              .style("text-anchor", "middle")
              .text("Date");

            // Add the text label for the Y axis
            svg.append("text")
              .attr("transform", "rotate(-90)")
              .attr("x", 0 - (height / 2))
              .attr("y", 0 - margin.left)
              .attr("dy", "1em")
              .style("text-anchor", "middle")
              .text("Price");

            // Adding the Title
            svg.append("text")
              .attr("x", (width / 2))
              .attr("y", 0 - (margin.top / 2))
              .attr("text-anchor", "middle")
              .style("font-size", "16px")
              .style("text-decoration", "underline")
              .text("Price to Date");

            //Mouseover
            var focus = svg.append("g")
              .attr("class", "focus")
              .style("display", "none");

            focus.append("line")
              .attr("class", "x-hover-line hover-line")
              .attr("y1", 0)
              .attr("y2", height);

            focus.append("line")
              .attr("class", "y-hover-line hover-line")
              .attr("x1", width)
              .attr("x2", width);

            focus.append("circle")
              .attr("r", 4.5);

            focus.append("text")
              .attr("x", 9)
              .attr("dy", ".35em");

            svg.append("rect")
              .attr("class", "overlay")
              .attr("width", width)
              .attr("height", height)
              .on("mouseover", function() {
                focus.style("display", null);
              })
              .on("mouseout", function() {
                focus.style("display", "none");
              })
              .on("mousemove", mousemove);

            function mousemove() {
              var x0 = x.invert(d3.mouse(this)[0]),
                i = bisectDate(data, x0, 1),
                d0 = data[i - 1],
                d1 = data[i],
                d = x0 - d0.date > d1.date - x0 ? d1 : d0;
              focus.attr("transform", "translate(" + x(d.date) + "," + y(d.close) + ")");
              focus.select(".x-hover-line").attr("y2", height - y(d.close));
              focus.select(".y-hover-line").attr("x2", width + width);


            }
          });
        }
      });

    </script>

  </body>

</html>

PS:您的代码中还有其他问题。

关于javascript - 根据窗口大小调整 D3 中的线图大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48816851/

相关文章:

javascript - 轴按比例正确显示,但图表条未正确绘制

css - 如何制作带边框的梯形

svg - 使用SVG对带有可选文本的图像进行 mask -可以吗?

javascript - 触发 Google Places 自动完成

javascript - D3.js 无法读取未定义的属性 'length'

javascript - 异步等待回调行为

javascript - 在甘特图 d3.js 顶部绘制多条线

css - 可以使用 CSS 动画同时为 SVG 的两个属性设置动画吗?

javascript - jQuery 鼠标悬停问题

javascript - Javascript 中的 strptime