使用D3.js无法放大巴基斯坦地图的技术求助
Hey there! Let's get your Pakistan map looking properly sized and add working zoom functionality too. The core issue with your current code is that you're using a fixed scale value that doesn't align with Pakistan's actual geographic bounds—so the map ends up tiny and off-center. Here's how to fix it step by step:
Step 1: Use Dynamic Projection Based on Map Bounds
Instead of guessing at scale and translate values, we'll calculate them automatically using the geographic extent of your TopoJSON data. This ensures the map fills your SVG container perfectly.
Step 2: Add Zoom Interaction (Optional but Handy)
If you want users to zoom in/out and pan the map, we'll integrate D3's built-in zoom behavior for that.
Modified Full Code
<meta charset="utf-8"> <style> path { fill: #e0e0e0; stroke: #000; stroke-width: .5px; } .land-boundary:hover { fill: #ffcc80; /* Add hover highlight for better visibility */ } </style> <body> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script> <link href="http://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet" type="text/css"> <script> var width = 960, height = 480; var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) .call(d3.behavior.zoom() // Enable zoom and pan .scaleExtent([1, 10]) // Restrict zoom between 1x and 10x .on("zoom", function() { svg.selectAll("path").attr("transform", `translate(${d3.event.translate})scale(${d3.event.scale})`); })); var projection = d3.geo.equirectangular() .precision(.1); var path = d3.geo.path() .projection(projection); // Load the provided TopoJSON file directly d3.json("https://raw.githubusercontent.com/deldersveld/topojson/master/countries/pakistan/pakistan-provinces.json", function(error, topology) { if (error) throw error; // Convert TopoJSON to usable GeoJSON feature var pakistanFeature = topojson.feature(topology, topology.objects.PAK_adm1); // Calculate the geographic bounds of the map var bounds = path.bounds(pakistanFeature); // Calculate scale to fit the map in the SVG (with 5% padding) var scale = .95 / Math.max((bounds[1][0] - bounds[0][0]) / width, (bounds[1][1] - bounds[0][1]) / height); // Calculate translate to center the map in the SVG var translate = [(width - scale * (bounds[1][0] + bounds[0][0])) / 2, (height - scale * (bounds[1][1] + bounds[0][1])) / 2]; // Update projection with our calculated values projection .scale(scale) .translate(translate); // Render the map svg.append("path") .datum(pakistanFeature) .attr("d", path) .attr("class", "land-boundary"); }); </script> </body> </html>
Key Changes Explained:
- Dynamic Projection:
path.bounds(pakistanFeature)grabs the exact min/max latitude and longitude of Pakistan's provinces.- We calculate
scaleto fit the map within your SVG (the.95adds a small padding so the map doesn't touch the edges). translatecenters the map perfectly in the SVG container.
- Zoom & Pan:
d3.behavior.zoom()adds mouse scroll zoom and click-drag pan functionality.scaleExtent([1,10])prevents users from zooming too far in or out.- The zoom event handler updates the map's transform to apply zoom and pan in real time.
- Visual Tweaks: Added a light fill color and hover highlight to make provinces easier to distinguish.
Why Your Original Code Failed
Hardcoding scale(153) was way too small for Pakistan's geographic size with the equirectangular projection. By using the actual bounds of your data, we eliminate guesswork and ensure the map fits exactly how you want it.
内容的提问来源于stack exchange,提问作者Inshal Saleem

