D3 Transform Rescale X向右跳转

D3 Transform Rescale X jumps to right

我正在创建一个显示 5 或 6 条不同线条的时间线折线图,并希望能够放大和滚动(一旦缩放)。我使用了一些使用面积图的示例,但出于某种原因,当我第一次缩放时,我的折线图跳到右边,我丢失了一些右边的数据(我无法再滚动查看它或在缩放时看到它完全退出)。当我缩放或滚动时,这些线也会出现在 y 轴上。

我已经将它复制到 JSFiddle (see here) 中,其中包含我图表中 1 行的数据集。为什么一使用缩放功能就向右跳线?我怎样才能阻止这条线出现在 y 轴上?

这里是我的版本的 JS,如果你想在这里阅读的话:

function drawTimeline() {

    var margin = {top: 10, right: 0, bottom: 50, left: 60}
    var width = d3.select('#timeline').node().getBoundingClientRect().width/3*2;
    var height = 300;

    var svg = d3.select("#timeline").append("svg")
        .attr("width", width)
        .attr("height", height+margin.top+margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .attr("width", width - margin.left - margin.right)
        .call(d3.zoom()
                // .extent()
                .scaleExtent([1, 10])
                .translateExtent([[0, -Infinity], [width - margin.left - margin.right, Infinity]])
                .on("zoom", zoom)
        );

    var view = svg.append("rect")
        .attr("class", "view")
        .attr("width", width - margin.left - margin.right)
        .attr("height", height)
        .attr("fill", "white");

    var x = d3.scaleTime()
            .domain([
                d3.min(poll_data[0].avgpolls, function(p) { return p.date; }), 
                d3.max(poll_data[0].avgpolls, function(p) { return p.date; })
            ])
            .range([0, width - margin.left - margin.right]);

    var y = d3.scaleLinear()
            .domain([50, 0])
            .range([0, height]);


    var xAxis = d3.axisBottom(x);
    var yAxis = d3.axisLeft(y);

    var gX = svg.append("g")
                  .attr("class", "axis xaxis")
                .attr("transform", "translate(0," + height + ")")
                .call(d3.axisBottom(x));

    var gY = svg.append("g")
                .attr("class", "axis yaxis")
                .call(yAxis);

    //All lines are drawn in the same way (x and y points)
    var line = d3.line()
        .x(function(d) { return x(d.date); })
        .y(function(d) { return y(d.poll); });

    //selectAll allows us to create and manipulate multiple groups at once
    var party = svg.selectAll(".party")
        .data(poll_data)
        .enter()
        .append("g")
        .attr("class", "party");

    //Add path to every country group at once
    var pollPaths = party.append("path")
        .attr("class", "line")
        .attr("d", function(d) { return line(d.avgpolls); })
        .attr("fill", "none")
        .attr("stroke-width", 2)
        .style("stroke", function(d) { return returnPartyColour(d.party); });

    function zoom() {
      console.log("zooming: " + d3.event.transform);
      var new_x = d3.event.transform.rescaleX(x);
      gX.call(d3.axisBottom(new_x));
      //view.attr("transform", d3.event.transform);

      //Redraw lines
      //pollPaths.select(".line").attr("d", function(d) { return line(d.avgpolls); });
      var newline = d3.line()
        .x(function(d) { return new_x(d.date); })
        .y(function(d) { return y(d.poll); });

      pollPaths.attr("d", function(d) { return line(d.avgpolls); });
    }

}

数据在我的版本中是这样格式化的,但不是 JSFiddle:

poll_data = [
    {
        'party' : 'Party 1',
        'avgpolls' : [
            {'date' : new Date(year, month, day), 'poll' : 0, },
        ],

]

谢谢

解决这些问题需要两件事。

缩放时跳线的原因是未设置缩放范围。已设置并更新了 translateExtent 的值:

d3.zoom()
    .scaleExtent([1, 10])
    .translateExtent([[0, 0], [width - margin.left - margin.right, Infinity]])
    .extent([[0, 0], [width - margin.left - margin.right, height]])
    .on("zoom", zoom)

为了防止路径溢出,需要剪切路径。创建 svg 之后,在添加其他元素之前,我添加了一个 clip-path 如下:

svg.append("defs").append("clipPath")
    .attr("id", "clip")
    .append("rect")
    //Same dimensions as the area for the lines to appear
    .attr("width", width - margin.left - margin.right)
    .attr("height", height);

然后这必须添加到每个路径。

var pollPaths = party.append("path")
    ...
    .attr("clip-path", "url(#clip)");

原始 JSFiddle updated 反映了这些变化。