2016-09-11 3 views
4

저는 Angular 2 응용 프로그램에서 d3 차트를 그립니다. 이제는 다중 시리즈 선 차트가있어서 각 선의 세로 위치를 가리킬 때 각 선에 도구 설명을 추가하려고합니다.d3, 각도 2 : node.getBoundingClientRect가 함수가 아닙니다.

export class LineGraphDirective { 
    private host; 
    private svg; 
    private margin; 
    private width; 
    private height; 
    private xScale; // D3 scale in X 
    private yScale; // D3 scale in Y 
    private zScale; // D3 color scale 
    private xAxis; 
    private yAxis; 
    private line; 
    private htmlElement:HTMLElement; 
    private parseDate; 
    private ds; 

    constructor(private element:ElementRef) { 
    this.htmlElement = this.element.nativeElement; 
    this.host = d3.select(this.element.nativeElement); 
    this.parseDate = d3.timeParse('%Y-%m-%d'); 
    let data = []; 
    this.ngOnChanges(data); 
    } 

    /** 
    * Every time the @Input is updated, rebuild the chart 
    **/ 
    ngOnChanges(data):void { 
    this.setup(data); 
    this.initData(data); 
    this.buildSVG(); 
    this.scaleAxis(data); 
    this.populate(); 
    this.drawXAxis(); 
    this.drawYAxis(); 
    this.zoomEventHandler(); 
    this.addVerticalLineTooltip(); 
    } 

    private setup(data):void {} 

    private initData(data) {} 

    /** 
    * build SVG element using the configurations 
    **/ 
    private buildSVG():void {} 

    private scaleAxis(data) {} 

    /** 
    * Create x axis 
    **/ 
    private drawXAxis():void {} 

    /** 
    *create y axis 
    **/ 
    private drawYAxis():void {} 

    /** 
    * Populate the graphs 
    **/ 
    private populate():void {} 

    private addVerticalLineTooltip() { 
    // append a g for all the mouse over nonsense 
    let mouseG = this.svg.append("g") 
     .attr("class", "mouse-over-effects"); 

    // this is the vertical line 
    mouseG.append("path") 
     .attr("class", "mouse-line") 
     .style("stroke", "black") 
     .style("stroke-width", "1px") 
     .style("opacity", "0"); 

    // keep a reference to all our lines 
    let lines = d3.select('.line'); 

    // here's a g for each circle and text on the line 
    var mousePerLine = mouseG.selectAll('.mouse-per-line') 
     .data(this.ds) 
     .enter() 
     .append("g") 
     .attr("class", "mouse-per-line"); 

    // the circle 
    mousePerLine.append("circle") 
     .attr("r", 7) 
     .style("stroke", (d) => { 
     return this.zScale(d.name); 
     }) 
     .style("fill", "none") 
     .style("stroke-width", "1px") 
     .style("opacity", "0"); 

    // the text 
    mousePerLine.append("text") 
     .attr("transform", "translate(10,3)"); 

    // rect to capture mouse movements 
    mouseG.append('svg:rect') 
     .attr('width', this.width) 
     .attr('height', this.height) 
     .attr('fill', 'none') 
     .attr('pointer-events', 'all') 
     .on('mouseout',() => { // on mouse out hide line, circles and text 
     d3.select(".mouse-line") 
      .style("opacity", "0"); 
     d3.selectAll(".mouse-per-line circle") 
      .style("opacity", "0"); 
     d3.selectAll(".mouse-per-line text") 
      .style("opacity", "0"); 
     }) 
     .on('mouseover',() => { // on mouse in show line, circles and text 
     d3.select(".mouse-line") 
      .style("opacity", "1"); 
     d3.selectAll(".mouse-per-line circle") 
      .style("opacity", "1"); 
     d3.selectAll(".mouse-per-line text") 
      .style("opacity", "1"); 
     }) 
     .on('mousemove',() => { // mouse moving over canvas 
     let mouse = d3.mouse(this); // this is the line I am getting error 

     // move the vertical line 
     d3.select(".mouse-line") 
      .attr("d",() => { 
      let d = "M" + mouse[0] + "," + this.height; 
      d += " " + mouse[0] + "," + 0; 
      return d; 
      }); 

     // position the circle and text 
     d3.selectAll(".mouse-per-line") 
      .attr("transform", (d, i) => { 
      let beginning = 0, 
       end = d3.select(lines[i]).node().getTotalLength(), 
       target, 
       pos; 

      while (true) { 
       target = Math.floor((beginning + end)/2); 
       pos = d3.select(lines[i]).node().getPointAtLength(target); 
       if ((target === end || target === beginning) && pos.x !== mouse[0]) { 
       break; 
       } 
       if (pos.x > mouse[0])  end = target; 
       else if (pos.x < mouse[0]) beginning = target; 
       else break; //position found 
      } 

      // update the text with y value 
      d3.select(this).select('text') 
       .text(this.yScale.invert(pos.y).toFixed(2)); 

      // return position 
      return "translate(" + mouse[0] + "," + pos.y + ")"; 
      }); 
     }); 
    } 

    private zoomEventHandler() { 
    let zoom = d3.zoom() 
     .scaleExtent([1, 2]) 
     .translateExtent([[0, -100], this.width + 90, this.height + 100]).on("zoom",() => this.zoomed()); 
    this.svg.call(zoom); 
    } 

    private zoomed() { 

    } 
} 

브라우저 콘솔에 다음과 같은 오류 메시지가 표시됩니다.

node.getBoundingClientRect is not a function 

Line: let mouse = d3.mouse(this); 

의견이 있으십니까?

감사합니다.

let mouse = d3.mouse(mouseG); 

나처럼 쓸 수 있습니다 :

+0

귀하의 문제는이 [답변] (https://stackoverflow.com/a/48231153/2414015)과 유사합니다. – jredd

답변

6

나는 당신이 그것을 사용해야 추측

let mouse = d3.mouse(d3.event.currentTarget); 
+0

두 번째 옵션이 작동합니다. 하지만 이제는 ** end = d3.select (lines [i]). node(). getTotalLength() **에서 또 다른 오류가 발생합니다 ** ** 'getTotalLength'속성을 읽을 수 없습니다 **. 새 질문을 게시하거나 업데이트해야합니까? – Rose18

+0

난 당신이 그것을 재현하는 최소한의 plunker을 만들 필요가 있다고 생각합니다 – yurzui

+0

** line = d3.select ('. line') 대신 ** line = document.getElementsByClassName ('line'); ; **. 이제 각 줄마다 원이있는 세로선이 표시되지만 툴팁은 표시되지 않습니다. 별도의 질문을 게시했습니다 .http : //stackoverflow.com/questions/39438578/d3-tooltips-on-multi-series-line-chart-at-each-line-when-mouse-hover-event – Rose18

0

d3.mouse() DOM 노드에서 호출해야합니다. "this"가 사용자 정의 클래스의 인스턴스이기 때문에 d3.mouse (this)가 작동하지 않습니다. 귀하의 경우에는 사용할 수 있습니다

let mouse = d3.mouse(mouseG.node()); 

다시 말하지만, mouseG는 DOM 노드가 아닌 d3 선택 객체이기 때문에 node()를 호출해야합니다. node()는 기본 "g"노드를 반환합니다.

관련 문제