折线图轴缩放

Line chart axis zoom

本文关键字:缩放 折线图      更新时间:2023-09-26

我的d3可视化出现了一些问题。我正在尝试做一个折线图,显示15年来的发展。

第一个问题是x轴不能根据缩放进行缩放。我用这个开始:http://bl.ocks.org/mbostock/4dc8736fb1ce9799c6d6但我不知道为什么我的轴不缩放。

第二,轴标签错误,应该是星期和年份(例如2016年1月1日)

最后:如果缺少一些数据,比如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. 问题1:x轴不会根据缩放进行缩放您遇到的问题来自于如何更新zoomed中的x轴和y轴。特别是,您当前的代码试图从container:中选择轴

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

    但是,这些轴不是container的子轴。此外,您将选择轴所需的.替换为具有空格的类"axis"。如果您选择轴作为svg的子轴,并正确设置类选择器,则缩放行为将起作用:

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

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

//设置画布/图形的尺寸var裕度={顶部:10,右:20,底部:30,左:50},width=1000-margin.left-margin.right,高度=570-顶部边缘-底部边缘;

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