web-dev-qa-db-fra.com

D3.js Définir le niveau de zoom initial

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');
27
Jakub Svec

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)");  
29
Pudders

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)");
24
davcs86

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é.

14
deweyredman

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

3
hexnod

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;
0
Prasanna