Skip to content

Instantly share code, notes, and snippets.

@rveciana
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rveciana/04ce0887026bd3e6185c to your computer and use it in GitHub Desktop.
Save rveciana/04ce0887026bd3e6185c to your computer and use it in GitHub Desktop.
D3 Trail Layout using coordinates

This an example using the D3 trail layout made by Benjamin Schmidt. The example shows how to use the coordinates as the coordType value. The track.json data represents the Hayian typhoon track, as it's explained in this blog entry.

There is a blog entry explaining this example at GeoExamples

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="pathlayout.js"></script>
<script>
var width = 600,
height = 500;
var projection = d3.geo.mercator()
.scale(5*(width + 1) / 2 / Math.PI)
.translate([width / 2, height / 2])
.rotate([-125, -15, 0])
.precision(.1);
var path = d3.geo.path()
.projection(projection);
d3.json("track.json", function(error, track) {
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var trail = d3.layout.trail()
.positioner(function(d) {return [d.lon,d.lat];})
.coordType('coordinates');
var trail_layout = trail.data(track).layout();
paths = svg.selectAll("line").data(trail_layout);
paths.enter()
.append('path')
.style("stroke-width",3)
.style("stroke","black")
.attr("d", path);
});
</script>
d3.layout.trail = function() {
var that = {}; //output object
var time = function() {}, //how to access the time data (must be numeric--should but doesn't handle dates);
currentTime, //points of this time will be display with full opacity;
//later points are dropped;
decayRange, //points of this age will have opacity 0. If either currentTime or decayRange is not defined, opacity will be added as some undefined values.
data, // the data being arranged
positioner, // a function that returns the [x,y] for the point.
sort, // a function specifying the sort order
coordType = 'coordinates', //either "coordinates" or "xy"; if the first, returns a "coordinates" array; if the latter, returns x1,y1,x2,y2
grouping; // a function to split the data up into multiple segments;
grouping = function(d) {
return 1
}
positioner = function(datum) {
//given a datum, returns an [x,y] array.
//Might be a projection, for example, or a scale output.
return [datum.x,datum.y]
}
lineToSegments = function(values) {
//the returned array will be filtered to only include segments that fit the defined values.
if (currentTime != undefined & decayRange != undefined) {
values = values.filter(function(d) {
return (time(d) <= currentTime && time(d) >= (currentTime-decayRange))
})
}
values = d3
.nest()
.key(function(d) {return grouping(d)})
.entries(values);
tmp = values;
output = [];
var i = 0
values.forEach(function(element) {
i++;
if (sort!=undefined) {
element.values.sort(sort)
}
if (i==1) {
//console.log(element)
}
var values = element.values;
for (var i = 0; i < (values.length); i++) {
var current = values[i];
if (values[i+1] != undefined) {
current.next = values[i+1]
} else {
current.next = {}
}
if (values[i-1] != undefined) {
current.previous = values[i-1]
if (coordType=="coordinates") {
current.coordinates = [
positioner(values[i-1]),
positioner(values[i])
]
} else if (coordType=="xy") {
var a = positioner(values[i-1]),
b = positioner(values[i]);
current.x1=a[0]
current.y1=a[1]
current.x2=b[0]
current.y2=b[1]
}
current.type = "LineString";
//opacity will probably be this: the percentage of the decay range ago that it was.
//Early tests should guarantee a result between 0 and 1.
}
current.opacity = 1-(currentTime-time(current))/decayRange
}
output = output.concat(values);
})
return output;
}
that.layout = function() {
output = lineToSegments(data);
return output;
}
that.coordType = function(x) {
if (!arguments.length) return coordType;
coordType= x
return that
}
that.grouping = function(x) {
if (!arguments.length) return grouping;
grouping= x
return that
}
that.time = function(x) {
if (!arguments.length) return time;
time = x
return that
}
that.currentTime = function(x) {
if (!arguments.length) return currentTime;
currentTime= x
return that
}
that.decayRange = function(x) {
if (!arguments.length) return decayRange;
decayRange= x
return that
}
that.data = function(x,append) {
if (!arguments.length) return data;
if (append) {
data = data || [];
data = data.concat(x)
} else {
data = x
}
return that
}
that.positioner = function(x) {
if (!arguments.length) return positioner;
positioner = x
return that
}
that.sort = function(x) {
if (!arguments.length) return sort;
sort= x
return that
}
return that;
}
[{"day":3, "hour":18, "lat":6.1, "lon":153.3, "class": 2},{"day":3, "hour":21, "lat":6.1, "lon":152.8, "class": 2},{"day":4, "hour":0, "lat":6.1, "lon":152.2, "class": 3},{"day":4, "hour":3, "lat":6.2, "lon":151.2, "class": 3},{"day":4, "hour":6, "lat":6.2, "lon":150.4, "class": 3},{"day":4, "hour":9, "lat":6.2, "lon":149.5, "class": 3},{"day":4, "hour":12, "lat":6.3, "lon":148.6, "class": 3},{"day":4, "hour":15, "lat":6.3, "lon":148.4, "class": 3},{"day":4, "hour":18, "lat":6.5, "lon":147.6, "class": 3},{"day":4, "hour":21, "lat":6.5, "lon":147.0, "class": 3},{"day":5, "hour":0, "lat":6.5, "lon":145.9, "class": 4},{"day":5, "hour":3, "lat":6.5, "lon":145.2, "class": 4},{"day":5, "hour":6, "lat":6.5, "lon":144.6, "class": 4},{"day":5, "hour":9, "lat":6.5, "lon":144.0, "class": 4},{"day":5, "hour":12, "lat":6.9, "lon":143.1, "class": 4},{"day":5, "hour":15, "lat":7.0, "lon":142.1, "class": 4},{"day":5, "hour":18, "lat":7.1, "lon":141.3, "class": 5},{"day":5, "hour":21, "lat":7.3, "lon":140.5, "class": 5},{"day":6, "hour":0, "lat":7.3, "lon":139.7, "class": 5},{"day":6, "hour":3, "lat":7.5, "lon":138.9, "class": 5},{"day":6, "hour":6, "lat":7.6, "lon":138.0, "class": 5},{"day":6, "hour":9, "lat":7.7, "lon":137.2, "class": 5},{"day":6, "hour":12, "lat":7.9, "lon":136.2, "class": 5},{"day":6, "hour":15, "lat":8.1, "lon":135.3, "class": 5},{"day":6, "hour":18, "lat":8.2, "lon":134.4, "class": 5},{"day":6, "hour":21, "lat":8.4, "lon":133.6, "class": 5},{"day":7, "hour":0, "lat":8.7, "lon":132.8, "class": 5},{"day":7, "hour":3, "lat":9.0, "lon":131.9, "class": 5},{"day":7, "hour":6, "lat":9.3, "lon":131.1, "class": 5},{"day":7, "hour":9, "lat":9.8, "lon":130.2, "class": 5},{"day":7, "hour":12, "lat":10.2, "lon":129.1, "class": 5},{"day":7, "hour":15, "lat":10.4, "lon":128.0, "class": 5},{"day":7, "hour":18, "lat":10.6, "lon":126.9, "class": 5},{"day":7, "hour":21, "lat":10.8, "lon":125.9, "class": 5},{"day":8, "hour":0, "lat":11.0, "lon":124.8, "class": 5},{"day":8, "hour":3, "lat":11.2, "lon":123.7, "class": 5},{"day":8, "hour":6, "lat":11.4, "lon":122.6, "class": 5},{"day":8, "hour":9, "lat":11.5, "lon":121.6, "class": 5},{"day":8, "hour":12, "lat":11.8, "lon":120.7, "class": 5},{"day":8, "hour":15, "lat":12.3, "lon":119.4, "class": 5},{"day":8, "hour":18, "lat":12.4, "lon":118.2, "class": 5},{"day":8, "hour":21, "lat":12.5, "lon":117.3, "class": 5},{"day":9, "hour":0, "lat":12.3, "lon":116.6, "class": 5},{"day":9, "hour":3, "lat":12.9, "lon":115.6, "class": 5},{"day":9, "hour":9, "lat":13.9, "lon":113.9, "class": 5},{"day":9, "hour":12, "lat":14.4, "lon":113.1, "class": 5},{"day":9, "hour":15, "lat":15.0, "lon":112.2, "class": 5},{"day":9, "hour":18, "lat":15.4, "lon":111.4, "class": 5},{"day":9, "hour":21, "lat":15.9, "lon":111.1, "class": 5},{"day":10, "hour":0, "lat":16.5, "lon":110.3, "class": 5},{"day":10, "hour":3, "lat":17.0, "lon":109.7, "class": 5},{"day":10, "hour":6, "lat":17.8, "lon":109.0, "class": 5},{"day":10, "hour":9, "lat":18.5, "lon":108.4, "class": 5},{"day":10, "hour":12, "lat":19.4, "lon":108.1, "class": 5},{"day":10, "hour":15, "lat":19.8, "lon":107.9, "class": 5},{"day":10, "hour":18, "lat":20.3, "lon":107.5, "class": 4},{"day":10, "hour":21, "lat":20.8, "lon":107.1, "class": 4},{"day":11, "hour":0, "lat":21.3, "lon":107.2, "class": 4},{"day":11, "hour":3, "lat":22.0, "lon":107.2, "class": 4},{"day":11, "hour":6, "lat":22.3, "lon":107.4, "class": 3},{"day":11, "hour":9, "lat":22.6, "lon":107.6, "class": 3},{"day":11, "hour":12, "lat":23.0, "lon":107.0, "class": 2}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment