Подтвердить что ты не робот

Наложить пути d3 на Карты Google?

Я пытаюсь наложить карту на Карты Google, используя d3.geo и GeoJson. Мне удалось заставить d3 использовать проекцию Google Map для рисования путей, что было удивительно просто. Вот что я до сих пор:

http://www.caudillweb.com/temp/d3_choropleth.html

Это хорошо работает, когда я увеличиваю и уменьшаю масштаб:

Map zoomed outMap zoomed in

Но когда я панорамирую, наложение SVG также перемещается, и поскольку его размер фиксирован, формы усекаются:

Map panned down

Кто-нибудь получил что-то подобное, чтобы работать? Любые идеи, по которым я мог бы идти отсюда? Приведенный выше пример представляет собой единый автономный HTML файл, если кто-то хочет поиграть с ним.

4b9b3361

Ответ 1

В этом примере ширина и высота svg установлены на 8000 x 8000, что, казалось, было в порядке до уровня масштабирования 9-10. Верхняя и левая стороны установлены на -4000 x -4000, чтобы центрировать его. Наконец, проекция смещена/смещена так, что она рисует в центре svg:

Увеличить и центрировать svg:

.SvgOverlay svg {
    position: absolute;
    top: -4000px;
    left: -4000px;
    width: 8000px;
    height: 8000px;        
}

Смещение проекции:

return [pixelCoordinates.x + 4000, pixelCoordinates.y + 4000];

Ответ 2

Один из вариантов - установить начальный размер карты на нечто очень большое, скажем, 1000 х 1000 пикселей или больше. Это заставит SVG-оверлей отображать в пределах видимой области (которая, по-видимому, является препятствием для Firefox). Я понимаю, что это может зависнуть с дизайном вашего сайта, поэтому вам может потребоваться обернуть карту с помощью div, чтобы скрыть переполнение.

#map-wrap {
    width: 500px;
    height: 500px;
    overflow: hidden;
}

#map {
    width: 1000px; /* just big enough to show the whole thing at zoom #6 */
    height: 1000px;
}

После того, как карта отобразится, вы можете изменить размер карты до желаемого размера 500 x 500 и повторно центрировать карту. Это можно сделать в событии bounds_changed:

google.maps.event.addListener(map, 'bounds_changed', function() {
    $map.css({ height: '500px', width: '500px' }); // back to desired dims
    google.maps.event.trigger(map, 'resize'); // trigger a 'refresh'
    map.setCenter(new google.maps.LatLng(-18.2, 35.1)); // re-center map
    google.maps.event.clearListeners(map, 'bounds_changed'); // don't do this again
});

Вот рабочий пример (протестирован в Firefox и Chrome).

Некоторые оговорки:

  • Чем дальше вы хотите, чтобы люди увеличивали масштаб изображения, тем больше вам нужно будет отображать начальную "временную" карту. Например, если вы хотите разрешить уровень масштабирования 7, вам может потребоваться сделать исходную карту 2000 x 2000 для компенсации. Очевидно, есть проблемы с производительностью при рендеринге большой карты. Как указано в дисперсии, может быть разумным ограничить уровни масштабирования.
  • В связи с изменением размера последней минуты при изменении карты произойдет мерцание. Возможно, вам захочется рассмотреть скрытие/отображение карты с помощью jQuery или, возможно, размещение белого наложения поверх всего, пока карта не закончит повторное определение размера.

Ответ 3

Я смог исправить проблему на этом уровне масштабирования, сделав svg больше, добавив некоторое дополнение и придав отрицательную верхнюю и левую позицию следующим образом:

    .SvgOverlay, .SvgOverlay svg {
        position: absolute;
        top: -250px;
        left: -250px;
        padding: 500px;            
    }

    var svg = layer.append("svg")
          .attr("width", 1000)
          .attr("height", 1000)

Если вы хотите, чтобы ваш пользователь увеличивал масштаб, вам придется увеличить все эти числа. Например, увеличение их в 10 раз, по-видимому, устраняет проблему для всех уровней масштабирования. Тем не менее, вы можете ограничить способность пользователя увеличивать масштаб, так как польза от наложения svg уменьшается при дальнейшем увеличении.

Вот скрипка, демонстрирующая эту идею. http://jsfiddle.net/VHWqq/7/

Изменить: Как указывает Херб, этот подход не работает в Firefox.