【问题标题】:Line chart axis zoom折线图轴缩放
【发布时间】:2016-01-01 20:00:21
【问题描述】:

我的 d3 可视化存在一些问题。我正在尝试制作一个显示 15 年以上发展的折线图。

第一个问题是 x 轴不会根据缩放比例缩放。 我已经用它开始了: http://bl.ocks.org/mbostock/4dc8736fb1ce9799c6d6 但我不知道为什么我的轴不缩放。

二、轴标注错误,应该是星期和年份(例如01-2016)

最后一点:如果缺少一些数据,例如 2013 年的数据,我有什么机会?我可以在图表中休息一下,以便今年只有一个空白区域吗?

这里是 HTML

<!doctype html>
<html>
  <head>  
    <link rel="stylesheet" href="main.css">
    <script src="//d3js.org/d3.v3.min.js"></script>
    <title>Test Tool</title> 
  </head> 

  <body>  
    <!--MAIN-->
    <main>

    <!--LINE CHART -->
    <script>
    // Set the dimensions of the canvas / graph
    var margin = {top: 10, right: 20, bottom: 30, left: 50},
        width = 1000 - margin.left - margin.right,
        height = 570 - margin.top - margin.bottom;

    // Set the ranges
    var x = d3.time.scale().domain([-width / 2, width / 2])
        .range([0, width]);
    var y = d3.scale.linear().domain([-height / 2, height / 2])
        .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);

    var zoom = d3.behavior.zoom()
        .x(x)
        .y(y)
        .scaleExtent([1, 10])
        .on("zoom", zoomed);

    var drag = d3.behavior.drag()
        .origin(function(d) { return d; })
        .on("dragstart", dragstarted)
        .on("drag", dragged)
        .on("dragend", dragended);

    var area = d3.svg.area()
        .x(function(d) { return x(d.meldewoche); })
        .y0(height)
        .y1(function(d) { return y(d.faelle); })
        .interpolate("basis");

    var areaflip = d3.svg.area()
        .x(function(d) { return x(d.meldewoche); })
        .y0(height)
        .y1(function(d) { return y(-d.faelle); })
        .interpolate("basis");

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

    var valuelineflip = d3.svg.line()
        .x(function(d) { return x(d.meldewoche); })
        .y(function(d) { return y(-d.faelle); })
        .interpolate("basis");

    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 + ")")
            .call(zoom); 

    var container = svg.append("g");

    var rect = svg.append("rect")
        .attr("width", width)
        .attr("height", height)
        .style("fill", "none")
        .style("pointer-events", "all");

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

    // Get the data
    d3.csv("data-hanta-gesamt.csv", function(error, data) {
        data.forEach(function(d) {
            // Parse the date / time
            var parseDate = d3.time.format("%W-%Y").parse;
            d.meldewoche = parseDate(d.meldewoche);
            d.faelle = +d.faelle; 
        });

    // Scale the range of the data
    x.domain(d3.extent(data, function(d) { return d.meldewoche; }));
    y.domain([0, d3.max(data, function(d) { return d.faelle+550; })]);

    // Add the valueline path.
    container.append("path")
            .attr("class", "line")
            .attr("d", valueline(data))
            .attr("transform", "translate(0,-265)");
    container.append("path")
            .attr("class", "lineflip")
            .attr("d", valuelineflip(data))
            .attr("transform", "translate(0,-265)");

    container.append("path")
            .datum(data)
            .attr("class", "area")
            .attr("d", area)
            .attr("transform", "translate(0,-265)"); 
    container.append("path")
            .datum(data)
            .attr("class", "areaflip")
            .attr("d", areaflip)
            .attr("transform", "translate(0,-265)");

    });


    //ZOOM
    function zoomed() {
        container.select(".x axis").call(xAxis);
        container.select(".y axis").call(yAxis); 
        //svg.selectAll('.line').attr('d', line)  
      container.attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ",1)");

    }

    function dragstarted(d) {
      d3.event.sourceEvent.stopPropagation();
      d3.select(this).classed("dragging", true);
    }

    function dragged(d) {
      d3.select(this)
          .attr("cx", d.x = d3.event.x)
          .attr("cy", d.y = d3.event.y);
    }

    function dragended(d) {
      d3.select(this).classed("dragging", false);
    }


    </script>
    </main>     
  </body>
</html>

还有 CSS:

     body {
        background: #E1E2DD;
        color: #333;
        font: 1em/1em "Helvetica Neue";
      }

      #main {
        float: left;
        padding: 3em;
        width: 65%;
      }
      #footer {
        padding: 1em;
        text-align: right;
        width:65%; 
      }

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

.x.axis path {
    display: none;
}

.line {
        fill: none;
        stroke: steelblue;
        stroke-width: 1.5px;
      }

.lineflip {
        fill: none;
        stroke: steelblue;
        stroke-width: 1.5px;
}

.area {
    fill: lightsteelblue;
      stroke-width: 0;
      fill-opacity: .67;
}

.areaflip {
    fill: lightsteelblue;
      stroke-width: 0;
      fill-opacity: .67;
}

csv 看起来像这样:

meldewoche,faelle
01-2001,2
03-2001,1
04-2001,2
05-2001,2
07-2001,1
08-2001,6
09-2001,1
...

【问题讨论】:

    标签: javascript d3.js svg


    【解决方案1】:

    您只需要稍作改动即可解决您提到的问题。

    1. 问题 1:x 轴不会随着缩放而缩放。您遇到的问题来自您如何更新 zoomed 中的 x 轴和 y 轴.特别是,您当前的代码尝试从container 中选择轴:

      container.select(".x axis").call(xAxis);
      container.select(".y axis").call(yAxis); 
      

      但是,坐标区不是container 的子级。此外,您用空格替换了“轴”类选择轴所需的.。相反,如果您选择轴作为 svg 的子级并正确设置类选择器,那么您的缩放行为将起作用:

      svg.select(".x.axis").call(xAxis);
      svg.select(".y.axis").call(yAxis); 
      
    2. 问题 2:x 轴标记错误。此问题源于您在加载数据之前添加 x 轴。因此,尚未使用您的数据日期设置 x 轴的域。

      解决这个问题的方法是将所有依赖于 x 轴的代码移动到您的d3.csv 中。这样,当您添加轴甚至缩放时,x 轴的比例域x 已经正确设置。这是对我有用的更新后的 Javascript。

    // 设置画布/图形的尺寸 变量边距 = { 前10名, 对:20, 底部:30, 左:50 }, 宽度 = 1000 - margin.left - margin.right, height = 570 - margin.top - margin.bottom;

    // Set the ranges
    var x = d3.time.scale().domain([-width / 2, width / 2])
      .range([0, width]);
    var y = d3.scale.linear().domain([-height / 2, height / 2])
      .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);
    
    // Get the data
    d3.csv("data-hanta-gesamt.csv", function(error, data) {
      data.forEach(function(d) {
        // Parse the date / time
        var parseDate = d3.time.format("%W-%Y").parse;
        d.meldewoche = parseDate(d.meldewoche);
        d.faelle = +d.faelle;
      });
    
    
      var drag = d3.behavior.drag()
        .origin(function(d) {
          return d;
        })
        .on("dragstart", dragstarted)
        .on("drag", dragged)
        .on("dragend", dragended);
    
      var area = d3.svg.area()
        .x(function(d) {
          return x(d.meldewoche);
        })
        .y0(height)
        .y1(function(d) {
          return y(d.faelle);
        })
        .interpolate("basis");
    
      var areaflip = d3.svg.area()
        .x(function(d) {
          return x(d.meldewoche);
        })
        .y0(height)
        .y1(function(d) {
          return y(-d.faelle);
        })
        .interpolate("basis");
    
      // Define the line
      var valueline = d3.svg.line()
        .x(function(d) {
          return x(d.meldewoche);
        })
        .y(function(d) {
          return y(d.faelle);
        })
        .interpolate("basis");
    
      var valuelineflip = d3.svg.line()
        .x(function(d) {
          return x(d.meldewoche);
        })
        .y(function(d) {
          return y(-d.faelle);
        })
        .interpolate("basis");
    
      // Scale the range of the data
      x.domain(d3.extent(data, function(d) {
        return d.meldewoche;
      }));
      y.domain([0, d3.max(data, function(d) {
        return d.faelle + 550;
      })]);
    
      var zoom = d3.behavior.zoom()
        .x(x)
        .y(y)
        .scaleExtent([1, 10])
        .on("zoom", zoomed);
    
      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 + ")")
        .call(zoom);
    
      var container = svg.append("g");
    
      var rect = svg.append("rect")
        .attr("width", width)
        .attr("height", height)
        .style("fill", "none")
        .style("pointer-events", "all");
    
      // Add the Y Axis
      svg.append("g")
        .attr("class", "y axis")
        .call(yAxis);
    
      // Add the X Axis
      svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);
    
      // Add the valueline path.
      container.append("path")
        .attr("class", "line")
        .attr("d", valueline(data))
        .attr("transform", "translate(0,-265)");
      container.append("path")
        .attr("class", "lineflip")
        .attr("d", valuelineflip(data))
        .attr("transform", "translate(0,-265)");
    
      container.append("path")
        .datum(data)
        .attr("class", "area")
        .attr("d", area)
        .attr("transform", "translate(0,-265)");
      container.append("path")
        .datum(data)
        .attr("class", "areaflip")
        .attr("d", areaflip)
        .attr("transform", "translate(0,-265)");
    
    
      //ZOOM
      function zoomed() {
        svg.select(".x.axis").call(xAxis);
        svg.select(".y.axis").call(yAxis);
        //svg.selectAll('.line').attr('d', line)  
        container.attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ",1)");
    
      }
    
      function dragstarted(d) {
        d3.event.sourceEvent.stopPropagation();
        d3.select(this).classed("dragging", true);
      }
    
      function dragged(d) {
        d3.select(this)
          .attr("cx", d.x = d3.event.x)
          .attr("cy", d.y = d3.event.y);
      }
    
      function dragended(d) {
        d3.select(this).classed("dragging", false);
      }
    });
    

    【讨论】:

    • 非常感谢您的帮助。但我认为变焦还有另一个问题。它可以工作,但轴标签会变大(字体变大)。它不像示例中的轴标签更改那样工作。线本身也有同样的问题,笔画宽度变大,但我想要一个更详细的相同笔画的图表。希望能很好地解释问题。
    猜你喜欢
    • 2020-05-04
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    相关资源
    最近更新 更多