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

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.

主站蜘蛛池模板: 师宗县| 浦东新区| 宿州市| 伊川县| 吉林省| 雷州市| 陕西省| 宝兴县| 临夏市| 泸溪县| 克拉玛依市| 科技| 乐昌市| 隆化县| 阿鲁科尔沁旗| 宜宾县| 宝鸡市| 托克逊县| 禄劝| 塘沽区| 九台市| 托里县| 东台市| 卓资县| 松桃| 彭阳县| 潼南县| 瑞昌市| 香河县| 昌吉市| 上林县| 新昌县| 柞水县| 南平市| 七台河市| 宜良县| 塘沽区| 南投市| 平武县| 额敏县| 杨浦区|