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

#javascript #d3.js #transform #translate #pan

#javascript #d3.js #преобразование #перевести #панорамирование

Вопрос:

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

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

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

Элемент, удерживающий группу, не должен иметь возможности перейти:

  1. вниз более чем на 20 пикселей от верхней части svg.
  2. справа более чем на 20 пикселей от левой части svg.
  3. более чем на 20 пикселей от нижней части svg.
  4. слева более чем на 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   ")");
            }

        }

    }
  

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

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

Ответ №1:

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

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

 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   ")");
}
  

Который отменяет перевод влево, но внутренне он продолжается. Ваш пользователь, вероятно, перестает перетаскивать влево. Панорамирование вправо становится странным при запуске панорамирования, поскольку внутренне событие переместилось далеко влево.