A less-sophisticated alternative to Mike Bostock's Gradient Along Stroke.
Note that this version does not compute mitre joints, so sharp bends reveal the segmented nature of the "path."
A less-sophisticated alternative to Mike Bostock's Gradient Along Stroke.
Note that this version does not compute mitre joints, so sharp bends reveal the segmented nature of the "path."
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<meta charset="utf-8"> | |
</head> | |
<body> | |
<script src="script.js"></script> | |
</body> | |
</html> |
var margin = { top: 50, left: 50, bottom: 50, right: 50 }, | |
width = window.innerWidth - margin.left - margin.right, | |
height = window.innerHeight - margin.top - margin.bottom, | |
vbWidth = width + margin.left + margin.right, | |
vbHeight = height + margin.top + margin.bottom; | |
var main = d3.select("body").append("main") | |
.style({ width: "90%", margin: "0 auto 0 auto" }) | |
.append("svg") | |
.attr({ viewBox: "0 0 " + vbWidth + " " + vbHeight }) | |
.append("g") | |
.attr({ | |
transform: "translate(" + [margin.left, margin.top] + ")" | |
}); | |
main.append("rect").attr({ | |
width: width, height: height, fill: "none" | |
}); | |
var random = d3.random.normal(); | |
var data = d3.range(10).map(function(d) { | |
return { x: random(), y: random() }; | |
}); | |
var x = d3.scale.linear() | |
.domain(d3.extent(data, function(d) { return d.x; })) | |
.range([0, width]); | |
var y = d3.scale.linear() | |
.domain(d3.extent(data, function(d) { return d.y; })) | |
.range([0, height]); | |
var dots = main.selectAll(".dot").data(data); | |
dots.enter().append("circle").classed("dot", true) | |
.attr({ r: 5 }) | |
.style({ opacity: 0.2 }) | |
dots.attr({ | |
cx: function(d) { return x(d.x); }, | |
cy: function(d) { return y(d.y); } | |
}); | |
var line = d3.svg.line().interpolate("basis") | |
.x(function(d) { return x(d.x); }) | |
.y(function(d) { return y(d.y); }); | |
var points = getPoints(line(data), 2); | |
var segs = []; | |
points.reduce(function(prev, curr) { | |
segs.push({ | |
x1: prev.x, y1: prev.y, x2: curr.x, y2: curr.y, t: curr.t | |
}); | |
return curr; | |
}); | |
var segmentContainer = main.selectAll(".segments").data([segs]); | |
segmentContainer.enter().append("g").classed("segments", true); | |
var segments = segmentContainer.selectAll(".segment").data(Object); | |
segments.enter().append("line"); | |
var i = d3.interpolateRgb("green", "red"); | |
segments | |
.attr({ | |
x1: function(d) { return d.x1; }, y1: function(d) { return d.y1; }, | |
x2: function(d) { return d.x2; }, y2: function(d) { return d.y2; }, | |
stroke: function(d) { return i(d.t); }, | |
"stroke-width": 10, "stroke-opacity": 0.1 | |
}) | |
.transition() | |
.delay(function(d, i) { return i; }) | |
.attr("stroke-opacity", 1); | |
segments.exit().remove(); | |
// Based on: //gist.github.com/mbostock/4163057 | |
// Sample the SVG path string "d" uniformly with the specified precision. | |
function getPoints(d, step) { | |
var path = document.createElementNS(d3.ns.prefix.svg, "path"); | |
path.setAttribute("d", d); | |
var length = path.getTotalLength(); | |
return d3.range(0, length, step) | |
.map(function(t) { | |
var point = path.getPointAtLength(t); | |
return { x: point.x, y: point.y, t: t/length }; | |
}); | |
} |