官术网_书友最值得收藏!

Tracking the mouse

As a last step, we'll add the mouse support that highlights the data points, shows the values at that specific year, and adds a vertical line to make things more clear:

We do this in two steps. First, we create all the elements that make up the line and the markers, and after that we add a mouse listener, which will show these elements in the correct positions. Let's look at the elements:

function addMouseTracker(xScale, yIndexedScale, yIncomeScale, adjustedIndexedData, unadjustedCleaned) { 

...
var focus = chart.append("g").attr("class", "focus").style("display", "none");
focus.append("circle").attr("id", "indexCircle").attr("r", 4.5);
focus.append("circle").attr("id", "incomeCircle").attr("r", 4.5);
focus.append("text").attr("id", "indexText").attr("x", 9).attr("dy", ".35em");
focus.append("text").attr("id", "incomeText").attr("x", 9).attr("dy", ".35em");

var verticalLineP = d3.line()([[0,-10],[0,height+10]]); focus.append("path")
.attr("d", verticalLineP)
.attr("class", "verLine")
.attr("stroke", "grey")
.attr("stroke-dasharray", "6,6")
.attr("stroke-width", "1");

chart.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);

...
}

We first add a group, which we hide (display: none), to which we add two circles, two text elements, and a vertical line. These are the elements we'll show when we move the mouse over the chart. We also add a rectangle that completely covers the chart. To this rectangle, we add our mouse listeners. As you can see, when we enter this rectangle, the focus g element becomes visible, and when we move out of the rectangle, the g element is hidden again. The interesting code, however, is in the mousemove() function:

function mousemove() { 
var x0 = xScale.invert(d3.mouse(this)[0])
var xToShow = Math.round(x0);
var d = adjustedIndexedData[xToShow-1984];
var dIncome = unadjustedCleaned[xToShow-1984];
var xPos = xScale(xToShow);
var yIncomePos = yIncomeScale(dIncome.value);
var yIndexPos = yIndexedScale(d.indexed);

focus.select("#indexCircle").attr("transform", "translate(" + xPos + "," + yIndexPos + ")");
focus.select("#incomeCircle").attr("transform", "translate(" + xPos + "," + yIncomePos + ")");
focus.select(".verLine").attr("transform", "translate(" + xPos + "," + 0 + ")");

var textOffset = (yIncomePos < yIndexPos) ? 5 : -5;

focus.select("#indexText")
.attr("transform", "translate(" + xPos + "," + (yIndexedScale(d.indexed) + textOffset) + ")")
.text(Math.round((d.indexed-100)*100)/100);
focus.select("#incomeText")
.attr("transform", "translate(" + xPos + "," + (yIncomeScale(dIncome.value) - textOffset) + ")")
.text("$ " + dIncome.value);

}

In this code, the following steps are taken whenever we move the mouse over the chart:

  1. We get the positon of the mouse inside the rectangle we defined, and get the value of x from that position (d3.mouse(this)[0]). With this x position, we can determine the year we're working with by using the xScale.invert function. So, at this point we know which year corresponds to the position of the mouse.
  2. Next, we get the relevant data (d and dIncome). With the year and these two values we can get the exact x and y positions of the data elements belonging to the year on the two lines: xPos, yIncomePos, and yIndexPos.
  3. Now that we have the positions, we move the circles and line we created to those positions.
  4. Finally, we move the text elements to the correct positions and set their values to the correct values.

And that's it. With this mouse listener added, we have a line and a set of circles that move to the correct points on the line whenever we move the mouse on the chart.

主站蜘蛛池模板: 开江县| 安平县| 乡宁县| 明光市| 庆城县| 靖西县| 云阳县| 龙川县| 河津市| 浪卡子县| 古浪县| 临桂县| 新郑市| 朝阳县| 崇文区| 长治县| 桃江县| 建昌县| 济阳县| 秀山| 临高县| 常州市| 恩平市| 定日县| 无棣县| 普宁市| 西宁市| 新源县| 巨鹿县| 蛟河市| 巴彦县| 井冈山市| 栾川县| 会昌县| 葵青区| 北票市| 武乡县| 沙田区| 白银市| 门头沟区| 环江|