D3.js Set niveau de zoom initial

j'ai plusieurs graphiques configurés pour zoomer sur le conteneur et cela fonctionne très bien. Cependant, sur la charge initiale, le niveau de zoom est trop étroite. Existe-t-il une méthode pour régler le niveau de zoom initial afin d'éviter d'avoir à effectuer un zoom avant? Je connais bien la méthode .scale() , mais je n'ai pas eu de chance de la mettre en œuvre. Est-ce le chemin à suivre ou y a-t-il quelque chose que je manque?

voici ce que j'ai jusqu'à présent en ce qui concerne 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');
21
demandé sur davcs86 2013-04-24 00:15:56

5 réponses

j'ai finalement obtenu que cela fonctionne en mettant à la fois la transformation initiale et le comportement de 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)");  
25
répondu Pudders 2017-06-21 07:21:33

D3v4 réponse

si vous êtes ici à la recherche de la même, 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)");
16
répondu davcs86 2017-04-20 17:45:10

ajouter cette réponse comme addenda à la réponse acceptée au cas où quelqu'un aurait encore des problèmes:

la chose qui a rendu cela vraiment facile à comprendre était de chercher ici

cela dit, j'ai mis trois variables:

échelle, zoomWidth et zoomHeight

est l'échelle initiale que vous voulez que le zoom soit, puis

zoomWidth et zoomHeight sont définis comme suit:

zoomWidth = (width-scale*width)/2
zoomHeight = (height-scale*height)/2

où largeur et hauteur sont la largeur et la hauteur de l'élément" vis " svg

la traduction ci-dessus est modifié pour être:

.attr("transform", "translate("+zoomWidth+","+zoomHeight+") scale("+scale+")")

ainsi que la fonction zoom:

d3.behavior.zoom().translate([zoomWidth,zoomHeight]).scale(scale)

cela permet de s'assurer que votre élément est zoomé et centré lorsque votre visualisation est chargée.

dites-moi si cela vous aide! Acclamation.

13
répondu deweyredman 2017-01-04 18:56:19

S'applique à d3.js v4

c'est similaire à réponse de davcs86 , mais il réutilise une transformation initiale et implémente la fonction 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);
  }
};

Voir en action: jsbin lien

2
répondu hexnod 2017-09-26 23:29:32

j'utilisais d3 avec react et j'étais très frustré que le zoom initial ne fonctionne pas.

j'ai essayé les solutions ici et aucune d'entre elles n'a fonctionné, ce qui a plutôt fonctionné était l'utilisation d'un facteur d'échelle initiale et les positions, puis la mise à jour de la fonction de zoom sur la base de ces facteurs d'échelle et les positions

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é le getEvent() en fonction, c'était parce que importer l'événement de d3-selection ne fonctionnait pas dans mon cas. Donc j'ai dû faire

const getEvent = () => require('d3-selection').event;
0
répondu Prasanna 2018-04-12 09:55:29