#javascript #d3.js #transform #translate #pan
#javascript #d3.js #преобразование #перевести #панорамирование
Вопрос:
Я использую d3.js с принудительным макетом для визуализации большого количества узлов. Я хотел бы реализовать ограничение на параметр панорамирования при масштабировании. JSFiddle :https://jsfiddle.net/40z5tw8h/24 /
Вышеупомянутая скрипка содержит простую версию того, над чем я работаю. Поскольку мне потенциально пришлось бы визуализировать очень большой набор данных, я использую функцию для уменьшения размера элемента, удерживающего группу (‘g’), после выполнения принудительных действий. Таким образом, у меня всегда есть полная визуализация, видимая впоследствии.
Я хотел бы ограничить панорамирование — когда график полностью виден, чтобы иметь возможность перемещать его только в пределах области просмотра. В случае увеличения макета я хотел бы ограничить панорамирование следующим образом:
Элемент, удерживающий группу, не должен иметь возможности перейти:
- вниз более чем на 20 пикселей от верхней части svg.
- справа более чем на 20 пикселей от левой части 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 ")");
}
}
}
Ограничения, которые я пытался реализовать, закомментированы, поскольку они не работают должным образом.
У кого-нибудь есть решение?
Ответ №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 ")");
}
Который отменяет перевод влево, но внутренне он продолжается. Ваш пользователь, вероятно, перестает перетаскивать влево. Панорамирование вправо становится странным при запуске панорамирования, поскольку внутренне событие переместилось далеко влево.