Подтвердить что ты не робот

Фильтровать данные в d3, чтобы нарисовать круг или квадрат

У меня возникли проблемы с пониманием выбора и фильтрации в d3. Скажем, у меня есть простой массив:

data = [1, 2, 6, 3, 4]

Я хочу нарисовать круги, если значение < 5 и квадратов, если он >= 5. Мой код сейчас только рисует круги и выглядит так:

var svg = d3.select("body").append("svg")
svg.selectAll("shapes")
    .data(data)
    .enter()
    .append("circle")

и другие атрибуты для кругов. Мне нужно использовать метод .filter(), но я не знаю, куда его поместить. Я попытался сделать что-то вроде:

var svg = d3.select("body").append("svg")
svg.selectAll("shapes")
    .data(data)
    .enter()
    .filter(function(d){if (d>5){console.log('working');})
    .append("circle")

но затем я получаю сообщение об ошибке с помощью метода append. Может ли кто-нибудь указать мне в правильном направлении, как я это выполнил?

4b9b3361

Ответ 1

Проблема в том, что после .enter() вы возвращаете вложенный массив, следовательно, ваша ошибка:

Uncaught TypeError: Object [object Array] не имеет метода 'append'

Чтобы использовать .filter(), вам необходимо применить его после .append():

var data = d3.range(10);
var svg = d3.select("body").append("svg");

var shapes = svg.selectAll(".shapes")
    .data(data).enter();

shapes.append("circle")
    .filter(function(d){ return d < 5; })
    .attr("cx", function(d, i){ return (i+1) * 25; })
    .attr("cy", 10)
    .attr("r", 10);

shapes.append("rect")
    .filter(function(d){ return d >= 5; })
    .attr("x", function(d, i){ return (i+1) * 25; })
    .attr("y", 25)
    .attr("width", 10)
    .attr("height", 10);

Используя приведенный выше код (также в этой скрипке), я получаю следующий вывод:

enter image description here

Обратите внимание, что вы также можете добиться того же эффекта с помощью метода фильтра массивов.

var shapes = svg.selectAll(".shapes")
    .data(data.filter(function(d){ return d < 5; })).enter()
    .append("circle")
    .attr("cx", function(d, i){ return (i+1) * 25; })
    .attr("cy", 10)
    .attr("r", 10);

Ответ 2

Также можно использовать данные для условного создания окружностей или прямоугольников путем предоставления аргумента функции функции append

    .append(function(d, i){
        if (something to do with d) {
            ... return an SVG circle element
        } else {
            ... return an SVG rectangle element
        }
    })

например. как это

var data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var svg = d3.select("body").append("svg");

function createSvgEl(name) {
    return document.createElementNS('http://www.w3.org/2000/svg', name);
}

svg
    .selectAll(".shapes")
    .data(data)
    .enter()
    .append(function(d, i){
        if (d <= 4) {
            return createSvgEl("circle");
        } else {
            return createSvgEl("rect");
        }
    });

svg.selectAll("circle")
        .attr("cx", function(d, i){ return (i+1) * 25; })
        .attr("cy", 10)
        .attr("r", 10);

svg.selectAll("rect")
        .attr("x", function(d, i){ return (i+1) * 25; })
        .attr("y", 25)
        .attr("width", 10)
        .attr("height", 10);