Карты Google с наложением d3. js (v5) - PullRequest
1 голос
/ 16 июня 2020

Я работаю над проектом, в котором у меня есть JSON, который выглядит так:

 [
    {
        "lat": 53.1521596106757,
        "lon": -0.486577431632087,
        "size": 3598,
        "field": "TestField",
        "variety": "TestVariety",
        "count": 67
    },
    {
        "lat": 53.1521596106757,
        "lon": -0.486287281632087,
        "size": 4077,
        "field": "TestField",
        "variety": "TestVariety",
        "count": 73
    }
]

Я пытаюсь добавить текст с помощью count, но не вижу ожидаемых результатов используя следующий код:

let testField = new google.maps.LatLng(53.1519, -0.4895);

const map = new google.maps.Map(d3.select('#map').node(), {
  zoom: 17,
  center: testField,
  mapTypeId: 'satellite',
  streetViewControl: false,
  mapTypeControl: false,
});

//colour scale
// const colorScale = d3.scaleSequential(d3.interpolateBlues);    

d3.json('/small_example.json')
  .then(data => {

    let countInfo = data.map(function (testVariety) {
      return testVariety.count;
    })

    // colorScale.domain(data.map(d => d.countInfo))

    //create overlay
    const overlay = new google.maps.OverlayView();

    // Add the container when the overlay is added to the map.
    overlay.onAdd = function () {
      const layer = d3.select(this.getPanes().overlayLayer).append('div')
        .attr('class', 'panes');

      // Draw each marker as a separate SVG element.
      overlay.draw = function () {
        const projection = this.getProjection(),
          padding = 10;

        const marker = layer.selectAll('svg')
          .data(d3.entries(data))
          .each(transform) // update existing markers
          .enter().append('svg')
          .each(transform)
          .attr('class', 'marker')

        //add a rect
        marker.append('rect')
          .attr('height', 15)
          .attr('width', 15)
        // .style('fill', d => colorScale(d.count));
        // .style('fill', function(d) {return d.count})

        let countInfo = data.map(function (testVariety) {
          return testVariety.count;
        })

        countInfo.forEach(element => {
          //add lable
          marker.append('text')
            .attr('x', padding + 7)
            .attr('y', padding)
            .attr('dy', '.31em')
            .each(transform)
            .text(function (d) {
              return element
            });
          console.log(element)
        });

        function transform(d) {
          d = new google.maps.LatLng(d.value.lat, d.value.lon);
          d = projection.fromLatLngToDivPixel(d);
          return d3.select(this)
            .style('left', (d.x - padding) + 'px')
            .style('top', (d.y - padding) + 'px')
        }
      };
    };

    // Bind overlay to the map
    overlay.setMap(map);
  });

console.log (element) выводит результаты, которые я хочу видеть, но я не могу понять, как отобразить их на экране.

Я чувствую, что приближаюсь, но мне нужна рука, чтобы переступить черту.

1 Ответ

1 голос
/ 17 июня 2020

Старайтесь всегда делать свой пример сниппетом там, где вы можете, чтобы он был минимально воспроизводимым примером, включая данные, версии библиотек, все теги скрипта и т. Д. c.

Но для вашего примера фрейм внешнего кода с перекрестным происхождением не будет работать во фрагменте переполнения стека (по крайней мере, не всегда для меня с Chrome). Итак, в этом случае попробуйте использовать что-то вроде codePen или другого сайта типа песочницы для кода.

Мой полный пример ниже (но он не работает последовательно в переполнении стека для меня) или доступен (работает) на codePen: https://codepen.io/Alexander9111/pen/mdVOmJL

Самая важная вещь, которую вы пропустили, это эта часть:

До:

const marker = layer.selectAll('svg')
          .data(d3.entries(data)) //tansform object to array
          .each(transform) // update existing markers
          .enter().append('svg')
          .each(transform)
          .attr('class', 'marker')

после:

const marker = layer.selectAll("svg")
          .data(data) //no need to transform array of objects
          .each(transform) // update existing markers
          .enter().append("svg")
          .each(transform)
          .attr("class", "marker");

Взгляните на пример кода, на который вы снова ссылались: https://bl.ocks.org/mbostock/899711

Их данные имеют следующий вид. Это означает, что это объект, в котором каждый ключ представляет собой 4-буквенный код, а соответствующее значение представляет собой массив формы [lat, lon, longName, someArr]:

{
  "KMAE":[-120.12,36.98,"MADERA MUNICIPAL AIRPORT",[26,1,2,5,6,3,2,1,2,7,29,12,3]],
  "KSJC":[-121.92,37.37,"SAN JOSE INTERNATIONAL  AIRPORT",[28,1,1,1,6,10,5,3,2,4,14,21,7]],
  ...
}

В то время как ваши данные имеют следующую форму. Это означает, что это массив объектов, каждый с ключами для широты, долготы, поля и т. Д. c. и соответствующие значения, присвоенные каждому из этих свойств для каждого объекта:

[
    {
        "lat": 53.1521596106757,
        "lon": -0.486577431632087,
        "size": 3598,
        "field": "TestField",
        "variety": "TestVariety",
        "count": 67
    },
    {
        "lat": 53.1521596106757,
        "lon": -0.486287281632087,
        "size": 4077,
        "field": "TestField",
        "variety": "TestVariety",
        "count": 73
    },
    ...
];

Итак, хотя в примере, на который вы ссылались, данные необходимо было преобразовать с помощью d3.entries(data), ваши данные уже были массивом, поэтому вы не нужно было преобразовывать его из объекта в массив, вы можете просто применить данные напрямую.

// Create the Google Map…
const map = new google.maps.Map(d3.select("#map").node(), {
  zoom: 7,
  center: new google.maps.LatLng(53.5, -0.466),
  mapTypeId: google.maps.MapTypeId.TERRAIN
});

// Load the field data. When the data comes back, create an overlay.
//this is commented our for example purposes, and data is declared directly above
//d3.json("/small_example.json", function(error, data) {
  //if (error) throw error;

  const overlay = new google.maps.OverlayView();

  // Add the container when the overlay is added to the map.
  overlay.onAdd = function() {
    const layer = d3.select(this.getPanes().overlayLayer).append("div")
        .attr("class", "stations");

    // Draw each marker as a separate SVG element.
    // We could use a single SVG, but what size would it have?
    overlay.draw = function() {
      const projection = this.getProjection(),
          padding = 10;

      const marker = layer.selectAll("svg")
          .data(data)
          .each(transform) // update existing markers
        .enter().append("svg")
          .each(transform)
          .attr("class", "marker");

      // Add a circle.
      marker.append("circle")
          .attr("r", 4.5)
          .attr("cx", padding)
          .attr("cy", padding);

      // Add a label.
      marker.append("text")
          .attr("x", padding + 7)
          .attr("y", padding)
          .attr("dy", ".31em")
          .text(function(d) { return d.field; });

      function transform(d) {
        d = new google.maps.LatLng(d.lat, d.lon);
        d = projection.fromLatLngToDivPixel(d);
        return d3.select(this)
            .style("left", (d.x - padding) + "px")
            .style("top", (d.y - padding) + "px");
      }
    };
  };

  // Bind our overlay to the map…
  overlay.setMap(map);
//this closing bracket pair is commented out, while d3.json() is not in use: 
//});
html, body, #map {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.stations, .stations svg {
  position: absolute;
}

.stations svg {
  width: 60px;
  height: 20px;
  padding-right: 100px;
  font: 10px sans-serif;
}

.stations circle {
  fill: brown;
  stroke: black;
  stroke-width: 1.5px;
}
<script src="//maps.google.com/maps/api/js?sensor=true"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="map"></div>

<script id="initData">
const data = [
    {
		"lat": 53.1521596106757,
		"lon": -0.486577431632087,
		"size": 3598,
		"field": "TestField",
		"variety": "TestVariety",
		"count": 67
	},
	{
		"lat": 53.1521596106757,
		"lon": -0.486287281632087,
		"size": 4077,
		"field": "TestField",
		"variety": "TestVariety",
		"count": 73
	}
];
</script>

Выход:

enter image description here

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