d3 v4如何限制x缩放线图上的左/右平移

时间:2017-05-22 19:05:53

标签: d3.js

我试图在24小时内在折线图中显示数据。

我创建了一个d3 v4折线图,并且已成功:

  • 应用x轴仅缩放,并重绘所有元素
  • 使用clippath来保持我的数据不显示在我的轴线的左下方

我的问题是现在尝试将translateExtent应用到我的d3.zoom。它似乎让我无法在缩放前左/右平移,但是当我缩放时,它似乎会在我的数据集的结尾和开始半小时左右切断或添加。

我认为我需要做的就是在我的d3.zoom声明中添加一些代码,也可以在缩放功能中添加一些代码。

我尝试将.translateExtent([[0,0],[w,h]])添加到我的d3.zoom代码和许多其他变体中,包括减去/添加我的边距等。

看起来像添加如下所示的w" 2 *边距会消除初始点击时的跳跃。 (这让我感到困惑,因为我认为第一个坐标组应该会影响我的图形的左平移)但是一旦我放大,它就会让我不能在一天开始之前平移(yay)但是让我有点过去一天结束(嘘)。

 var zoomCall = d3.zoom()
      .scaleExtent([1, 24]) // no zooming out (1x), only zoom to 1hr (24x)
      .translateExtent([[0,0],[w+2*margin,h]])
      .on("zoom", zoom);

我也在考虑将我的宽度范围乘以d3.event.transform.k的缩放功能,这应该是我认为的缩放级别,但它并没有给我我想要的东西:

function zoom() {
    zoomCall.translateExtent([[0,0],[w+margin*2*d3.event.transform.k, h]]);

在添加translateExtent代码之后,有时在点击图表时,我的数据会向左或向右翻译20px。



  window.onload = function() {
    // parse the date / time functions
    var formatTime = d3.timeFormat("%H:%M"),
      formatMinutes = function(d) {
        return formatTime(new Date(2012, 0, 1, 0, d));
      };

    // Get and Prepare Data for gap_array and range_array
    var count_data = [
      {  
         "date_time":"\/Date(1494864780000)\/",
         "count":14
      },
      {  
         "date_time":"\/Date(1494864780000)\/",
         "count":11
      },
      {  
         "date_time":"\/Date(1494864780000)\/",
         "count":25
      },
      {  
         "date_time":"\/Date(1494864840000)\/",
         "count":31
      },
      {  
         "date_time":"\/Date(1494864840000)\/",
         "count":53
      },
      {  
         "date_time":"\/Date(1494864840000)\/",
         "count":56
      },
      {  
         "date_time":"\/Date(1494864900000)\/",
         "count":57
      },
      {  
         "date_time":"\/Date(1494864960000)\/",
         "count":68
      },
      {  
         "date_time":"\/Date(1494865020000)\/",
         "count":69
      },
      {  
         "date_time":"\/Date(1494865020000)\/",
         "count":70
      },
      {  
         "date_time":"\/Date(1494865140000)\/",
         "count":65
      },
      {  
         "date_time":"\/Date(1494865200000)\/",
         "count":68
      },
      {  
         "date_time":"\/Date(1494865320000)\/",
         "count":68
      },
      {  
         "date_time":"\/Date(1494865380000)\/",
         "count":68
      },
      {  
         "date_time":"\/Date(1494865500000)\/",
         "count":70
      },
      {  
         "date_time":"\/Date(1494865560000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494865680000)\/",
         "count":61
      },
      {  
         "date_time":"\/Date(1494865740000)\/",
         "count":61
      },
      {  
         "date_time":"\/Date(1494865860000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494865920000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494866040000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494866100000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494866220000)\/",
         "count":68
      },
      {  
         "date_time":"\/Date(1494866280000)\/",
         "count":66
      },
      {  
         "date_time":"\/Date(1494866400000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494866460000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494866580000)\/",
         "count":68
      },
      {  
         "date_time":"\/Date(1494866640000)\/",
         "count":66
      },
      {  
         "date_time":"\/Date(1494866760000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494866820000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494866940000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494867000000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494867120000)\/",
         "count":53
      },
      {  
         "date_time":"\/Date(1494867180000)\/",
         "count":66
      },
      {  
         "date_time":"\/Date(1494867300000)\/",
         "count":72
      },
      {  
         "date_time":"\/Date(1494867360000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494867480000)\/",
         "count":69
      },
      {  
         "date_time":"\/Date(1494867540000)\/",
         "count":70
      },
      {  
         "date_time":"\/Date(1494867660000)\/",
         "count":61
      },
      {  
         "date_time":"\/Date(1494867720000)\/",
         "count":28
      },
      {  
         "date_time":"\/Date(1494867720000)\/",
         "count":10
      },
      {  
         "date_time":"\/Date(1494867840000)\/",
         "count":60
      },
      {  
         "date_time":"\/Date(1494867900000)\/",
         "count":60
      },
      {  
         "date_time":"\/Date(1494868020000)\/",
         "count":50
      },
      {  
         "date_time":"\/Date(1494868020000)\/",
         "count":42
      },
      {  
         "date_time":"\/Date(1494868140000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494868200000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494868320000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494868380000)\/",
         "count":61
      },
      {  
         "date_time":"\/Date(1494868500000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494868560000)\/",
         "count":44
      },
      {  
         "date_time":"\/Date(1494868560000)\/",
         "count":14
      },
      {  
         "date_time":"\/Date(1494868680000)\/",
         "count":35
      },
      {  
         "date_time":"\/Date(1494868740000)\/",
         "count":73
      },
      {  
         "date_time":"\/Date(1494868860000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494868920000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494869040000)\/",
         "count":58
      },
      {  
         "date_time":"\/Date(1494869100000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494869220000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494869280000)\/",
         "count":62
      },
      {  
         "date_time":"\/Date(1494869400000)\/",
         "count":62
      },
      {  
         "date_time":"\/Date(1494869460000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494869580000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494869640000)\/",
         "count":55
      },
      {  
         "date_time":"\/Date(1494869700000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494869820000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494869880000)\/",
         "count":58
      },
      {  
         "date_time":"\/Date(1494869880000)\/",
         "count":58
      },
      {  
         "date_time":"\/Date(1494869880000)\/",
         "count":58
      },
      {  
         "date_time":"\/Date(1494870000000)\/",
         "count":35
      },
      {  
         "date_time":"\/Date(1494870060000)\/",
         "count":43
      },
      {  
         "date_time":"\/Date(1494870120000)\/",
         "count":53
      },
      {  
         "date_time":"\/Date(1494870180000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494870180000)\/",
         "count":6
      },
      {  
         "date_time":"\/Date(1494870180000)\/",
         "count":8
      },
      {  
         "date_time":"\/Date(1494870240000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494870240000)\/",
         "count":4
      },
      {  
         "date_time":"\/Date(1494870240000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494870240000)\/",
         "count":6
      },
      {  
         "date_time":"\/Date(1494870300000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494870300000)\/",
         "count":6
      },
      {  
         "date_time":"\/Date(1494870300000)\/",
         "count":15
      },
      {  
         "date_time":"\/Date(1494870300000)\/",
         "count":14
      },
      {  
         "date_time":"\/Date(1494870300000)\/",
         "count":22
      },
      {  
         "date_time":"\/Date(1494870360000)\/",
         "count":27
      },
      {  
         "date_time":"\/Date(1494870420000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494870540000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494870600000)\/",
         "count":67
      },
      {  
         "date_time":"\/Date(1494870720000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494870780000)\/",
         "count":63
      },
      {  
         "date_time":"\/Date(1494870900000)\/",
         "count":54
      },
      {  
         "date_time":"\/Date(1494870900000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494870900000)\/",
         "count":6
      },
      {  
         "date_time":"\/Date(1494870960000)\/",
         "count":15
      },
      {  
         "date_time":"\/Date(1494871020000)\/",
         "count":13
      },
      {  
         "date_time":"\/Date(1494871020000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494871080000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494871200000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494871260000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494871380000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494871440000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494871560000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494871620000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494888600000)\/",
         "count":6
      },
      {  
         "date_time":"\/Date(1494888600000)\/",
         "count":6
      },
      {  
         "date_time":"\/Date(1494888720000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494888780000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494888900000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494888960000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889080000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889140000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889260000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889320000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889380000)\/",
         "count":4
      },
      {  
         "date_time":"\/Date(1494889380000)\/",
         "count":4
      },
      {  
         "date_time":"\/Date(1494889380000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889380000)\/",
         "count":5
      },
      {  
         "date_time":"\/Date(1494889380000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889500000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889560000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889680000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889740000)\/",
         "count":4
      },
      {  
         "date_time":"\/Date(1494889740000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889860000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889920000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889920000)\/",
         "count":4
      },
      {  
         "date_time":"\/Date(1494889980000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494889980000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494890220000)\/",
         "count":5
      },
      {  
         "date_time":"\/Date(1494890220000)\/",
         "count":5
      },
      {  
         "date_time":"\/Date(1494890280000)\/",
         "count":6
      },
      {  
         "date_time":"\/Date(1494890340000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494890400000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494890520000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494890580000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494890700000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494890760000)\/",
         "count":0
      },
      {  
         "date_time":"\/Date(1494890880000)\/",
         "count":0
      },
                     ];

    count_data.forEach(function(d) {
      d.date_time = new Date(parseInt(d.date_time.replace(/\/Date\((-?\d+)\)\//gi, "$1")));
      //d.date_time = formatTime(d.date_time);
    });

    var maxY = d3.max(count_data, function(d) {
      return d.count;
    });
    var minY = 0;

    var minX = new Date(count_data[0].date_time).setHours(0, 0, 0, 0);
    var maxX = new Date(count_data[0].date_time).setHours(23, 59, 59, 999);

    var gap_array = [];
    var range_array = [];

    var range_start = moment(new Date(firstDateTime)),
      range_end,
      range_start_position = 0,
      range_end_position,
      in_range = true;

    var gap_start,
      gap_end,
      gap_start_position,
      gap_end_position,
      in_gap = false,
      gap_min = 2;

    var firstDateTime = count_data[0].date_time;
    var lastDateTime = count_data[count_data.length - 1].date_time;
    var date_previous = moment(new Date(firstDateTime));

    for (i = 0; i < count_data.length; i++) {
      var current = moment(new Date(count_data[i].date_time));
      if (current.diff(date_previous, "m") > gap_min && !in_gap) {

        range_end = date_previous;
        range_end_position = i - 1;
        in_range = !in_range;

        range_array.push({
          start: range_start.toDate(),
          end: range_end.toDate(),
          start_position: range_start_position,
          end_position: range_end_position
        });

        gap_start = date_previous;
        gap_start_position = i;
        in_gap = !in_gap;

      } else if (current.diff(date_previous, "m") <= gap_min && in_gap) {

        range_start_position = i;
        range_start = current;
        in_range = !in_range;

        gap_end_position = i;
        gap_end = current;
        in_gap = !in_gap;

        gap_array.push({
          start: gap_start.toDate(),
          end: gap_end.toDate(),
          start_position: gap_start_position,
          end_position: gap_end_position
        });

      } else if (i == count_data.length - 1) {

        if (in_gap) {
          gap_end_position = i;
          gap_end = current;
          in_gap = !in_gap;

          gap_array.push({
            start: gap_start.toDate(),
            end: gap_end.toDate(),
            start_position: gap_start_position,
            end_position: gap_end_position
          });
        } else {
          range_end = current;
          range_end_position = i;
          in_range = !in_range;

          range_array.push({
            start: range_start.toDate(),
            end: range_end.toDate(),
            start_position: range_start_position,
            end_position: range_end_position
          });
        }

      }
      date_previous = current;
    }

    gap_array.push({
      start: minX,
      end: firstDateTime,
      start_position: null,
      end_position: 0
    }); // push initial gap
    gap_array.push({
      start: lastDateTime,
      end: maxX,
      start_position: count_data.length - 1,
      end_position: null
    }); // push final gap

    var count_data_array = [];

    for (i = 0; i < range_array.length; i++) {
      count_data_array.push(count_data.slice(range_array[i].start_position, range_array[i].end_position + (range_array[i].end_position < count_data.length - 1 ? 1 : 0)));
    }

    //
    var margin = 40;
    var w = document.getElementById("d3-chart").offsetWidth - margin - margin,
      h = 250 - margin - margin;

    var x = d3.scaleTime().range([0, w]).domain([minX, maxX]);
    var y = d3.scaleLinear().range([h, 0]).domain([minY, maxY]);

    var zoomCall = d3.zoom()
      .scaleExtent([1, 24]) // no zooming out (1x), only zoom to 1hr (24x)
      .on("zoom", zoom);

    var container = d3.select("#d3-chart");

    var svg = container.append("svg")
      .attr("width", w + margin + margin)
      .attr("height", h + margin + margin);

    var g = svg.append("g")
      .attr("transform",
        "translate(" + margin + "," + margin + ")")
      .call(zoomCall);

    g.append("clipPath")
      .attr("id", "clip")
      .append("rect")
      .attr("width", w)
      .attr("height", h);

    var xAxis = d3.axisBottom(x).ticks(20); //.tickFormat(formatMinutes);
    var yAxis = d3.axisLeft(y);

    function zoom() {

      // re-scale y axis during zoom;
      xAxisCall.transition()
        .duration(50)
        .call(xAxis.scale(d3.event.transform.rescaleX(x)));

      // re-draw circles using new y-axis scale;
      var new_xScale = d3.event.transform.rescaleX(x);

      var new_valueline = d3.line()
        .x(function(d) {
          return new_xScale(d.date_time);
        })
        .y(function(d) {
          return y(d.count);
        });

      gaps.attr("x", d => new_xScale(d.start)).attr("width", d => new_xScale(d.end) - new_xScale(d.start)).attr("clip-path", "url(#clip)");
      for (i = 0; i < paths.length; i++) {
        paths[i]
          .attr("d", new_valueline).attr("clip-path", "url(#clip)");
      }
    }

    var gaps = g.selectAll('.gap')
      .data(gap_array)
      .enter().append('rect')
      .attr("class", "gap")
      .attr("x", d => x(d.start))
      .attr("y", 0)
      .attr("width", d => x(d.end) - x(d.start))
      .attr("height", h)
      .attr("fill", "#efefef");

    var xAxisCall = g.append("g")
      .attr("class", "axis")
      .attr("transform", "translate(0," + h + ")")
      .call(xAxis);

    var yAxisCall = g.append("g")
      .attr("class", "axis")
      .call(yAxis);

    // define the line
    var valueline = d3.line()
      .x(function(d) {
        return x(d.date_time);
      })
      .y(function(d) {
        return y(d.count);
      });

    var paths = [];

    // Add the valueline path.
    for (i = 0; i < count_data_array.length; i++) {
      paths.push(
        g.append("path")
        .data([count_data_array[i]])
        .attr("class", "line")
        .attr("d", valueline)
      );
    }

    g.append("rect")
        .attr("class", "overlay")
        .attr("width", w)
        .attr("height", h)

  };
&#13;
 #d3-chart {
   position: relative;
 }
 
 .axis {
   font: 14px sans-serif;
 }
 
 .line {
   fill: none;
   stroke: #3988ff;
   stroke-width: 2px;
}

.overlay {
    fill: none;
    pointer-events: all;;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.js"></script>
<h3>D3 Test</h3>
<div id="d3-chart"></div>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

逻辑上不确定原因,但边际偏移需要除以缩放系数。

UdpProtoBufServerHandler -> ProtobufEncoder -> ... -> ProtobufVarint32FrameDecoder
相关问题