简体   繁体   中英

D3 Rotating Globe: How to rotate the graticule (grid)?

I am using D3 to make an interactive visualisation of some JSON data on an orthographic projection. The user should be able to spin the globe by dragging their mouse/trackpad.

Using the below code I can successfully spin the points, however the graticule remains static.

I tred to make a working snippet below but it displays differently on the embedded previewer than on my machine; any tips on how to get this working are also appreciated!

 leeroyjenkins = function() { var data = [{ "latitude": 0, "longitude": 0, "magnitude": "1.0" }, { "latitude": 10, "longitude": 10, "magnitude": "2.0" }, { "latitude": 20, "longitude": 20, "magnitude": "3.0" }, { "latitude": 30, "longitude": 30, "magnitude": "4.0" }, { "latitude": 40, "longitude": 40, "magnitude": "5.0" }, ] main(data); }; var main = function(points) { var width = 600, height = 600, //rotate = [10, -10], time = Date.now(); var sphere = { type: "Sphere" }; var graticule = d3.geo.graticule(); var projection = d3.geo.orthographic() .scale(250) .translate([width / 2, height / 2]) .clipAngle(90); var pointpath = function(d, r) { var pr = d3.geo.path().projection(projection).pointRadius(r); return pr({ type: "Point", coordinates: [d.longitude, d.latitude] }) } var path = d3.geo.path() .projection(projection); var λ = d3.scale.linear() .domain([0, width]) .range([-180, 180]); var φ = d3.scale.linear() .domain([0, height]) .range([90, -90]); var drag = d3.behavior.drag().origin(function() { var r = projection.rotate(); return { x: λ.invert(r[0]), y: φ.invert(r[1]) }; }) .on("drag", function() { projection.rotate([λ(d3.event.x), φ(d3.event.y)]); svg.selectAll("path.point").attr("d", function(d) { return pointpath(d, d.magnitude * 2.5); }); svg.selectAll("path.graticule").attr("d", path); }); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); svg.append("path") .datum(graticule) .attr("class", "graticule") .attr("d", path); var point = svg.selectAll("path.point").data(points); point.enter() .append("path") .attr("class", "point") .attr("d", function(d) { return pointpath(d, 0) }) .transition() .delay(function(d, i) { return i * 200; }) .duration(200) .attr("d", function(d) { return pointpath(d, d.magnitude * 2.5) }); svg.call(drag); } //end Main leeroyjenkins(); 
 body { background-color: #DDD; color: #555; } country { fill: #ccc; stroke: #fff; stroke-width: .5px; stroke-linejoin: round; } graticule { fill: none; stroke: #EEE; stroke-opacity: .3; stroke-width: .5px; } graticule.outline { stroke: #333; stroke-opacity: 1; stroke-width: 1.5px; } div.tooltip { position: absolute; text-align: center; width: 240px; height: 60px; padding: 2px; font: 12px sans-serif; background: #FFF; border: 0px; border-radius: 8px; /*pointer-events: none; */ } title { display: inline-block; font-size: 48px; line-height: 90px; text-align: center; } path.point { stroke: red; fill: red; } 
 <script src="http://d3js.org/topojson.v1.min.js"></script> <script src="http://d3js.org/d3.geo.projection.v0.min.js"></script> <script src="http://d3js.org/d3.v3.min.js"></script> 

I believe I actually posted the correct code in my question, however my issues with the previewer meant I didn't notice that it was working.

In any event the part I was having trouble with was:

svg.selectAll("path.graticule").attr("d", path);

Which I was putting on the line under return pointpath . Simply placing the code on the line under that did the trick.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM