В d3.js пропустите append () для нулевых данных

Я рисую линейный график из маленьких круглых маркеров. Однако в данных есть дыры, которые представлены нулем в моем массиве. Естественно, там, где нет данных, не должно быть кружков. Но метод append () d3 все равно добавляет их. Как мне избежать этого?

Вот этоjsFiddle макет точно воспроизвести мою проблему.

Я заинтересован в том, чтобы НЕ иметь ту серию окружностей, которые лежат на оси X моего графа, поскольку все они равны нулю.

Соответствующий код из ссылки jsfiddle:

svg.selectAll('circle').data(values).enter()
  .append('circle')// <-- I don't want to do this for null's
  .attr('fill', '#c00')
  .attr('r', 3)
  .attr('cx', xi)
  .attr('cy', yFlipped)
 Madhur12 июн. 2018 г., 08:16
Привет, если вы найдете решение, пожалуйста, скажите мне. если мне нужно остановить рисовать диагональный узел из нулевых значений. Как это сделать?

Ответы на вопрос(5)

values.filter(function(el){return el !== null;})
 meetamit31 мая 2012 г., 05:11
Спасибо, но это просто удаляет эти элементы из массива, что влияет на индекс, который передается в мои функции установки attr (). Мне нужно, чтобы индекс оставался неизменным, потому что это то, что я использую для вычисления x позиций.
 06 нояб. 2015 г., 10:18
Это была моя проблема, и я чувствовал себя глупо, даже не думая о том, чтобы просто отфильтровать. Полагаю, я так увлекся "Как это делает d3?" что я не думал :)

если вы хотите, чтобы никогда не добавлять его в первую очередь. Я использовал оператор if внутри .each (), а затем d3.select (this), чтобы добавить его к текущему элементу.

var data = [9, 0, 7, 0, 5, 0, 3, 0, 1];

var svg = d3.select('#svg').append('svg').attr({'viewBox': '-10 -10 99 20'});

svg.selectAll('g').data(data).enter().append('g').each(function (d,i) {
 if(d){
  d3.select(this).append('circle').attr({r:5,cx:(i*9)});
 }else{
  d3.select(this).remove();
 }
});

Вот корзинаhttp://jsbin.com/qojifug/edit?js,output

 meetamit13 февр. 2017 г., 17:47
Да & # x2014; призвание.remove() достигает результата, имея только столько<g>с, как есть ненулевые вdata, Это также держитi синхронно с положениемd вdata, Но, в зависимости от более широкого контекста, могут возникнуть проблемы с этим. Например, если вам нужно вызвать дополнительную функцию (например,.attr или же.remove) наupdating или жеexiting результаты этого.data() присоединиться, вы можете получить ошибку, потому что некоторые элементы будут уже удалены. Кроме того, если вы позже повторноselectAll() <g>и присоединиться к ним с данными,i может больше не синхронизироваться сdмассив поз.
 11 февр. 2017 г., 15:39
Спасибо за обзор. Как насчет добавления еще, чтобы удалить g, если нет d? & quot; else {d3.select (this) .remove ()} & quot;
 meetamit13 февр. 2017 г., 17:56
Без тестирования я не уверен, что проблемные примеры, на которые я указал, на самом деле будут иметь место, как описано. Я в основном исходил из предположения, что если вы когда-либо.remove() член выбора d3 без использованияexiting выбор для этого, вы могли бы иметь проблемы. Поскольку я разместил этот вопрос (5 лет назад, господи), я в основном принял рекомендацию mbostock (на этой странице), чтобы почти никогда не полагаться наi для представления данных и вместо использованияd как можно больше.
 meetamit30 янв. 2017 г., 23:49
Хотя это пропускает добавление<circle>, он все еще добавляет<g> в качестве контейнера & # x2014; просто оставляет его пустым, когдаd равно 0. Хотя это может быть выгодно в том случае, если вы намереваетесь также добавить другие элементы внутри этого<g>это не пропускает добавление<g>, Также в.selectAll('z') так должно быть.selectAll('g')в противном случае повторите вызовы этого кода (даже если с тем жеdata) добавлю дополнительные<g> элементы каждый раз.

// Step 1: hides all circles which are "null"
d3.selectAll(".yourItem")
.data(data)
.enter()
    .append("circle")
    .attr("visibility", function(d,i){
        if(yourFunction(d) == null) return "hidden";
})

// Step 2: optional, deletes all circles which are "hidden"
d3.selectAll("circle[visibility=hidden]").remove();

Самый простой вариант - отфильтровать нули из данных, передаваемых в.data(…), увеличивая данные для поддержания индекса:

svg.selectAll('circle')
  .data(values
    .map(function(v, idx) { return v == null? null : { idx: idx, value: v })
    .filter(function(v) { return v != null })
  )
  .enter()
    .append('circle')
    .attr('fill', '#c00')
    .attr('r', 3)
    .attr('cx', function(d) { return d.idx * 10 }) // or whatever
    .attr('cy', function(d) { return d.value.y }) // or whatever

Обратите внимание, что вы также можете следовать этому шаблону для отдельных подэлементов, даже если они не являются естественными списками. Например, рассмотрим ситуацию, когда вы хотите условно добавить второй круг:

var circles = [
    { color: 'red', cx: 30, cy: 30, subCircleColor: 'blue' },
    { color: 'blue', cx: 60, cy: 60, subCircleColor: 'green' },
    { color: 'green', cx: 90, cy: 90 },
];

// Create a group which will hold the circles, since the result will
// be:
//    <g class="circles">
//      <circle color="{{ color }}" ... />
//      <circle class="sub-circle" color="{{ subCircleColor }}" ... />
//    </g>
var circlesGroups = svg.selectAll("g.circles")
    .data(circles)
    .enter()
        .append("g").attr({"class": "circles"})

// Add the first circle to the group
circlesGroups
    .append("circle").attr({
        "fill": function(d) { return d.color },
        "r": 20,
        "cx": function(d) { return d.cx },
        "cy": function(d) { return d.cy },
    })

// If there is a subCircleColor, add the second circle to the group
circlesGroups.selectAll("circle.sub-circle")
    .data(function(d) {
        if (d.subCircleColor)
            return [d];
        return [];
    })
    .enter()
        .append("circle").attr({
            "class": "sub-circle",
            "fill": function(d) { return d.subCircleColor; },
            "r": 10,
            "cx": function(d) { return d.cx },
            "cy": function(d) { return d.cy },
        })

Скрипки:http://jsfiddle.net/3d6e648k/

Решение Вопроса

Один из вариантов состоит в том, чтобы представлять ваши данные по-разному, чтобы вы не зависели от индекса для вычисления x-координаты. Например, если вы представляли каждый элемент данных как объект (например,{x: 0, y: 0.2840042}) тогда вы могли бы вычислить координату X какx(d.x) скорее, чемx(i).

Другой вариант - установить радиус на ноль, если значение равно нулю, поэтому круги скрыты:circle.attr("r", function(d) { return d == null ? 0 : 3; }), Или вы можете скрыть круги:circle.style("display", function(d) { return d == null ? "none" : null; }).

Вы также можете удалить нулевые элементы после добавления их:circle.filter(function(d) { return d == null; }).remove(), Это сработало бы для первоначального создания, но я бы не рекомендовал его, поскольку индекс изменился бы, если бы вы повторно выбрали элементы позже.

 23 июл. 2015 г., 15:02
Я использовалcircle.filter(function(d) { return d == null; }).remove() метод для моего вопроса, и он работал прекрасно!
 25 сент. 2014 г., 23:40
Кроме того, что касается подхода с нулевым радиусом - с моим большим, но разреженным массивом, я получаю намного лучшую производительность, когда я создаю и использую новый фильтрованный массив черезdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/…, Я понимаю, что @meetamit хочет сохранить исходные индексы, но подумал, что могу указать, что это может иметь нежелательные последствия для производительности. Возможно, d3 может решить эту проблему путем короткого замыкания, когда r & lt; = 0, или реализовать "определенные" значения. функция для круга?

Ваш ответ на вопрос