d3.js ограничить панорамирование в силовом макете

1

Я использую d3.js с компоновкой сил, чтобы визуализировать большое количество узлов. Я хотел бы применить ограничение к опции панорамирования масштабирования. JSFiddle: https://jsfiddle.net/40z5tw8h/24/

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

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

Элемент группового удержания не должен уходить:

  • вниз более 20 пикселей от вершины svg.
  • справа больше 20 px с левой стороны svg.
  • вверху более 20 пикселей снизу svg.
  • осталось более 20 пикселей с правой стороны svg.

Я думаю, что вся реализация должна быть в функции масштабирования, которая на данный момент:

function zoomed(){
        if (d3.event.sourceEvent == null){ //when fitFullGraph uses the zoom
            g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
        }
        else{
            var gElementBounds = g.node().getBoundingClientRect();
            var g_bottom = gElementBounds.bottom;
            var g_top = gElementBounds.top;
            var g_left = gElementBounds.left;
            var g_right = gElementBounds.right;
            var g_height = gElementBounds.height;
            var g_width = gElementBounds.width;

            var svg = g.node().parentElement;
            var svgElementBounds = svg.getBoundingClientRect();
            var svg_bottom = svgElementBounds.bottom;
            var svg_top = svgElementBounds.top;
            var svg_left = svgElementBounds.left;
            var svg_right = svgElementBounds.right;
            var svg_height = svgElementBounds.height;
            var svg_width = svgElementBounds.width;

            var t = d3.event.translate;
            var margin = 20;

            if(d3.event.sourceEvent.type == 'wheel'){//event is zoom
                g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");

            }
            else{//event is pan
                // if(t[0] < svg_left + margin) t[0]= svg_left + margin;
                //else if(t[0] > svg_width-g_width - margin) t[0] = svg_width-g_width - margin;
                // if(t[1] < g_height +margin) t[1] = g_height + margin;
                //else if (t[1] > svg_height - margin) t[1] = svg_height - margin;
               //.attr("transform", "translate(" + t+ ")scale(" + d3.event.scale + ")");
               //3.event.translate = t;
                g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
            }

        }

    }

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

У кого-нибудь есть решение?

Теги:
d3.js
transform
translate
pan

1 ответ

0

Это не полный ответ на ваш вопрос.

Я использовал для панорамирования блоков влево перевести шкалу X

var translate = d3.event.translate;
var translateX = translate[0];
var translateY = translate[1];
var scale = d3.event.scale;
var tX = translateX * scale;
var tY = translateY * scale;
console.log('tx', tX, 'ty', tY);
// Do not pan more to left
if (tX> 0) {
  g.attr("transform", "translate(" + d3.event.translate + ")  scale(" + d3.event.scale + ")");
} else {
  translate[0] = 0;
  g.attr("transform", "translate(" + translate + ")  scale(" + d3.event.scale + ")");
}

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню