nini
nini

Reputation: 41

how to use .scale and .translate with d3.js?

I have been trying to use .scale().translate on projection. However, I was unable to create the right scale. Mine seems to show tiny map on the webpage and was unable to change its size(when I try to change it, it disappear which is probable not the right scale....). In the photo, you probably see a tiny map with my h1 heading on the top of the page. Does anyone know how to make the right scale? I've been stuck on this really long time, please help :(

Here is my HTML

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link rel="stylesheet" href="./dist/main.css" />
    <script src="./dist/main.js"></script>
    <script src="https://d3js.org/d3.v4.js"></script>
    <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
    <script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>
    <script src="https://d3js.org/topojson.v2.min.js"></script>
    <script src="neighborhood.js"></script>
    <title>Project Name</title>
</head>

<body>
    <h1>House Price in the Bay Area</h1>
    <svg id="my_dataviz" width="400" height="300"></svg>
    <script src="index.js"></script>
    <script src="neighborhood.js"></script>
</body>

</html>

and here is my .js file

var canvas = d3.select("body").append("svg")
    .attr("width", 900)
    .attr("height", 600)

d3.json("Bay_Area_Counties.geojson", function (data) {
    var group = canvas.selectAll("g")
        .data(data.features)
        .enter()
        .append("g")

    var projection = d3.geoMercator().**scale().translate([])**;
    var path = d3.geoPath(projection);

    var areas = group.append("path")
        .attr("d", path)[![ ][1]][1]
        .attr("class", "area")
        .attr("fill", "steelblue");
});

Upvotes: 3

Views: 474

Answers (1)

Andrew Reid
Andrew Reid

Reputation: 38161

If the point disappears as you zoom in your probably have the wrong translate.

A d3 projection has a center. A coordinate in degrees that marks the center of the projection. The translate value is to what coordinate in pixels the center should be projected to.

  • You have no center coordinate specified, so for a Mercator projection it is the default: [0°E,0°N]: a point off the coast of Africa.
  • You don't show what coordinate you have for the translate, but the default is [480,250] - this is where the center coordinate will be renedered: 250 pixels from the left of the SVG/Canvas/Container, 480 pixels down from the top.

As we zoom in the center point remains projected to the translate point, everything else moves. If we zoom in far enough (ie increase the scale value enough), everything other than the center point will be out of frame:

enter image description here

So if when zooming in your feature drops off the map, we need a new center coordinate. Preferably select a coordinate within your features of interest and roughly in their geographic center. Now you can toy with a scale factor that will properly show your areas of interest.

Without setting a center - how is D3 to know what you want to focus on when you set the scale higher?

You haven't provided a geojson of your features or a description, so hopefully the above is enough for you to get a good result. However, there is an easier way.

When setting the map parameters by hand a center coordinate is useful and traditionally the translate value is the middle of the SVG/Canvas/Container. However, projection.fitSize/fitExtent will set the translate and the scale values so that the features of interest will fill the specified pixel extent automagically.

This approach does not set the center coordinate - it translates the center coordinate off screen if necessary so that the geographic features of interests intersect the specified pixel extent. This means the translate value is dependent on scale, and we can't modify projection parameters after we use these fitting methods as easily as before.

With projection.fitSize() we specify the width and height of our SVG and the geojson object we wish to show: projection.fitSize([width,height],feature). fitExtent is similar but allows margins to be specified (D3's documentation has details), there are also a few similar methods for different spacing options (again covered in the docs better than I can do here).

Upvotes: 2

Related Questions