2017-12-28 10 views
0

도넛 형 차트에 D3 범례를 추가하려고하는데 여기 예제를 따르십시오 : http://bl.ocks.org/ZJONSSON/3918369. 도넛 형 차트가 잘 렌더링됩니다.`d3.legend`를 사용한 오류 : 캐치되지 않음 TypeError : node.getAttribute가 함수가 아닙니다.

그러나, 나는 아래의 오류로 실행하고 다음 d3.legend() 함수 내부

, 나는이 오류를 얻고있다 'catch되지 않은 형식 오류 : node.getAttribute는 함수가 아닙니다'이것 'catch되지 않은 형식 오류. querySelectorAll은 함수가 아닙니다. '

나는 왜 ... 모든 생각을 잘 모르겠다?

// Alerts.js 
renderBody() { 
    const {list, currentProgram} = this.props 
    const width = 260; 
    const height = 260; 
    const radius = width/2; // 130 

    // arc & label generator 
    let arc = d3.arc() 
     .outerRadius(radius - 10) 
     .innerRadius(90) 
     .padAngle(0.02); 

    let labelArc = d3.arc() 
     .outerRadius(radius + 60) 
     .innerRadius(radius - 90); 

    // pie generator 
    let pie = d3.pie() 
     .sort(null) 
     .value(d => { return d; }); 

    // define svg 
    let svg = d3.select('.enrolled-statistics-svg').append('svg') 
     .attr('width', width) 
     .attr('height', height) 
     .append('g') // group similar elements together 
     .attr('transform', 'translate(' + width/2 + ', ' + height/2 + ')'); 

    // append g elements (arc) 
    const g = svg.selectAll('.arc') 
     .data(pie(testData)) 
     .enter().append('g') 
     .attr('class', 'arc'); 

    // append the path of the arc 
    g.append('path') 
     .attr('d', arc) 
     .attr('data-legend', val => { 
     return val.data; 
     }) 
     .attr('data-legend-pos', (val) => { 
     return val.index; 
     }) 
     .style('fill', val => { 
     return COLOR_ARRAY[val.index]; 
     }); 

    // append with label 
    g.append('text') 
     .attr('transform', d => { 
     return 'translate(' + labelArc.centroid(d) + ')'; 
     }) 
     .attr('dy', '0.35em') 
     .text(val => { 
     return (val.data/testResp.data.enrolledStatistics.total) * 100 + '%'; 
     }); 

    // define d3.legend() 
    d3.legend = (g) => { 

     g.each(() => { 
     let g = d3.select(this); 
     console.log('------- g: ', g); 

     let items = {}; 
     let svg = d3.select(g.property('nearestViewportElement')); 
     let legendPadding = g.attr('data-style-padding') || 5; // ERROR: Uncaught TypeError: node.getAttribute is not a function 
     let legendBox = g.selectAll('.legend-box').data([true]); // ERROR: Uncaught TypeError: this.querySelectorAll is not a function 
     let legendItems = g.selectAll('.legend-items').data([true]); 

     legendBox.enter().append('rect').classed('legend-box', true); 
     legendItems.enter().append('g').classed('legend-items', true); 

     svg.selectAll('[data-legend]').each(() => { 
      let self = d3.select(this) 
      items[self.attr('data-legend')] = { 
      pos: self.attr("data-legend-pos") || this.getBBox().y, 
      color: self.attr("data-legend-color") != undefined ? self.attr("data-legend-color") 
       : self.style("fill") != 'none' ? self.style("fill") : self.style("stroke") 
      } 
     }); 

     items = d3.entries(items).sort(function (a, b) { 
      return a.value.pos - b.value.pos 
     }); 

     console.log('------- items: ', items); 

     legendBox.selectAll('text') 
      .data(items, val => val.key) 
      .call(val => { 
      val.enter().append('text') 
      }) 
      .call(val => { 
      val.exit().remove() 
      }) 
      .attr('y', (val, i) => { 
      return `${i}em` 
      }) 
      .attr('x', '1em') 
      .text(val => val.key); 

     legendItems.selectAll("circle") 
      .data(items, function (d) { 
      return d.key 
      }) 
      .call(val => val.enter().append("circle")) 
      .call(val => val.exit().remove()) 
      .attr('cy', (val, i) => `${i - 0.25}em`) 
      .attr('cx', 0) 
      .attr('r', '0.4em') 
      .style('fill', val => { 
      console.log(val.value.color); 
      return val.value.color 
      }); 

     // Reposition and resize the box 
     let lbbox = li[0][0].getBBox(); 

     lbbox.attr("x", (lbbox.x - legendPadding)) 
      .attr("y", (lbbox.y - legendPadding)) 
      .attr("height", (lbbox.height + 2 * legendPadding)) 
      .attr("width", (lbbox.width + 2 * legendPadding)); 
     }); 

     return g; 
    } 

    // define legend svg 
    let padding = 20; 
    let legx = radius + padding; 
    let legendSVG = d3.select('.enrolled-statistics').append('svg') 
     .attr('width', 150) 
     .attr('height', 150) 
     .append('g') 
     .attr('class', 'legend') 
     .attr('transform', 'translate(' + legx + ', 0)') 
     .style('font-size', '12px') 
     .style('fill', 'blue') 
     .call(d3.legend); 

    return(....) 
    } 

답변

2

each 콜백을 정의하는 화살표 함수를 사용하고 있습니다. 이로 인해 this 키워드의 범위가 변경됩니다. here). 따라서 기본적으로 d3.select(this)은 기대하는 바를 선택하지 않습니다. 또한, 두 가지 다른 방법으로 변수로 g을 사용하고 있는데, 예기치 않은 동작이 발생할 수 있습니다 (어쨌든 혼동을 피하기 위해 별개의 이름을 가진 변수를 작성하는 것이 좋습니다).

관련 문제