2015-07-03 26 views
5

byłem krach głowę nad tym problemem od pewnego czasu ...Niezwykłe d3 zoom w klasie wielokrotnego użytku - to i wiążą

Mam zwykły konstruktor/prototyp obiektu (jak klasa) w JS, który przechowuje wszystkie mój wykres d3 logika:

figureGen = function(html_element) { 
    this.svg = d3.select(html_element) 
    .append('svg') 
    .style('width', '100%') 
    .style('height', '100%') 
    .append('g') 
     .attr("class", "sadrzalac") 
     .attr("transform", "translate(" + 0 + "," + 0 + ")"); 
     this.element = element; 
     this.data = []; 
     this.yRange = d3.scale.linear(); 
     this.xRange = d3.scale.linear(); 
     this.xAxis = undefined; 
     this.yAxis = undefined; 
     this.width = undefined; 
     this.height = undefined; 
     this.zoom = undefined; 
     this.margin = {top: 20, right: 20, bottom: 20, left: 35}; 
     this.svg.append("rect") 
     .attr("class", "clipPath") 
     .attr("transform", "translate(" + this.margin.left + "," + -this.margin.top + ")"); 
     this.svg.append('g') 
     .attr("class","xaxis axis"); 
     this.svg.append('g') 
     .attr("class", "yaxis axis"); 
} 

dla konstruktora, a dla metody coś takiego

figureGen.prototype = { 
    constructor: figureGen, 
    init: function(sampledata, width, height){ 
     var y_min = Number(d3.min(this.podaci, function (d) { return d.y;})); 
     var y_max = Number(d3.max(this.podaci, function (d) { return d.y;})); 
     var x_min = Number(d3.min(this.podaci, function (d) { return d.x;})); 
     var x_max = Number(d3.max(this.podaci, function (d) { return d.x;})); 

     var ukupan_opseg = y_max - y_min; 
     var spacer = (ukupan_opseg*25)/100; 

     this.xRange = d3.scale.linear().range([this.margin.left + 10, this.width - this.margin.right]).domain([x_min, x_max]); 
     this.yRange = d3.scale.linear().range([this.height - this.margin.top, this.margin.bottom]).domain([y_min-spacer, y_max+spacer]); 

     this.zoom = d3.behavior.zoom() 
     .x(this.xRange) 
     .y(this.yRange) 
     .scaleExtent([1, 5]) 
     .center([this.width/2, this.height/2]) 
     .size([this.width, this.height]) 
     .on("zoom", this.zoomProcess()); 

     this.svg 
     .attr("width", this.sirina) 
     .attr("height", this.visina) 
     .call(this.zoom); 

     this.xAxis = d3.svg.axis() 
      .scale(this.xRange) 
      .innerTickSize(-this.height+40) 
      .outerTickSize(5) 
      .tickPadding(10) 
      .tickFormat(d3.format("d")); 

     this.yAxis = d3.svg.axis() 
      .scale(this.yRange) 
      .orient("left") 
      .innerTickSize(-this.width) 
      .outerTickSize(5) 
      .tickPadding(10) 
      .tickSubdivide(false); 

     this.svg.select('.xosa') 
      .attr("transform", "translate(0," + (this.height - this.margin.bottom) + ")") 
      .call(this.xAxis); 

     this.svg.select(".yosa") 
      .attr("transform", "translate(" + (this.margin.left) + ",0)") 
      .call(this.yAxis); 
    }, 
    zoomProcess: function{ 
     this.svg.select(".xaxis").call(this.xAxis); 
     this.svg.select(".yaxis").call(this.yAxis); 
     console.log(this.svg); 
    } 
} 

i problem jest w zoomProcess metoda, która zawsze zwraca (loguje) element HTML na obiekcie this.svg zamiast this.svg, który może .select. Funkcja powiększania jest poprawnie dołączona do mojego elementu, a na myszy, gdy zacznie się powiększanie, ale pojawi się komunikat o błędzie, że nie można wykonać tej operacji na tym.xAxis.

Co jeszcze dziwniejsze, kiedy wywołać zoomProcess z innego źródła, jak przycisk kliknij jego dziennika konsola wysyła przedmiotu właściwego this.svg a nie elementu HTML, więc wydaje się, że błąd pochodzi z obsługi zdarzeń zoom. Co jest nie tak?

Są to dwa przykłady Szukałem na stronie:
http://bl.ocks.org/stepheneb/1182434
http://bl.ocks.org/mbostock/7ec977c95910dd026812

EDIT: Teraz myślę, że chyba powinni stosować .bind() na tym obiekcie, tak aby jego odniesienie pozostaje takie samo podczas przechodzenia do metody zoomProcedura. Wciąż nie jestem pewien, jak to zrobić.

+0

Co to oznacza: "_ i problem jest w metodzie zoomProcess, która zawsze zwraca (loguje) element HTML na obiekcie this.svg zamiast this.svg, który może .select. Zachowanie zoomu jest poprawnie dołączone do mojego elementu, a na myszy, gdy zacznie się powiększanie, ale wyskakuje błąd mówiąc, że to .call na this.xAxis_ "możesz chcieć go edytować, żeby miało to sens." –

Odpowiedz

1

Zakładam jest literówka, że ​​nie jest w rzeczywistym kodzie ...

zoomProcess: function{ 
     this.svg.select(".xaxis").call(this.xAxis); 
     this.svg.select(".yaxis").call(this.yAxis); 
     console.log(this.svg); 
    } 

jest prawdopodobnie ...

zoomProcess: function(){ 
     this.svg.select(".xaxis").call(this.xAxis); 
     this.svg.select(".yaxis").call(this.yAxis); 
     console.log(this.svg); 
    } 

czy może ...

zoomProcess: function(){ 
     return function() { 
      this.svg.select(".xaxis").call(this.xAxis); 
      this.svg.select(".yaxis").call(this.yAxis); 
      console.log(this.svg); 
     } 
    } 

Nie mogę wiedzieć na pewno. i zakładam, że naprawdę powołując jak ...

.on("zoom", this.zoomProcess()); 

Nie ...

.on("zoom", this.zoomProcess); 

Ale tak czy owak, na podstawie tego założenia, aby to działało tak, jak chcesz, spróbuj ...

zoomProcess: function(){ 
     //'this' is figureGen.prototype 
     var that = this; 
     return function() { 
      //'this' is window 
      that.svg.select(".xaxis").call(that.xAxis); 
      that.svg.select(".yaxis").call(that.yAxis); 
      console.log(that.svg); 
     } 
    } 

lub ...

zoomProcess: function(){ 
     //'this' is figureGen.prototype 
     return function() { 
      //'this' is figureGen.prototype 
      this.svg.select(".xaxis").call(this.xAxis); 
      this.svg.select(".yaxis").call(this.yAxis); 
      console.log(this.svg); 
     }.bind(this) 
    } 
+0

dziękuję za dużo CoolBlue. z rozwiązań, które dostarczyłeś, dzięki za wszystkie kłopoty. –

Powiązane problemy