Instructor: We're starting off with a basic line already drawn. We have a scaleLinear for the X and a scaleLinear for the Y, and we're rendering a path. We can see what that looks like here.
With a line, we're going to add our data points. We're going to loop over our data. We'll get our D, which is going to be a data point. Now, we'll get the coordinates at which we need to render our circle.
I say const Y point is equal to our Y scale, and we'll use our Y selector to get our data and pass in our data point. Then, we'll get out X point. X scale with our X selector and pass in our data point.
With our two coordinates, we can now render our circle. I'll say return the circle element, and we're going to use CX, pass in our X point, and CY, pass in our Y point. CX and CY stand for center X and center Y. This will be the central point at which the circle renders.
We'll then supply a radius of 5, and then a stroke of white with a stroke width of 2. Then, we'll fill it with the same color as our line.
If we take a look at how it renders, we can see that we now have each point represented by a circle. The white stroke around the outside accentuates each point. You can see though that these points are getting cut off because of how the circle is rendering from the central point with the radius going outwards.
To fix this, we need to add some padding to our domain scale, a range of our scale. We're going to set up some const padding equals 10. Because these values, the domain, map to our output range, we can set our padding here, as well as our width minus padding.
We'll set our height minus padding, as well as instead of zero, we'll say padding. Now, our SVG will maintain at the same width, but will render to a constrained width and height. If we go back and look, we can see that we are now rendering within our constraints.
Rather than setting up mouse hovers on each of these, what we're going to do is set up an onMouseMove on the main SVG. Then, we will create our onMouseMove. That way, any time we move our mouse over the SVG, we can catch where the mouse coordinates are.
With our mouse coordinates, we can use e.clientX, which with us, because our SVG is rendering in the corner, it will map to this point. However, what we really care about is getting the coordinate that matches up with our range, because what we're going to do is do a invert.
We're going to take our X scale and use the invert method, which rather than what we have been doing using the X scale to take our data point and create a rendering value, what we're going to do is take our rendered value, which is just going to be a mouse coordinate, and map it back into our domain. This is going to return roughly a value between 0and 10.
Because our data is simplified, and our 0and 10 actually map to the index at which they are located, we can just stick with X scale invert. However, if we did have more complex data, or using the Y scale, we might have to use a bisector.
However, here, we can just say const index is equal to math.round, and we'll just round to a single index. Then, we'll do a this.setState and set our selected value to be our index.
In order to highlight the index, we're just going to just our radius. We're going get the index of our data, and then we're going to say const R equals this.state.selected is equal to i. We'll do a 10 radius or a 5 radius. Then, we'll pass in our radius here.
As we move our mouse along, we're going to get the coordinate inverted into our X value, and then we're going to round it to an index, and then trigger a setState. What that looks like is when we hover over, we can see that we're getting our X value, and the closer we are to that round point, which is going to be .5, it'll toggle over to the value that we are closest to.
Because we've set the onMouseOver to our SVG, we don't have to hover exactly over each data point for it to trigger.