Проблема с кодом является то, что расположение стратегия пересматривается каждый раз, когда отображается диаграмма. Обычно время рендеринга ~ 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-маркированной макет в ближайшее время.
Можете ли вы предоставить более полный и управляемый пример, демонстрирующий вашу проблему? – ColinE
Hi @ColinE - я не могу опубликовать фактический код, поскольку он встроен в более крупную систему пользовательского интерфейса Sencha ExtJS, но я попытался представить упрощенную версию кода, чтобы показать, как я использую d3fs. Спасибо, что пытались помочь! –
Я думаю, что это займет немного работы, чтобы разобраться - вычисление компоновки занимает около 100 мс, что всегда будет делать ваш «прыгающий» масштаб. Я поднял проблему здесь (https://github.com/d3fc/d3fc-label-layout/issues/24) и попытаюсь найти достойное решение. – ColinE