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