Добавление точек на карту d3 SVG - PullRequest
2 голосов
/ 17 октября 2019

Я новичок в d3 и у меня возникли проблемы с добавлением точек на мою карту SVG. Я загружаю в карту SVG, а затем пытаюсь добавить координаты из моих данных, которые представляют собой массив объектов, отформатированных следующим образом:

{schoolName: "Harvard University", gpa: 4, state: "MA", city: "Cambridge", longitude: -71.10973349999999, latitude: 42.3736158}

В результате мой код ниже, что я добавляю наборкружков под тегом SVG, но ни один не появляется на карте, и я получаю то, что похоже на синтаксическую ошибку, которую я не вижу в своем коде.

Ошибка перевода: Translate Error

Что я здесь делаю неправильно?

var coords = require('./data/coordinates')

document.addEventListener("DOMContentLoaded", () => {

    // loads svg map
    d3.xml('src/data/usa2.svg', function(data){
        document.body.append(data.documentElement)
    })

    // adjusts data to include coordinates for each city
    cities = cities.default
    let schoolData = []
    d3.json("src/data/schoolInfo.json", function(schools){
        schools.map(el => {
            let currentCity = cities.filter(function(cities){return cities.city === el.city})
            el["hs-gpa-avg"] !== null && currentCity.length > 0 ? schoolData.push({"schoolName": el["displayName"], "gpa": el["hs-gpa-avg"], "state": el["state"], "city": el["city"], "longitude": currentCity[0]["longitude"], "latitude": currentCity[0]["latitude"]}) : ''
        })


    var width = 1200,
        height = 720;

    var albersProjection = d3.geoAlbers()
        .scale(1000)
        .rotate([70, 0])
        .center([-15, 35])
        .translate([width/2, height/2]);

    var svg = d3.select('svg')

    svg.selectAll("circle")
        .data(schoolData).enter()
        .append("circle")
        .attr("transform", function(d) {
            let coords = albersProjection([ d.longitude, d.latitude ]);
            return `translate(${coords[0]}px, ${coords[1]}px)`
        })
        .attr("r", "8px")
        .attr("fill", "red")   
    })

})

При устранении ошибки, связанной с переводом, у меня все еще остаются неуместные круги, как и предсказывалось в этом ответе :

Неуместные точки: Misaligned points to coordinates on map

1 Ответ

1 голос
/ 17 октября 2019

Атрибуты SVG-преобразования ожидают числа, простые числа без единиц. Однако вы можете указать единицы измерения, если используете CSS (style="transform: ..." вместо указания атрибута transform: transform = "...").

В приведенном ниже фрагменте сравниваются установочные единицы со свойством стиля CSS, прямая установка атрибута transform без единиц измерения и прямая установка атрибута transform с использованием единиц измерения. Это должно вызвать ту же ошибку в последнем прямоугольнике (который расположен неправильно из-за ошибки, он должен быть ниже синего прямоугольника):

<svg>
   <rect style="transform:translate(200px,0px)" width="20" height="20" fill="steelblue"></rect>
   <rect transform="translate(100,0)" width="20" height="20" fill="crimson"></rect>   
   <rect transform="translate(200px,50px)" width="20" height="20" fill="orange"></rect>
</svg>

Моя ошибка в последнем прямоугольнике: "Error: <rect> attribute transform: Expected ')', "translate(200px,50px)"."

Это то же самое, что и у вас, решение будет просто удалить px из ваших значений перевода. Вы также можете указать свойство CSS, используя .style() вместо .attr().


Что касается вашего следующего вопроса: почему круги все еще не правильно, но теперь у вас нет ошибок, ну, это другая проблема. Это обычная проблема.

У вас есть версия SVG для США - этот SVG состоит из вершин на плоскости 2d: проецируемых точек с единицами измерения в пикселях. Поскольку SVG уже спроецирован, ваши SVG-объекты уже спроецированы.

Ваши географические данные состоят из трехмерных точек (точек на сфере) с единицами измерения в градусах. Не зная проекции, использованной для создания SVG, вы не можете выровнять географическую точку и предварительно спроецированную точку.

Это распространенная проблема с предварительно спроецированным топографом / геойсон (также в котором координаты находятся в 2D-пространствес единицами измерения в пикселях). Решения те же:

  • попытка реплицировать проекцию, используемую при создании SVG при проецировании географических точек поверх нее (сложно)

  • При рисовании карты используйте только непроецированные координаты для обоих слоев (без готовых SVG, если вы их не сделали). (просто)

  • использовать только предварительно спроецированные координаты для обоих слоев при рисовании карты (но чтобы сделать это для точек, вам все равно нужно знать проекцию, используемую для создания SVG). (не стоит)

Эти вопросы и ответы касаются аналогичной проблемы, только с предварительно спроектированным топойсон / геойсон, а не SVG (это справедливо для сравнения, поскольку geoPath создает SVG-векторыобычно):

Второй включает ссылку на непрогнозируемый топойсон США:

https://bl.ocks.org/mbostock/raw/4090846/us.json

Мы можем использовать это с нашиминепроецированные точки - мы просто используем одну и ту же проекцию для точки и области.

Мы можем использовать это с topojson.js для создания массива геоджонов:

 var geojson = topojson.feature(data,data.objects.states).features;

И как только мы определим нашу проекцию, можно использовать projection([long,lat]) для проецирования точек и d3.geoPath(projection) для проецирования геоджона.

Где data - проанализированный JSON - значение, переданное функции обратного вызова d3.json.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...