前回はこちら
d3.jsでチャートを作る ラインチャートとバーチャートを2つのy軸上に描画する
次回はこちら
d3.jsでチャートを作る パイチャート
JSFiddleはこちら
X軸。今回はtimeを使用している。またrange()の指定は少しずらすために30からとなっている。
// x軸は日付。y軸にくっつけたくなかったので30からはじめている var x = d3.time.scale().nice() .domain(d3.extent(data, function (d) { return d.date; })) .range([30, width]); var yearMonthFormat = d3.time.format("%Y/%m"); var xAxis = d3.svg.axis().scale(x) .orient('bottom') .tickFormat(yearMonthFormat); svg.append('g') .attr('class', 'x axis') .attr('transform', 'translate(0, ' + height + ')') .call(xAxis);
ツールチップ。
// ツールチップ var focus = svg.append('g') .attr('class', 'focus'); focus.append('rect') .attr({ x: -10, y: -25, width: 105, height: 50 }); // circle focus.append('circle') .attr('class', 'profit') .attr({ r: 5, cy: -15 }); focus.append('circle') .attr('class', 'sales') .attr({ r: 5 }); focus.append('circle') .attr('class', 'expense') .attr({ r: 5, cy: 15 }); // text focus.append('text') .attr('class', 'profit') .style('text-anchor', 'end') .attr({ x: 90, y: -15, dy: '.35em' }); focus.append('text') .attr('class', 'sales') .style('text-anchor', 'end') .attr({ x: 90, dy: '.35em' }); focus.append('text') .attr('class', 'expense') .style('text-anchor', 'end') .attr({ x: 90, y: 15, dy: '.35em' });
オーバーレイとツールチップの表示場所の指定。チャート上のどこにマウスがあっても表示したいのでオーバーレイはチャート全体を覆っている。mousemove()の冒頭でマウスの現在座標からその位置よりも左側に位置するデータをbisector()で取得している。それだけだとマウスが二つのデータ間にある場合、必ず左側のものが選ばれてしまうのでマウスとデータ間の距離を比較してツールチップを表示するべきデータを取得している。このx.invert()の使用方法はtime()でしか使用できないので注意。ordinal(), linear()の場合(linear()は違うのかも。調査していないので不明)はデータの幅とrange()、マウスの座標から当該のデータを探し出す必要がある(詳細は下記参考を参照してもらいたい)。
// オーバーレイ svg.append('rect') .attr('class', 'overlay') .attr({ width: width, height: height }) .on('mouseover', function () { focus.style('display', 'block'); }) .on('mouseout', function () { focus.style('display', 'none'); }) .on('mousemove', mousemove); var bisectDate = d3.bisector(function (d) { return d.date; }).left , formatValue = d3.format(",.2f") , formatCurrency = function (d) { return formatValue(d) + '億円'; }; function mousemove() { var x0 = x.invert(d3.mouse(this)[0]) , i = bisectDate(data, x0, 1); if (i < data.length) { var d0 = data[i - 1], d1 = data[i], d = x0 - d0.date > d1.date - x0 ? d1 : d0; // 一番近いデータを取得 focus.attr('transform', 'translate(' + (x(d.date)) + ',' + y(d.sales) + ')'); focus.select('text.profit').text(formatCurrency(d.profit)); focus.select('text.sales').text(formatCurrency(d.sales)); focus.select('text.expense').text(formatCurrency(d.sales - d.profit)); } }
参考
Inversion with ordinal scale
0 件のコメント:
コメントを投稿