What is the proper way to use D3's projection.

2019-04-17 23:08发布

So I'm experimenting a bit with D3's geo stream API, and things feel a bit hazy. I've been reading through the documentation here:

https://github.com/mbostock/d3/wiki/Geo-Streams

One point of confusion I have is the proper implementation of stream transforms. Let's say I create one:

//a stream transform that applies a simple translate [20,5]:
var transform = d3.geo.transform({
    point:function(){this.stream.point(x+20,y+5)}
}) 

Per the documentation, this.stream references the "wrapped stream." But what is the stream, really? From what I can gather, it is more of a procedure than explicit data structure--a sequence of data and function calls to transform the data. The syntax above seems to suggest that the wrapped stream is simply the object containing "stream listeners"

Moving on, I'm able to apply the stream transform using the projection method:

//a path generator with the transform applied using the projection() method
var path = d3.geo.path().projection(transform);

While I don't quite understand the underlying mechanics, the effect seems relatively straightforward: the underlying transform function of the path generator is called with transformed x,y arguments.

For my use case, I don't find this that helpful, particularly because my input data is not already projected. I'd like to use a projection to transform the data first, then transform those outputted coordinates. To that end, is there a general pattern for layering transforms?

I see that D3 does provide the projection.stream(listener) pattern which applies the projecting transform first, before applying the listener, but I'm not sure how to implement this. What should the listener argument be? Here's an example: http://jsfiddle.net/kv7yn8rw/2/.

Any guidance would be greatly appreciated!

标签: d3.js geo d3.geo
1条回答
放荡不羁爱自由
2楼-- · 2019-04-17 23:18

A key fact from the documentation is that "a geographic projection is one example of a stream transform."

Streams just allow one to transform (e.g. project) data multiple times without saving the intermediate data. A projection can just be an object with a stream attribute, e.g. proj_then_transform below.

The way to chain streams is as follows:

// stream 1
var proj = d3.geo.equirectangular();
// stream 2
var transform = d3.geo.transform({
    point:function(x,y){this.stream.point(x+20,y+5)}
});
// stream 1 then stream 2
var proj_then_transform = {
        stream: function(s) { 
            return proj.stream(transform.stream(s)); 
        }
     };

I've updated the example with a working solution: http://jsfiddle.net/cvs5d7o9/2/

查看更多
登录 后发表回答