2017-08-23 4 views
0

J'ai un graphique chronologique contenant des points de données indiquant des événements spécifiques. J'ai essayé de construire une fonction de zoom dans le graphique, mais j'ai atteint une impasse. Je peux zoomer sur l'axe, mais je ne peux pas repositionner les datapoins dans la nouvelle échelle. J'ai traversé beaucoup de d3 bl.ocks mais n'ai pas trouvé de solution.Comment faire en sorte que les éléments d'une ligne de temps suivent un zoom à l'aide de D3.js v4

J'ai une version minimale en jsFiddle ici: https://jsfiddle.net/q73ggw3e/2/

pièces principales sont:

le zoom:

var zoom = d3.zoom() 
    .scaleExtent([1, Infinity]) 
    .translateExtent([[0, 0], [width, height]]) 
    .extent([[0, 0], [width, height]]) 
    .on("zoom", zoomed); 

Les points de données:

svg.append("g") 
    .selectAll("logo") 
    .attr("class", "logo") 
    .data(data) 
    .enter() 
    .append("circle") 
    .attr("cy", 40) 
    .attr("cx", function(d) { return x(d);}) 
    .attr("r", 10) 
    .style("fill", "#000000") 

La zone de zoom :

svg.append("rect") 
    .attr("class", "zoom") 
    .attr("width", width) 
    .attr("height", height) 
    .call(zoom); 

Et la fonction zoomée:

function zoomed() { 
    svg.select(".axis--x") 
     .call(xAxis.scale(d3.event.transform.rescaleX(x))); 
    var new_x = d3.event.transform.rescaleX(x); 
     svg.selectAll(".logo") 
      .attr("cx", function(d) { return new_x(d);}); 
    }; 

Je est obligatoire la (.logo) classe de cercles à l'événement zoom aussi, mais pour une raison que l'axe effectue un zoom ...

Où est-ce que je vais mal? Ou y a-t-il un autre moyen de le faire ...

Si cela est important, les points de données auront également des fonctions de glisser-déposer, de survol et de clic. Cela fonctionne bien pour le moment, mais le zoom rect bloque les événements de pointeur. Mais ce doit être trié après le zoom fonctionne ...

+0

Comme Frog a souligné qu'il était un problème d'ajouter les bonnes choses au comportement de zoom. Fonctionne bien maintenant. –

Répondre

-1

tableau bizarre que vous faites

  var margin = { 
 
       top: 30, 
 
       right: 20, 
 
       bottom: 30, 
 
       left: 120 
 
       }, 
 
       width = 800 - margin.left - margin.right, 
 
       height = 210 - margin.top - margin.bottom; 
 

 

 
      var svg = d3.select(".zoom") 
 
       .append("svg") 
 
       .attr("width", width + margin.left + margin.right) 
 
       .attr("height", height + margin.top + margin.bottom) 
 
       .append("g") 
 
       .attr("transform", 
 
       "translate(" + margin.left + "," + margin.top + ")"); 
 

 
      var y = d3.scaleLinear() 
 
       .rangeRound([height, 0]); 
 

 
      var x = d3.scaleTime() 
 
       .rangeRound([0, width]); 
 

 
      var xAxis = d3.axisTop(x) 
 

 
      var zoom = d3.zoom() 
 
       .scaleExtent([1, Infinity]) 
 
       .translateExtent([[0, 0], [width, height]]) 
 
       .extent([[0, 0], [width, height]]) 
 
       .on("zoom", zoomed); 
 

 
      var parseTime = d3.timeParse("%Y-%m-%d"); 
 

 
      var lanes = ["A", "B", "C"] 
 
      var lanesLength = lanes.length 
 

 
      var a = ["2010-02-12", "2013-08-15", "2015-01-23", "2017-01-22"] 
 
      var data = []; 
 
      a.forEach(function (d){ 
 
       data.push(parseTime(d)); 
 
      }); 
 

 
      var today = new Date(); 
 
      x.domain([d3.min(data, function(d) { return d;}), today]); 
 
      y.domain([0, lanesLength]); 
 

 
      svg.append("g") 
 
       .attr("class", "axis axis--x") 
 
       .style("stroke-width", 2) 
 
       .attr("transform", "translate(0)") 
 
       .call(xAxis); 
 

 

 
      svg.append("g") 
 
       .selectAll(".lanetext") 
 
       .data(lanes) 
 
       .enter() 
 
       .append("text") 
 
       .text(function(d) { return d;}) 
 
       .attr("x", -margin.right) 
 
       .attr("y", function(d, i) { return y(i + .5);}) 
 
       .attr("dy", ".5ex") 
 
       .attr("text-anchor", "end") 
 
       .attr("class", "lanetext") 
 

 
      svg.append("g") 
 
       
 
       .attr("class", "logomu") 
 
       .selectAll("logomu") 
 
       .data(data) 
 
       .enter() 
 
       .append("circle") 
 
       .attr("cy", 40) 
 
       .attr("class", "logo") 
 
       .attr("cx", function(d) { return x(d);}) 
 
      .attr("r", 10) 
 
      .style("fill", "#000000") 
 

 
      svg.append("rect") 
 
       .attr("class", "zoom") 
 
       .attr("width", width) 
 
       .attr("height", height) 
 
       .call(zoom); 
 

 
      function zoomed() { 
 
       svg.select(".axis--x") 
 
        .call(xAxis.scale(d3.event.transform.rescaleX(x))); 
 
       var new_x = d3.event.transform.rescaleX(x); 
 
       svg.selectAll(".logo") 
 
        .attr("cx", function(d) { return new_x(d);}); 
 
      };
 .axis line{ 
 
      stroke: #000 
 
     } 
 
     .axis path{ 
 
      stroke: #000 
 
     } 
 
     .axis text{ 
 
      fill: #000 
 
     } 
 
     .lanetext { 
 
      fill: #000 
 
     } 
 
     .zoom { 
 
      cursor: move; 
 
      fill: none; 
 
      pointer-events: all; 
 
      } 
 
     .logo { 
 
      fill: #000; 
 
     }
<script src="https://code.jquery.com/jquery-3.1.0.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script> 
 

 
<body> 
 

 
<div class="zoom"> 
 
</div> 
 
</body>

je la classe est obligatoire (.logo) des cercles l'événement de zoom aussi, mais pour une raison que l'axe effectue un zoom ...

s'il y a une cla ss nom du logo? inspec le html assurez-vous de l'ajouter à droite

Où vais-je me tromper? Ou est-il un complètement autre façon de faire cette ...

vous na pas vérifier ce que vous dessinez. Yup juste besoin d'expérience