I'm trying to achieve the desired result (left) using d3, svg, and css for a spline chart to give it a '3d' effect. Overlaying two splines with an offset results in something close however with certain data or zooming you can see the bottom 'shadow' (right) does not follow the main spline due to interpolation.
I've tried with a gradient however this gets applied over the entire svg area and not just horizontally on the path. Code snippet follows d3's example (https://bl.ocks.org/gordlea/27370d1eea8464b04538e6d8ced39e89).
// 2. Use the margin convention practice
var margin = { top: 50, right: 50, bottom: 50, left: 50 }
, width = window.innerWidth - margin.left - margin.right // Use the window's width
, height = window.innerHeight - margin.top - margin.bottom; // Use the window's height
// The number of datapoints
var n = 21;
// 5. X scale will use the index of our data
var xScale = d3.scaleLinear()
.domain([0, n - 1]) // input
.range([0, width]); // output
// 6. Y scale will use the randomly generate number
var yScale = d3.scaleLinear()
.domain([0, 1]) // input
.range([height, 0]); // output
// 7. d3's line generator
var line = d3.line()
.x(function (d, i) { return xScale(i); }) // set the x values for the line generator
.y(function (d) { return yScale(d.y); }) // set the y values for the line generator
.curve(d3.curveBasisOpen) // apply smoothing to the line
// 8. An array of objects of length N. Each object has key -> value pair, the key being "y" and the value is a random number
var dataset = d3.range(n).map(function (d) { return { "y": d3.randomUniform(1)() } })
// 1. Add the SVG to the page and employ #2
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// 3. Call the x axis in a group tag
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale)); // Create an axis component with d3.axisBottom
// 4. Call the y axis in a group tag
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale)); // Create an axis component with d3.axisLeft
// 9. Append the path, bind the data, and call the line generator
svg.append("path")
.datum(dataset) // 10. Binds data to the line
.attr("class", "line") // Assign a class for styling
.attr("stroke", "url(#gradID)")
//.attr("stroke", "red")
.attr("d", line); // 11. Calls the line generator
var defs = svg.append('defs');
const linearGradient = defs.append("linearGradient");
linearGradient
.attr("id", "gradID")
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "0%")
.attr("y2", "100%");
linearGradient
.append("stop")
.attr("offset", "0")
.attr("style", "stop-color:blue;stop-opacity:1");
linearGradient
.append("stop")
.attr("offset", "1")
.attr("style", "stop-color:red;stop-opacity:1");
.line {
fill: none;
stroke-width: 10;
stroke-linecap: round;
}
<!DOCTYPE html>
<meta charset="utf-8">
<body>
</body>
<!-- Load in the d3 library -->
<script src="https://d3js.org/d3.v5.min.js"></script>
