D3 Transform Rescale X перемещается вправо

1

Я создаю график временной шкалы, показывающий 5 или 6 разных строк, и хочу иметь возможность масштабирования и прокрутки (после увеличения). Я использовал некоторые примеры, которые используют диаграммы областей, но по какой-то причине моя линейная диаграмма прыгает вправо, когда я увеличиваю масштаб в первый раз, и я теряю некоторые данные вправо (я больше не могу прокручивать, чтобы увидеть его или увидеть его при увеличении полностью отсутствует). Также линии появляются по оси y, когда я масштабирую или прокручиваю.

Я скопировал его в JSFiddle (см. Здесь) с набором данных из 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, },
        ],

]

Спасибо

Теги:
d3.js
zoom

1 ответ

1
Лучший ответ

Для устранения этих проблем необходимо выполнить две задачи.

Причина, по которой линия прыгала по масштабированию, была связана с тем, что масштаб не был установлен. Это значение установлено и значение 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, перед добавлением других элементов, я добавил клип-путь следующим образом:

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 был обновлен, чтобы отразить эти изменения.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню