2016-12-10 3 views
0

Я пытаюсь сделать что-то о перекрытии меток на диаграммах рассеяния, подобных изображению на картинке.D3: расположение меток на диаграммах рассеяния

Я использую d3fc, и он действительно хорошо позиционирует метки, однако он медленный даже при небольшом количестве точек (> 100), но фактическое требование обычно составляет> 1000 пунктов. Потребуется много времени, чтобы сначала построить диаграмму, а масштабирование/заполнение практически невозможно.

Есть ли что-то, что я делаю неправильно с d3fc? Если нет, существуют ли какие-либо другие устойчивые подходы к автоматической маркировке меток?

Я использую жадную стратегию:

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

fc.layoutGreedy()

Вот jsFiddle с упрощенным воспроизводимым кода (хотя это не загружает d3fs ОМТ) - https://jsfiddle.net/f5oxcyg7/

enter image description here

+0

Можете ли вы предоставить более полный и управляемый пример, демонстрирующий вашу проблему? – ColinE

+0

Hi @ColinE - я не могу опубликовать фактический код, поскольку он встроен в более крупную систему пользовательского интерфейса Sencha ExtJS, но я попытался представить упрощенную версию кода, чтобы показать, как я использую d3fs. Спасибо, что пытались помочь! –

+0

Я думаю, что это займет немного работы, чтобы разобраться - вычисление компоновки занимает около 100 мс, что всегда будет делать ваш «прыгающий» масштаб. Я поднял проблему здесь (https://github.com/d3fc/d3fc-label-layout/issues/24) и попытаюсь найти достойное решение. – ColinE

ответ

1

Проблема с кодом является то, что расположение стратегия пересматривается каждый раз, когда отображается диаграмма. Обычно время рендеринга ~ 100 мс при первом рендеринге диаграммы не является проблемой, но если вам нужно плавное панорамирование/масштабирование, это становится проблемой.

Решение, которое я разработал, состоит в том, чтобы «кэшировать» результат компоновки, чтобы он не подвергался переоценке при увеличении графика. Однако, когда операция масштабирования завершается, макет повторно оценивается для удаления коллизий.

Во-первых, зум события обрабатываются, чтобы включить поведение кэша включения/выключения:

var returnCachedLayout = false; 
var zoomBeh = d3.behavior.zoom() 
    .x(x) 
    .y(y) 
    .scaleExtent([0, 500]) 
    .on("zoomstart", function() { 
     returnCachedLayout = true; 
     zoom() 
    }) 
    .on("zoom", zoom) 
    .on("zoomend", function() { 
     returnCachedLayout = false; 
     zoom() 
    }) 

Тогда стратегия адаптирована для использования кэша:

var strategyCache = function (strategy) { 
    var cachedLayout; 

    var cache = function(layout) { 
    if (!returnCachedLayout) { 
     cachedLayout = strategy(layout); 
     // determine the offset applied by the layout 
     for (var i = 0; i< layout.length; i++) { 
     cachedLayout[i].dx = layout[i].x - cachedLayout[i].x; 
     cachedLayout[i].dy = layout[i].y - cachedLayout[i].y; 
     } 
    } else { 
     // update the location of each label, including the offset 
     for (var i = 0; i< layout.length; i++) { 
     cachedLayout[i].x = layout[i].x - cachedLayout[i].dx; 
     cachedLayout[i].y = layout[i].y - cachedLayout[i].dy; 
     } 
    } 
    return cachedLayout; 
    }; 
    return cache; 
}; 

// construct a strategy that uses the "greedy" algorithm for layout, wrapped 
// by a strategy that removes overlapping rectangles. 
var strategy = strategyCache(fc.layout.strategy.removeOverlaps(fc.layout.strategy.greedy())); 

Это немного сложнее потому что вы не можете просто повторно отображать метки из кеша, потому что поведение масштабирования заставит эти точки двигаться. Вот почему смещение также сохраняется, чтобы его можно было повторно применить к этикеткам в новом месте.

Во всяком случае, вот полный пример:

https://jsfiddle.net/qrpr0wre/

Я буду смотреть, чтобы сделать это «первый класс» особенность d3fc-маркированной макет в ближайшее время.

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

  • Нет связанных вопросов^_^