[d3.js] एक geoJSON ऑब्जेक्ट दिया डी 3 में एक मानचित्र केंद्र


Answers

मेरा जवाब जन वैन डेर लान के करीब है, लेकिन आप चीजों को थोड़ा सा सरल बना सकते हैं क्योंकि आपको भौगोलिक केंद्र की गणना करने की आवश्यकता नहीं है; आपको केवल बाउंडिंग बॉक्स की आवश्यकता है। और, एक unscaled, untranslated इकाई प्रक्षेपण का उपयोग करके, आप गणित को सरल बना सकते हैं।

कोड का महत्वपूर्ण हिस्सा यह है:

// Create a unit projection.
var projection = d3.geo.albers()
    .scale(1)
    .translate([0, 0]);

// Create a path generator.
var path = d3.geo.path()
    .projection(projection);

// Compute the bounds of a feature of interest, then derive scale & translate.
var b = path.bounds(state),
    s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
    t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];

// Update the projection to use computed scale & translate.
projection
    .scale(s)
    .translate(t);

यूनिट प्रोजेक्शन में फीचर के बाउंडिंग बॉक्स को कंप्यूटिंग करने के बाद, आप बाउंडिंग बॉक्स ( b[1][0] - b[0][0] और b[1][1] - b[0][1] के पहलू अनुपात की तुलना करके उपयुक्त पैमाने की गणना कर सकते हैं। b[1][1] - b[0][1] ) कैनवास के पहलू अनुपात ( width और height ) के लिए। इस मामले में, मैंने बाध्यकारी बॉक्स को 100% की बजाय कैनवास के 95% तक स्केल किया है, इसलिए स्ट्रोक और आस-पास की विशेषताओं या पैडिंग के किनारों पर थोड़ा अतिरिक्त कमरा है।

फिर आप बाध्यकारी बॉक्स के केंद्र का उपयोग करके अनुवाद की गणना कर सकते हैं ( (b[1][0] + b[0][0]) / 2 और (b[1][1] + b[0][1]) / 2 ) और कैनवास का केंद्र ( width / 2 और height / 2 )। ध्यान दें कि चूंकि बाउंडिंग बॉक्स यूनिट प्रोजेक्शन के निर्देशांक में है, इसलिए इसे स्केल ( s ) से गुणा किया जाना चाहिए।

उदाहरण के लिए, bl.ocks.org/4707858 :

bl.ocks.org/4707858

एक संबंधित प्रश्न है जहां प्रक्षेपण को समायोजित किए बिना किसी संग्रह में किसी विशेष सुविधा को ज़ूम करना है, यानी ज़ूम इनट्रिक के साथ प्रोजेक्शन को ज़ूम इन और आउट करने के साथ संयोजन करना। यह उपर्युक्त सिद्धांतों का उपयोग करता है, लेकिन गणित थोड़ा अलग है क्योंकि ज्यामितीय परिवर्तन (एसवीजी "ट्रांसफॉर्म" विशेषता) भौगोलिक प्रक्षेपण के साथ संयुक्त है।

उदाहरण के लिए, bl.ocks.org/4699541 :

bl.ocks.org/4699541

Question

वर्तमान में डी 3 में यदि आपके पास एक geoJSON ऑब्जेक्ट है जिसे आप आकर्षित करने जा रहे हैं तो आपको इसे स्केल करना होगा और उसे उस आकार में लाने के लिए इसका अनुवाद करना होगा, जिसे वह चाहता है और उसे केंद्र में व्यवस्थित करने के लिए इसका अनुवाद करें। यह परीक्षण और त्रुटि का एक बहुत ही कठिन कार्य है, और मैं सोच रहा था कि क्या इन मूल्यों को प्राप्त करने के लिए कोई बेहतर तरीका जानता है?

तो उदाहरण के लिए यदि मेरे पास यह कोड है

var path, vis, xy;
xy = d3.geo.mercator().scale(8500).translate([0, -1200]);

path = d3.geo.path().projection(xy);

vis = d3.select("#vis").append("svg:svg").attr("width", 960).attr("height", 600);

d3.json("../../data/ireland2.geojson", function(json) {
  return vis.append("svg:g")
    .attr("class", "tracts")
    .selectAll("path")
    .data(json.features).enter()
    .append("svg:path")
    .attr("d", path)
    .attr("fill", "#85C3C0")
    .attr("stroke", "#222");
});

मैं कितना छोटा कर सकता हूं। स्केल (8500) और .translate ([0, -1200]) कम से कम बिना जा रहे हैं?




डी 3 वी 4 के साथ यह आसान तरीका हो रही है!

var projection = d3.geoMercator().fitSize([width, height], geojson);
var path = d3.geoPath().projection(projection);

और अंत में

g.selectAll('path')
  .data(geojson.features)
  .enter()
  .append('path')
  .attr('d', path)
  .style("fill", "red")
  .style("stroke-width", "1")
  .style("stroke", "black");

आनंद लें, चीयर्स




केंद्र के अलावा, एक geoJSON ऑब्जेक्ट दिए गए डी 3 में एक मानचित्र , ध्यान दें कि आप फिट ऑब्जेक्ट fitExtent() पर fitSize() fitExtent() को पसंद कर सकते हैं यदि आप अपनी ऑब्जेक्ट की सीमाओं के चारों ओर पैडिंग निर्दिष्ट करना चाहते हैं। fitSize() स्वचालित रूप से इस पैडिंग को 0 पर सेट करता है।




उन लोगों के लिए जो लंबवत और क्षैतिज समायोजित करना चाहते हैं, यहां समाधान है:

  var width  = 300;
  var height = 400;

  var vis = d3.select("#vis").append("svg")
      .attr("width", width).attr("height", height)

  d3.json("nld.json", function(json) {
      // create a first guess for the projection
      var center = d3.geo.centroid(json)
      var scale  = 150;
      var offset = [width/2, height/2];
      var projection = d3.geo.mercator().scale(scale).center(center)
          .translate(offset);

      // create the path
      var path = d3.geo.path().projection(projection);

      // using the path determine the bounds of the current map and use 
      // these to determine better values for the scale and translation
      var bounds  = path.bounds(json);
      var hscale  = scale*width  / (bounds[1][0] - bounds[0][0]);
      var vscale  = scale*height / (bounds[1][1] - bounds[0][1]);
      var scale   = (hscale < vscale) ? hscale : vscale;
      var offset  = [width - (bounds[0][0] + bounds[1][0])/2,
                        height - (bounds[0][1] + bounds[1][1])/2];

      // new projection
      projection = d3.geo.mercator().center(center)
        .scale(scale).translate(offset);
      path = path.projection(projection);

      // adjust projection
      var bounds  = path.bounds(json);
      offset[0] = offset[0] + (width - bounds[1][0] - bounds[0][0]) / 2;
      offset[1] = offset[1] + (height - bounds[1][1] - bounds[0][1]) / 2;

      projection = d3.geo.mercator().center(center)
        .scale(scale).translate(offset);
      path = path.projection(projection);

      // add a rectangle to see the bound of the svg
      vis.append("rect").attr('width', width).attr('height', height)
        .style('stroke', 'black').style('fill', 'none');

      vis.selectAll("path").data(json.features).enter().append("path")
        .attr("d", path)
        .style("fill", "red")
        .style("stroke-width", "1")
        .style("stroke", "black")
    });



मैं अपने मानचित्र को केन्द्रित करने के लिए एक झुकाव मुक्त तरीके से इंटरनेट पर देख रहा था, और जन वैन डेर लान और एमबोस्टॉक के जवाब से प्रेरित हो गया। यदि आप svg के लिए कंटेनर का उपयोग कर रहे हैं तो jQuery का उपयोग करके एक आसान तरीका यहां दिया गया है। मैंने पैडिंग / सीमाओं आदि के लिए 95% की सीमा बनाई

var width = $("#container").width() * 0.95,
    height = $("#container").width() * 0.95 / 1.9 //using height() doesn't work since there's nothing inside

var projection = d3.geo.mercator().translate([width / 2, height / 2]).scale(width);
var path = d3.geo.path().projection(projection);

var svg = d3.select("#container").append("svg").attr("width", width).attr("height", height);

यदि आप सटीक स्केलिंग की तलाश में हैं, तो यह उत्तर आपके लिए काम नहीं करेगा। लेकिन अगर मुझे पसंद है, तो आप एक नक्शा प्रदर्शित करना चाहते हैं जो कंटेनर में केंद्रीकृत हो, यह पर्याप्त होना चाहिए। मैं मर्केटर मानचित्र को प्रदर्शित करने की कोशिश कर रहा था और पाया कि यह विधि मेरे मानचित्र को केंद्रीकृत करने में उपयोगी थी, और मैं आसानी से अंटार्कटिक हिस्से को काट सकता था क्योंकि मुझे इसकी आवश्यकता नहीं थी।




Related