2014-06-30 5 views
5

Проводка как вопрос & ответить здесь, чтобы спасти кого-то еще те же проблемы позже ...Sunburst данных разделов перезаписаны второй Sunburst на той же странице

Когда я создаю два Sunburst диаграммы с использованием d3.layout.partition, ломтика пропорции первого SunBurst в заменяются пропорциями среза второй солнечной вспышки при изменении размеров срезов.

Эти две диаграммы передают различные функции доступа в макет раздела, например.

d3.layout.partition() 
.sort(null) 
.value(function(d) { return 1; }); 

против

d3.layout.partition() 
.sort(null) 
.value(function(d) { return d.size; }); 

И они создают свой собственный список узлов, которые не распределяются между двумя завиток. Однако, если я перезвоню генератору d3.svg.arc, чтобы изменить его размер до большего радиуса (но не изменить общие пропорции), углы среза будут внезапно перезаписаны.

Смотрите пример здесь: http://bl.ocks.org/explunit/ab8cf15534f7fec5ac6d

ответ

3

Проблема заключается в том, что в то время как partition.nodes()кажется для создания новой структуры данных (например, если вы даете ему некоторые .key функции, он записывает дополнительные свойства (например, .x, .y, .dx, dy) для исходных данных и не делают копию данных. Таким образом, если структура данных разделена между двумя картами, эти .x, .y, .dx, dy свойств будут ли d до других графиков.

Это кажется ошибкой для меня, но при чтении this old GitHub issue это похоже на «по дизайну». Возможно, он будет пересмотрен в будущих версиях.

Одним из способов является использование чего-то вроде Lodash/Underscore cloneDeep или Angular's copy, чтобы каждый график имел свою собственную копию данных.

makeSunburst(null, _.cloneDeep(root), countAccessorFn); 
makeSunburst(null, _.cloneDeep(root), sizeAccessorFn); 

Смотрите пример здесь: http://bl.ocks.org/explunit/e9efb830439247eea1be

2

Альтернатива скопировать весь набор данных для каждой карты будет просто пересчитывать раздел перед повторной визуализацией.

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

// create separate partition variables 
var countPartition = d3.layout.partition().sort(null).value(countAccessorFn); 
var sizePartition = d3.layout.partition().sort(null).value(sizeAccessorFn); 

// make the charts as a function of partition 
charts.push(makeSunburst(root, countPartition)); 
charts.push(makeSunburst(root, sizePartition)); 

Затем перед нанесением перехода, просто обновить переменную nodes, чтобы отразить соответствующий раздел:

addToRadius: function(radiusChange) { 
    radius += radiusChange; 
    ringRadiusScale.range([0, radius]); 

    // update the data before re-rendering each chart 
    nodes = partition.nodes(dataRoot); 
    path.transition().attr('d', arc); 
} 

Теперь, когда вы обновляете каждую таблицу, то с помощью правильный раздел.

Вот updated example.

+0

Да, это еще одно допустимое обходное решение.Ни обходное решение не должно быть необходимым, ИМО, но я думаю, что авторам D3 не понравилось обертывание исходных данных. – explunit

+0

Попробуйте представить, что произойдет, если ваши данные будут постоянно обновляться. Копирование всего набора данных для каждой диаграммы имеет смысл, если вы знаете, что данные никогда не будут меняться, но это не похоже, что это должно быть поведение по умолчанию. Там должен быть способ сохранить эти копии данных в синхронизации друг с другом. Что, если вы делаете 20 карт? Должно ли d3 сделать 20 копий данных и попытаться синхронизировать изменения во всех 20 из них? Для меня имеет смысл просто перекомпилировать раздел, поскольку это все, что отличается между графиками. – jshanley

+0

Но это несовместимо с тем, как работают другие части D3, например. Пировая компоновка обертывает исходные данные в свойство '.data'. – explunit

Смежные вопросы