2014-10-24 2 views
3

this D3js 꺾은 선형 차트 예제를 다중 선형 차트에 적용하려고합니다.D3js mulitline chart mouseOver

mousemove 함수의 d3.mouse(this)[0]은 " 'null'속성 'sourceEvent'을 읽을 수 없습니다."라는 오류가 발생합니다.

1 null sourceEvent 오류가 발생하는 이유는 무엇입니까?

2 단일 선 차트에서 다중 (n) 선 차트로 예제를 수정하는 방법에 대한 팁은 무엇입니까?

문제를 설명하기 위해 여기에 jsfiddle이 있습니다. 당신이 바로 mousemove 함수를 호출하고 "mousemove" 이벤트에 listener function 등의 반환 값을 전달합니다

.on("mousemove", mousemove()); 

쓰기 (그리고 solution)

var myApp = angular.module('app', []); 
myApp.directive("lineChart", function() { 
    return { 
    restrict: 'E', 
    scope: { 
     data: '=', 
     id: '@' 
    }, 
    link: function (scope, element, attrs) { 
     scope.$watch('data', function (data) { 
     d3.select("#"+attrs.id).select("svg").remove(); 
     if (data) { 
      var margin = {top: 20, right: 20, bottom: 30, left: 40}, 
       width = element[ 0 ].parentElement.offsetWidth - margin.left - margin.right, 
       height = element[ 0 ].parentElement.offsetHeight - margin.top - margin.bottom; 
      var parseDate = d3.time.format("%d-%b-%y").parse; 
      var x = d3.time.scale() 
       .range([0, width]); 
      var y = d3.scale.linear() 
       .range([height, 0]); 
      var xAxis = d3.svg.axis() 
       .scale(x) 
       .orient("bottom") 
       .innerTickSize(-height) 
       .ticks(4) 
       .outerTickSize(0) 
       .tickPadding(5) 
       .tickFormat(function(d) { return d3.time.format('%d/%m %H:%M')(new Date(d)); }); 
      var yAxis = d3.svg.axis() 
       .scale(y) 
       .orient("left") 
       .innerTickSize(-width) 
       .outerTickSize(0) 
       .tickPadding(10); 
      var line = d3.svg.line() 
       .x(function(d) { return x(d[0]); }) 
       .y(function(d) { return y(d[1]); }); 
      var svg = d3.select(element[0]).append("svg") 
       .attr("width", '100%') 
       .attr("height", '100%') 
       .attr('viewBox','0 0 '+ element[ 0 ].parentElement.offsetWidth +' '+ element[ 0 ].parentElement.offsetHeight) 
      .append("g") 
       .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
      var minX = d3.min(data, function (item) { return d3.min(item.values, function (d) { return d[0]; }) }); 
      var maxX = d3.max(data, function (item) { return d3.max(item.values, function (d) { return d[0]; }) }); 
      var minY = d3.min(data, function (item) { return d3.min(item.values, function (d) { return d[1]; }) }); 
      var maxY = d3.max(data, function (item) { return d3.max(item.values, function (d) { return d[1]; }) }); 
      x.domain([minX, maxX]); 
      y.domain([0, maxY]); 
      svg.append("g") 
       .attr("class", "x axis") 
       .attr("transform", "translate(0," + height + ")") 
       .call(xAxis); 
      svg.append("g") 
       .attr("class", "y axis") 
       .call(yAxis); 
      var domaine = svg.selectAll(".domaine") 
       .data(data) 
       .enter().append("g") 
       .attr("class", "domaine"); 
      domaine.append("path") 
       .attr("class", "line") 
       .attr("d", function (d) { 
        return line(d.values); 
       }) 
       .style("stroke", function (d) { 
       return d.color; 
       }); 
      var focus = svg.append("g") 
       .attr("class", "focus") 
       .style("display", "none"); 
      focus.append("circle") 
       .attr("r", 4.5); 
      focus.append("text") 
       .attr("x", 9) 
       .attr("dy", ".35em"); 
      svg.append("rect") 
       .attr("class", "overlay") 
       .attr("width", width) 
       .attr("height", height) 
       .on("mouseover", function() { focus.style("display", null); }) 
       .on("mouseout", function() { focus.style("display", "none"); }) 
       .on("mousemove", mousemove()); 
      function mousemove() {    
      var x0 = x.invert(d3.mouse(this)[0]), 
       i = bisectDate(data, x0, 1), 
       d0 = data[i - 1], 
       d1 = data[i];/* 
       To adapt for multi line 
       , 
       d = x0 - d0.date > d1.date - x0 ? d1 : d0; 
      focus.attr("transform", "translate(" + x(d.date) + "," + y(d.close) + ")"); 
      focus.select("text").text(formatCurrency(d.close));*/ 
      } 
     } 
     }); 
    } 
    }; 
}); 
function MainCtrl($scope) { 
$scope.lineData = [{"key": "users","color": "#16a085", 
"values": [[1413814800000,4034.418],[1413815400000,5604.155000000001]]}, 
{"key": "users 2","color": "#d95600", 
"values": [[1413814800000,3168.183],[1413815400000,1530.8435]]}]; 
} 

답변

4

. this을 올바르게 설정하지 않았기 때문에 d3.mouse(this)null을 반환합니다.

수정은 매우 간단합니다 : 그냥 참고로 당신의 mousemove 기능에 전달하고 호출하지 않습니다 그러나

.on("mousemove", mousemove); 

을 경우에도이 수정 후 여전히 fiddle 당신의 bisectDate 기능 때문에에 오류가 발생합니다 누락되었습니다 ...

+0

여기를 지적 해 주셔서 감사합니다. [fiddle] (http://jsfiddle.net/takuan/gakdeL1u/7/)의 업데이트 된 버전입니다. 코드를보다 명확하게 만들려면 어떤 권장 사항이나 모범 사례가 있습니까? – Pierre

+0

D3에 대해 너무 많은 경험이 없으므로 코드를 주석으로 추가 할 수 없습니다. 그러나 angularjs 관점에서 볼 때 이것은 차트 생성 논리를 재사용 가능한 지시문에 숨기는 가장 좋은 사용 사례입니다. – nemesv