2016-12-20 8 views
1

これをコピーしようとしていますtutorial。最終的な目標は、マウスのx位置に続いて線上にとどまる線を持つ折れ線グラフを作成し、その線上のその位置に関する関連データをツールチップに表示することです。以下は、私が持っているコードですが、私はスタイルにいくつかの小さな変更と線の下の満たされた領域の追加を行っているが、私はそれは、これがどのように動作するかの違いを作る必要があるとは思わない:円ツールチップを使用した折れ線グラフの作成に問題があります

var margin = { 
      top: 20, 
      left: 50, 
      right: 50, 
      bottom: 50 
     }, 
     width = $element.innerWidth() - margin.left - margin.right, 
     height = 0.2 * width; 

     var parseTime = d3.timeParse('%m/%d/%Y'); 
     data.forEach(function(d) { 
      d.date = parseTime(d.date); 
      d.price = +d.price; 
     }); 

     var bisectDate = d3.bisector(function(d) { return d.date; }).left; 

     var x = d3.scaleTime() 
      .domain(d3.extent(data, function(d, i) { 
       return d.date; 
      })) 
      .range([0, width]); 
     var y = d3.scaleLinear() 
      .domain(d3.extent(data, function(d, i) { 
       return d.price; 
      })) 
      .range([height, 0]); 

     var xAxis = d3.axisBottom(x) 
      .tickSizeOuter(0); 
     var yAxis = d3.axisLeft(y) 
      .ticks(5) 
      .tickSizeOuter(0); 

     var area = d3.area() 
      .x(function(d) { return x(d.date); }) 
      .y0(height) 
      .y1(function(d) { return y(d.price); }); 

     var line = d3.line() 
      .x(function(d) { return x(d.date); }) 
      .y(function(d) { return y(d.price); }); 

     var svg = d3.select('#priceChart') 
      .append('svg') 
       .attr('width', width + margin.left + margin.right) 
       .attr('height', height + margin.top + margin.bottom) 
      .append('g') 
       .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); 

     svg.append('g') 
      .attr('class', 'x axis') 
      .attr('transform', 'translate(0,' + height + ')') 
      .call(xAxis); 

     svg.append('g') 
      .attr('class', 'y axis') 
      .call(yAxis); 

     var areaSvg = svg.append('g'); 
     areaSvg.append('path') 
      .attr('class', 'area') 
      .attr('d', area(data)) 
      .style('opacity', 0.3); 

     var lineSvg = svg.append('g'); 
     lineSvg.append('path') 
      .attr('class', 'line') 
      .attr('d', line(data)); 

     var focus = svg.append('g') 
      .style('display', 'none'); 

     focus.append('circle') 
      .attr('class', 'y') 
      .style('fill', 'steelblue') 
      .attr('r', 3); 

     svg.append('rect') 
      .attr('width', width) 
      .attr('height', height) 
      .style('fill', 'none') 
      .style('pointer-events', 'all') 
      .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], 
       d = x0 - d0.date > d1.date - x0 ? d1 : d0; 

      focus.select('circle.y') 
       .attr('transform', 'translate(' + x(d.date) + ',' + y(d.price) + ')'); 
     } 

私は何が間違っているのか分かりません。しかし、基本的にマウスを画面の左半分に動かすと、何も起こりません。グラフの最後のデータポイントに円が表示され、決して移動しません。グラフの右側にマウスを移動すると、コンソールにエラーが表示されますUncaught TypeError: Cannot read property 'date' of undefined

更新 ここには、問題を表すjsFiddleがあります。私が提供したコードは実際には関数であり、dataと$ elementの両方が変数に渡されます。私は彼らがどのようにフィドルで渡されたかを変えましたが、データは私が働いているものと同じです。

+0

あなたは何のフィドルを添付することができますあなたが持っている? (基本的にhtmlを含む) – deweyredman

+0

も$ elementはどこに定義されていますか? – deweyredman

+0

@deweyredman私はjsFiddleを含めるように質問を編集し、データと$要素の両方がどこから来たのかを説明しました。 –

答えて

1

d3.bisectorを使用するには、まずデータ配列をソートする必要があります。

APIは、この点に関しては非常に明示的ではないですが、あなたはそこに読むことができます:

は、戻り値は使用するのに適している[...]ソートされた順序を維持するために、アレイ内のxの挿入点を返します。配列がであると仮定してスプライスの最初の引数としてが既にソートされています。 (強調鉱山)

あなたがd3.bisectorを使用する前に、これは、あなたのデータをソートする機能である:ここでは

data.sort(function(a, b) { 
    return d3.ascending(a.date, b.date) 
}); 

は、あなたの作業フィドルは次のとおりです。https://jsfiddle.net/7154p8uv/

+0

それは素晴らしいです、私自身でそれを完全に逃しました。ご助力ありがとうございます。 –

関連する問題