J'ai plusieurs graphiques mis en place pour zoomer sur le conteneur et cela fonctionne très bien. Cependant, lors du chargement initial, le niveau de zoom est trop proche. Existe-t-il une méthode permettant de définir le niveau de zoom initial pour éviter d'avoir à effectuer un zoom arrière? Je connais la méthode .scale()
mais je n’ai pas eu la chance de l’appliquer. Est-ce la voie à suivre ou y a-t-il quelque chose qui me manque?
Voici ce que j'ai jusqu'à présent en ce qui concerne le zoom:
var margin = {top: 20, right: 120, bottom: 20, left: 120},
width = 50000 - margin.right - margin.left,
height = 120000 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([0, width])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, height])
.range([height, 0]);
var tree = d3.layout.tree()
.size([height, width])
.separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.x, d.y]; });
function zoom(d) {
svg.attr("transform",
"translate(" + d3.event.translate + ")"+ " scale(" + d3.event.scale + ")");
}
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("pointer-events", "all")
.call(d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([0,8])
.on("zoom", zoom))
.append('g');
svg.append('rect')
.attr('width', width*5)
.attr('height', height)
.attr('border-radius', '20')
.attr('fill', 'sienna');
J'ai finalement obtenu ce travail en mettant tous les deux la transformation initiale et le comportement du zoom à la même valeur.
var zoom = d3.behavior.zoom().translate([100,50]).scale(.5);
vis = svg.append("svg:svg")
.attr("width", width)
.attr("height", height)
.call(zoom.on("zoom",zooming))
.append("svg:g")
.attr("transform","translate(100,50)scale(.5,.5)");
Réponse D3v4
Si vous recherchez la même chose mais avec D3 v4,
var zoom = d3.zoom().on("zoom", zooming);
vis = svg.append("svg:svg")
.attr("width", width)
.attr("height", height)
.call(zoom) // here
.call(zoom.transform, d3.zoomIdentity.translate(100, 50).scale(0.5))
.append("svg:g")
.attr("transform","translate(100,50) scale(.5,.5)");
Ajout de cette réponse sous forme d’addenda à la réponse acceptée au cas où des problèmes persisteraient:
Ce qui rendait cela vraiment facile à comprendre était regarder ici
Cela étant dit, j'ai défini trois variables:
échelle, zoomWidth et zoomHeight
scale correspond à l’échelle initiale que vous souhaitez utiliser pour le zoom, puis
zoomWidth et zoomHeight sont définis comme suit:
zoomWidth = (width-scale*width)/2
zoomHeight = (height-scale*height)/2
où width et height sont les largeur et hauteur de l'élément svg "vis"
la traduction ci-dessus est alors modifiée pour être:
.attr("transform", "translate("+zoomWidth+","+zoomHeight+") scale("+scale+")")
ainsi que la fonction zoom:
d3.behavior.zoom().translate([zoomWidth,zoomHeight]).scale(scale)
Cela garantit effectivement que votre élément est zoomé et centré lorsque votre visualisation est chargée.
Faites-moi savoir si cela vous aide! À votre santé.
S'applique à d3.js v4
Ceci est similaire à la réponse de davcs86 , mais elle réutilise une transformation initiale et implémente la fonction de zoom.
// Initial transform to apply
var transform = d3.zoomIdentity.translate(200, 0).scale(1);
var zoom = d3.zoom().on("zoom", handleZoom);
var svg = d3.select("body")
.append('svg')
.attr('width', 800)
.attr('height', 300)
.style("background", "red")
.call(zoom) // Adds zoom functionality
.call(zoom.transform, transform); // Calls/inits handleZoom
var zoomable = svg
.append("g")
.attr("class", "zoomable")
.attr("transform", transform); // Applies initial transform
var circles = zoomable.append('circle')
.attr("id", "circles")
.attr("cx", 100)
.attr("cy", 100)
.attr('r', 20);
function handleZoom(){
if (zoomable) {
zoomable.attr("transform", d3.event.transform);
}
};
Le voir en action: lien jsbin
J'utilisais d3 avec Rea et j'étais très frustré par le zoom initial qui ne fonctionnait pas.
J'ai essayé les solutions ici et aucune d'entre elles n'a fonctionné. Ce qui a bien fonctionné a été d'utiliser un facteur d'échelle initial et les positions, puis de mettre à jour la fonction de zoom en fonction de ces facteurs
const initialScale = 3;
const initialTranslate = [
width * (1 - initialScale) / 2,
height * (1 - initialScale) / 2,
];
const container = svg
.append('g')
.attr(
'transform',
`translate(${initialTranslate[0]}, ${initialTranslate[1]})scale(${initialScale})`
);
La fonction de zoom ressemblerait à quelque chose comme ça
svg.call(
zoom().on('zoom', () => {
const transformation = getEvent().transform;
let {x, y, k} = transformation;
x += initialTranslate[0];
y += initialTranslate[1];
k *= initialScale;
container.attr('transform', `translate(${x}, ${y})scale(${k})`);
})
);
Si vous avez remarqué la fonction getEvent()
, c'est que l'importation des événements à partir de d3-selection
ne fonctionnait pas dans mon cas. Donc je devais faire
const getEvent = () => require('d3-selection').event;