折线图轴缩放

时间:2016-01-01 20:00:21

标签: javascript d3.js svg

我的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
...

1 个答案:

答案 0 :(得分:0)

您只需进行一些小修改即可解决您提到的问题。

  1. 问题1:x轴没有缩放以响应缩放。您遇到的问题来自于您更新x-和zoomed中的y轴。特别是,您当前的代码尝试从container

    中选择轴
    container.select(".x axis").call(xAxis);
    container.select(".y axis").call(yAxis); 
    

    但是,轴不是container的子项。此外,您更换了按类&#34;轴&#34;选择轴所需的.。有空间。如果您选择轴作为svg的子项并正确设置类选择器,那么您的缩放行为将起作用:

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

    此问题的解决方案是将所有依赖x轴的代码移动到d3.csv。这样,当您添加轴或甚至缩放时,x轴的刻度x的域已经正确设置。以下是为我工作的更新后的Javascript。

  3. //设置画布/图形的尺寸     var margin = {         前10名,         右:20,         底部:30,         左: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);
    
    // 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);
      }
    });