Choose The Right Interpolation In D3 To Center A Path (line) Inside A Path (area)
By way of example, consider the following D3 code (only the relevant part, the complete - but only less than a dozen lines longer - code is on JSFiddle) which draws a line inside a band.
var points = [
[200, 100],
[200, 200],
[100, 300],
[100, 400]
];
var areaGenerator=d3.area()
.curve(d3.curveMonotoneY)
.x0(function(d){return d[0]-20})
.x1(function(d){return d[0]+20})
.y0(function(d,i){return d[1]})
.y1(function(d,i){return d[1]})
;
var area = areaGenerator(points);
svg.append('path')
.attr('d', area);
svg.append("path")
.data([points])
.attr("d", d3.line()
.curve(d3.curveCardinal
.tension(0.8)))
.attr("id","line")
Here is an image of the resulting svg object:
I've tried several value for .tension()
but I'm unable to find the right interpolation function to make the line to lie (approximately) in the middle of the band for its whole flow, subjected to the constraint that the first and the last sections of both the line and the band should be exactly vertical and they cannot "enlarge" to the left or to the right.
This is what I want to obtain, approximately:
Answer
My original answer wasn't thought through. You can simply apply the same curve property to the black path as you do to your red path: https://jsfiddle.net/s5o4hp3z/
Simply change the black path to this:
svg.append("path")
.data([points])
.attr("d", d3.line().curve(d3.curveMonotoneY))
.attr("id","line")
------- Original answer -------
You can use an area generator similar to the one you use for your red area, but with width properties making it look like a line.
I've modified your JSFiddle to showcase this: https://jsfiddle.net/6e03o42f/3/
What I've done is to change the path creation to this:
var lineAreaGenerator = d3.area()
.curve(d3.curveMonotoneY)
.x0(function(d){return d[0]-0.5})
.x1(function(d){return d[0]+0.5})
.y0(function(d,i){return d[1]})
.y1(function(d,i){return d[1]});
var lineArea = lineAreaGenerator(points);
svg.append("path")
.attr("d", lineArea)
.attr("id","line")
If this is indeed the approach you choose, then one would want to seperate the area generator code into a function. I've shown how do this in this JSFiddle: https://jsfiddle.net/6e03o42f/4/
Hope this helps!
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM