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

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.

主站蜘蛛池模板: 曲阳县| 福泉市| 日土县| 奉新县| 威远县| 张家界市| 鲜城| 禄劝| 蕲春县| 集安市| 临漳县| 漾濞| 连山| 安吉县| 东乌| 明光市| 海门市| 安国市| 通辽市| 定远县| 东兰县| 道真| 平南县| 会昌县| 南通市| 沁源县| 凤城市| 东至县| 丰顺县| 新郑市| 罗源县| 怀来县| 重庆市| 通山县| 厦门市| 克什克腾旗| 新乡市| 常熟市| 遵义县| 长寿区| 华容县|