2016-07-21 22 views
4

Example Code FiddleD3 Skalierung Ausgabe von Graph mit entsprechender Skalierung von Skalen (Y-Achse, X-Achse)

ich auf einer Heatmap arbeite. In dem ich die Rechtecke der Heatmap (Breite, Höhe) programmatisch abhängig von Daten mache.

Ich möchte Schieberegler für das Zoomen auf X-Achse (Zeitbereich), Y-Achse (Entfernungsbereich) hinzufügen. Ich versuchte d3 Skalierungsoptionen, die gut funktioniert. Aber die Skalen (X-Achse, Y-Achse) skalieren nicht im Verhältnis zu den Rechtecken des Graphen. Wie wenn ein Rechteck zwischen 10,20 Meilen y-Achsenskala wäre. es geht weiter als 20 Meilen auf Skalierung.

Dann versuchte ich Viewbox auf Svg. Es klappt . Skalen werden genau proportional zur Grafik gehalten.

Ich möchte den Anteil der Skalen und Graphen auf Skalierung beibehalten, aber nicht die Größe der Skalenbeschriftungen erhöhen, da dies die Grafik hässlich macht.

Hier ist Code-Schnipsel, wie ich meine Graph mache zunächst

d3.json('dateWiseNewDataRight.json',function(err,right_dat){ 
      // console.log(right_dat); 
      var dateGroups=_.groupBy(right_dat, "DATE"); 
      var data = []; 
      var x= 0,y=0; 
      var tlength=0; 
      var totalDates=Object.keys(dateGroups); 
      var graphWidth=(total_width/totalDates.length)-6; 

      for(var key in dateGroups){ 
       tlength=0; 
       data = []; 
       y=0; 
       var segmentMiles=0; 
       var currentGraphData=dateGroups[key]; 
       var road=currentGraphData[0]['ROAD']; 
       for(var i = 0; i < currentGraphData.length-1; i++) { 
        tlength+=currentGraphData[i].MILES; 
       } 
       for (var i = 0; i < currentGraphData.length-1; i++) { 
        var height=0; 
        segmentMiles=segmentMiles+currentGraphData[i].MILES; 
        for(var j in times){ 
         if(road!=currentGraphData[i]['ROAD']){ 
          road=currentGraphData[i]['ROAD']; 
          height=1; 
          for(var k=0;k<times.length;k++){ 
           data.push({value:20000,x:x,y:y, height:height ,width:col_width,name:"",tmc:"", length:"",road:""}); 
           x=x+col_width; 
          } 
          break; 
         } 
         else{ 

          col_width=graphWidth/24; 
          var Congestion= currentGraphData[i][times[j]]; 
          height=(currentGraphData[i].MILES/tlength)*total_height; 
          //road=leftDat[i]['ROAD']; 
          data.push({value:Congestion,x:x,y:y, height:height ,width:col_width,name:currentGraphData[i]['NAME'],tmc:currentGraphData[i]['TMC CODE'], length:currentGraphData[i]['MILES'],road:currentGraphData[i]['ROAD'],miles:segmentMiles}); 
          // x=x+col_width; 
         } 
         x=x+col_width; 
        } 
        y=y+height; 
        x=0; 
       } 

       plotSegmentNames(panelData); 

       var margin = { top: 50, right: 0, bottom: 10, left: 10 }; 

       $('.heat-map-2').append('<div class="chart-right-'+key+' " style="width: '+graphWidth+'px;float:left;margin:3px;;overflow:hidden"></div>'); 
       var graphDiv='.chart-right-'+key; 
       var right_Svg = d3.select(graphDiv) 
         .append("svg") 
         .attr("class", "chart") 
         .attr("width",graphWidth) 
         .attr("height", total_height) 
         .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
       var right_color_chart = right_Svg.append("g") 
         .attr("class", "rightHeatMap"); 
       right_color_chart.call(tip); 

       var color = d3.scale.linear() 
         .domain([d3.min(data), 1]) 
         .range(["blue", "green"]); 
       right_color_chart.selectAll("rect") 
         .data(data) 
         .enter() 
         .append("rect") 
         .attr("x", function(d,i) {return d.x; }) 
         .attr("y", function(d,i) { return d.y; }) 
         .attr("width", col_width) 
         .attr("height", function(d) { return d.height; }) 
         .attr("road",function(d){ 
          return d.road; 
         }) 
         .attr("miles", function(d) { return d.miles; }) 
         .style("fill", function(d) {return chooseColor(d.value);}) 
         .on('mouseover', tip.show) 
         .on('mouseout', tip.hide); 
       var right_xAxisScale = d3.time.scale(), 
         right_xAxis = d3.svg.axis() 
           .orient('bottom') 
           .ticks(d3.time.hour,1) 
           .tickFormat(d3.time.format('%I %p')) 
           .tickSubdivide(6); 

       right_xAxis.scale(right_xAxisScale.range([0,graphWidth]).domain([timeFormat.parse(times[0]),timeFormat.parse(times[times.length-1])])); 
       right_Svg.append('g') 
         .attr('class','x axis') 
         .call(right_xAxis) 
         .append('text') 
         .attr('transform','translate('+total_width+',0)'); 

       var yAxisScale = d3.scale.linear() 
           .range([0,xAxisHeight]) 
           .domain([0,tlength]), 
         yAxis = d3.svg.axis() 
           .orient('right') 
           .ticks(5) 
           .scale(yAxisScale); 
       right_Svg.append('g') 
         .attr('transform','translate('+1+','+0+')') 
         .attr('class','y axis') 
         .call(yAxis) 
//      .append('text') 
//      .text('Length') 
//      .attr('transform','translate(100,'+total_height+') rotate(-90)'); 
      } 



      var testTimes =times; 
      var distanceRange=[0,60]; 
      $("#scale-slider") 
        .slider({ 

         animate:true, 
         range: true, 
         min: 0, 
         max: 1440, 
         step: 24, 
         values: [0, 1440], 
         slide: function (e, ui) { 
          var sliderTime= calculateSiderTime(e,ui); 
          testTimes=[sliderTime.nob1Time,sliderTime.nob2Time]; 
          $('.x.axis').remove(); 
          $('.y.axis').remove(); 
          /* redrawHeatMaps('left',left_color_chart,'leftHeatMap',leftDat,testTimes,tlength); 
          redrawHeatMaps('right',right_color_chart,'rightHeatMap',right_dat,testTimes,tlength);*/ 

          redrawYHeatMaps('left',left_color_chart,'leftHeatMap',leftDat,testTimes,tlength,distanceRange); 
          redrawYHeatMaps('right',right_color_chart,'rightHeatMap',right_dat,testTimes,tlength,distanceRange); 

         } 
        }) 
        .on("slidechange", function(e, ui) { 


        }); 

      $("#distance-slider") 
        .slider({ 

         animate:true, 
         range: true, 
         min: 0, 
         max: 60, 
         step: 5, 
         values: [0, 60], 
         slide: function (e, ui) { 
          distanceRange=ui.values; 
          $('.x.axis').remove(); 
          $('.y.axis').remove(); 
         // left_color_chart.attr("transform", "translate("+ d3.event.translate + ")scale(" + d3.event.scale + ")"); 
          redrawYHeatMaps('left',left_color_chart,'leftHeatMap',leftDat,testTimes,tlength,distanceRange); 
          redrawYHeatMaps('right',right_color_chart,'rightHeatMap',right_dat,testTimes,tlength,distanceRange); 
          $('.slider-distance1').html(ui.values[0]); 
          $('.slider-distance2').html(ui.values[1]); 
         } 
        }) 
        .on("slidechange", function(e, ui) { 


        }); 
     }); 
+2

Fügen Sie bitte ein Arbeitsbeispiel hinzu, wenn möglich. –

+0

@FrancisHemsher [fiddle] (https://jsfiddle.net/tahir_pucit_7/we7mmvk5/12/) ist jetzt hier – Achilles

+0

@Achilles Wenn ich genau verstanden habe, ist dein Problem y-Achse und Heatmap-rects nicht gleich skalieren und du willst Y-Achse entsprechend den Heatmap-Rezepten gleich skalieren? –

Antwort

1

gerade nur yAxisScale ‚s Domäne bearbeiten, wenn Skala Ereignis aufgetreten ist.

Here is updated fiddle.

Zuerst y Verfahren in zoom entfernen. Es hilft bei der automatischen Skalierung für eine Achse, aber das ist nicht Ihr Fall. Ich werde endlich eine Erklärung geben.

zoom = d3.behavior.zoom() 
    .scaleExtent([0, 5]) 
    .scale(1) 
    .on("zoom", zoomed); 

Nach anpassen yAxisScale Domäne, wenn Skalenwert geändert wird.

function zoomed() { 
    yAxisScale.domain([0, tlength/d3.event.scale]); // added 
    leftSvg.select(".y.axis").call(yAxis); 
    zoomIn(); 
} 

Warum Division nicht Multiplikation verwenden? Denn wenn Sie zweimal skalieren, werden die Achsenwerte nur um die Hälfte größer als die ursprünglichen Werte.

Wenn Sie 's y Methode verwenden, wird es automatisch skalieren yAxisScale mit Multiplikation. Also, ich sagte, es ist nicht dein Fall oben.

+0

Danke, es funktioniert perfekt. Können Sie erklären, wie Sie auf die Idee kommen, dass wir bei der Skalierung tlength mit d3.event.scale teilen müssen. um geeignete yScale – Achilles

+0

zu erhalten, wenn ich Skalenwert manuell einstellen möchte. Wie bei einem Schieberegler möchte ich nur Daten zwischen 20 und 40 auf der Y-Achse anzeigen. Kann ich das machen? – Achilles

+0

Nehmen wir an, dass der Entfernungsbereich zwischen 0 und 40 liegt. Wenn Sie die Heatmap-Werte zweimal skalieren, wird 'd3.event.scale'' 2.0' und der Bereich muss um die Hälfte (0 - 20) vergrößert werden. –

2

Ich nehme an, Sie können über Mausrad zoomen möchten, in die Heatmap-Zellen mit der Achse nicht skaliert werden. Hier sind ein paar Vorschläge. Probieren Sie es aus.

1) Veränderung Zoomverhalten:

   zoom = d3.behavior.zoom().scaleExtent([0,5]).scale(1).on("zoom", zoomIn); 

2) Entfernen Sie die gezoomt Funktion und ändern Sie die zoomIn:

function zoomIn(){ 
var t = d3.event.translate, 
s = d3.event.scale; 
left_color_chart.attr("transform","translate("+t+")scale("+s+")") 
} 
+0

Es tut tatsächlich das gleiche Verhalten, was mein Code tut. Der Graph skaliert, aber die Achse ändert sich nicht entsprechend dem Skalierungsverhältnis. Insbesondere möchte ich nur die Skalierung von Y-Achse. – Achilles

+1

Jemand hat gerade eine Geige geschrieben, die helfen könnte: https://jsfiddle.net/sjp700/u6rj20jc/1/ (Dies kam von: http: // stackoverflow.com/questions/38544216/d3-version-4-zoom-verhalten-auf-g-element) –