d3.js график разброса масштабирования/перетаскивания

Я работаю над точечной диаграммой d3.js и хочу, чтобы ее можно было масштабировать без изменения размера точек. Я основывался на http://static.cybercommons.org/js/d3/examples/zoom-pan/zoom-pan.html, в котором есть работающие масштабируемые линии сетки, но пока у меня возникают проблемы с увеличением точек. Когда я масштабирую/панорамирую, каждая точка возвращает следующее предупреждение консоли:

Неожиданное значение translate(NaN,0) при синтаксическом анализе атрибута преобразования.

Вы можете увидеть все это полностью здесь со скриншотами дизайна под ним (нажмите «Открыть в новом окне», чтобы увидеть все это): http://bl.ocks.org/242dcfc83d98743d8589

Упрощенная версия JS здесь:

d3.csv("js/AllOccupations.csv", function(data) {

    var margin = {top: 30, right: 10, bottom: 50, left: 60},
        width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

    var xMax = d3.max(data, function(d) { return +d.TotalEmployed2011; }),
        xMin = 0,
        yMax = d3.max(data, function(d) { return +d.MedianSalary2011; }),
        yMin = 0;

    //Define scales
    var x = d3.scale.linear()
        .domain([xMin, xMax])
        .range([0, width]);

    var y = d3.scale.linear()
        .domain([yMin, yMax])
        .range([height, 0]);

    var colourScale = function(val){
        var colours = ['#9d3d38','#c5653a','#f9b743','#9bd6d7'];
        if (val > 30) {
            return colours[0];
        } else if (val > 10) {
            return colours[1];
        } else if (val > 0) {
            return colours[2];
        } else {
            return colours[3];
        }
    };


    //Define X axis
    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom")
        .tickSize(-height)
        .tickFormat(d3.format("s"));

    //Define Y axis
    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        .ticks(5)
        .tickSize(-width)
        .tickFormat(d3.format("s"));

    var svg = d3.select("#chart").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(d3.behavior.zoom().x(x).y(y).scaleExtent([1, 8]).on("zoom", zoom));

    svg.append("rect")
        .attr("width", width)
        .attr("height", height);

    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis);

    // Create points
    svg.selectAll("polygon")
        .data(data)
        .enter()
        .append("polygon")
        .attr("transform", function(d, i) {
            return "translate("+x(d.TotalEmployed2011)+","+y(d.MedianSalary2011)+")";
        })
        .attr('points','4.569,2.637 0,5.276 -4.569,2.637 -4.569,-2.637 0,-5.276 4.569,-2.637')
        .attr("opacity","0.8")
        .attr("fill",function(d) {
            return colourScale(d.ProjectedGrowth2020);
        });

    // Create X Axis label
    svg.append("text")
        .attr("class", "x label")
        .attr("text-anchor", "end")
        .attr("x", width)
        .attr("y", height + margin.bottom - 10)
        .text("Total Employment in 2011");

    // Create Y Axis label
    svg.append("text")
        .attr("class", "y label")
        .attr("text-anchor", "end")
        .attr("y", -margin.left)
        .attr("x", 0)
        .attr("dy", ".75em")
        .attr("transform", "rotate(-90)")
        .text("Median Annual Salary in 2011 ($)");


    function zoom() {
      svg.select(".x.axis").call(xAxis);
      svg.select(".y.axis").call(yAxis);
    }
});

Любая помощь будет принята с благодарностью.


person richardwestenra    schedule 14.02.2013    source источник


Ответы (1)


Линии сетки в примере на самом деле являются отметками оси! Таким образом, вы заметите, что ваша функция масштабирования обновляет их при событиях мыши, но вы никогда не обновляете положение точек. Вы должны скопировать линии позиционирования точек в функцию масштабирования (или выделить ее в отдельную функцию).

Вот как выглядит мой:

function zoom() {
    svg.select(".x.axis").call(xAxis);
    svg.select(".y.axis").call(yAxis);
    svg.selectAll("polygon")
        .attr("transform", function(d, i) {
            return "translate("+x(d.TotalEmployed2011)+","+y(d.MedianSalary2011)+")";
        })
        .attr('points','4.569,2.637 0,5.276 -4.569,2.637 -4.569,-2.637 0,-5.276 4.569,-2.637');
}

Вы можете попробовать его здесь

person Superboggly    schedule 15.02.2013
comment
Идеальный! Я подумал, что мне нужно что-то добавить к функции масштабирования, но я не мог сообразить, что именно. Большое спасибо! Для справки в будущем: предложенное вами решение позволяет точкам переполнять сетку и располагаться на осях, поэтому я обернул их в SVG, чтобы они содержались следующим образом: svg.append(svg) .attr(class, points) .attr(width, ширина) .attr(высота, высота) .selectAll(полигон) .data(данные) .enter() .append(полигон) ... - person richardwestenra; 15.02.2013