Вопрос по javascript, google-maps-api-3 – Как сместить центральную точку в гугл картах api V3

71

У меня есть карта Google с полупрозрачной панелью, покрывающей часть области. Я хотел бы отрегулировать центральную точку карты, чтобы учесть часть карты, которая частично скрыта. Смотрите изображение ниже. В идеале место перекрестья и булавки должно быть в центре карты.

Я надеюсь, что в этом есть смысл.

Причина проста: при масштабировании необходимо центрировать карту по перекрестию, а не на 50%, 50%. Также я буду наносить на карту маркеры и последовательно перемещаться по ним. Когда карта центрируется на них, они также должны быть в смещенной позиции.

Заранее спасибо!

Mockup of the map I am building

Вы должны будете уточнить свой вопрос. Что учитывает ту часть карты, которая частично скрыта? имею в виду? И что значит «а не на 50%, на 50%» имею в виду? Хотите помочь, но не можете понять, чего вы пытаетесь достичь. Sean Mickey
Привет, Можете ли вы дать URL рабочего примера, потому что мне нужна помощь для создания движущейся линии уловки вместе с линией маршрута SP Singh

Ваш Ответ

9   ответов
4

Старый вопрос, я знаю. Но как насчет более CSS-ориентированного способа?

http://codepen.io/eddyblair/pen/VjpNQQ

То, что я сделал, было:

  • Wrap the map and overlay in a container with overflow: hidden

  • Overlaid the overlay with position: absolute

  • Extended the map's apparent width by the overlay width (plus any padding and offset) by setting a negative margin-left.

  • Then in order to comply with https://www.google.com/permissions/geoguidelines/attr-guide.html positioned the widgets and attribution divs.

Таким образом, центр карты находится на одной линии с центром желаемой области. JS - это просто стандартная карта JS.

Перестановка иконок для просмотра улиц - упражнение для читателя :)


Если вы хотите наложение слева, просто измените строку24 margin-left вmargin-right и строка 32right вleft.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
6

Эндрю ответ. Однако в моем случае map.getBounds () продолжал возвращать неопределенный. Я исправил это ожидание события bounds_changed иthen вызовите функцию, чтобы сместить центр. Вот так:

var center_moved = false;
google.maps.event.addListener(map, 'bounds_changed', function() {
  if(!center_moved){
    offsetCenter(map.getCenter(), 250, -200);
    center_moved = true; 
  }
});
Error: User Rate Limit Exceeded
1

Другой подход к смещению маршрута или группы маркеров можно найти здесь:

https://stackoverflow.com/a/26192440/1238965

Он все еще используетfromLatLngToPoint() метод, описанный в ответе Эндрю Лича.

Error: User Rate Limit Exceeded
10

Вот более простой способ, который может быть более полезен в адаптивном дизайне, поскольку вы можете использовать проценты вместо пикселей. Нет мировых координат, нет точек привязки к точкам!

var center;  // a latLng
var offsetX = 0.25; // move center one quarter map width left
var offsetY = 0.25; // move center one quarter map height down

var span = map.getBounds().toSpan(); // a latLng - # of deg map spans

var newCenter = { 
    lat: center.lat() + span.lat()*offsetY,
    lng: center.lng() + span.lng()*offsetX
};

map.panTo(newCenter);  // or map.setCenter(newCenter);
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
62

Также взгляните на функцию panBy (x: number, y: number) на объекте карт.

В документации упоминается об этой функции:

Changes the center of the map by the given distance in pixels. If the distance is less than both the width and height of the map, the transition will be smoothly animated. Note that the map coordinate system increases from west to east (for x values) and north to south (for y values).

Просто используйте это так:

mapsObject.panBy(200, 100)
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
74

Это не особенно сложно, когда вы найдетесоответствующий предыдущий ответ.

Вам нужно преобразовать центр карты в его мировые координаты, найти, где карта должна быть центрирована, чтобы поместитьapparent центр, где вы хотите, и перецентрировать карту, используяreal центр.

API всегда будет центрировать карту по центру области просмотра, поэтому вы должны быть осторожны, если используетеmap.getCenter() как это вернет реальный центр, а не видимый центр. Я полагаю, что было бы возможно перегрузить API, чтобы егоgetCenter() а такжеsetCenter() методы заменены, но я этого не сделал.

Код ниже.Пример онлайн, В этом примере нажатие кнопки сдвигает центр карты (там находится дорожная развязка) вниз на 100 пикселей и влево на 200 пикселей.

function offsetCenter(latlng, offsetx, offsety) {

    // latlng is the apparent centre-point
    // offsetx is the distance you want that point to move to the right, in pixels
    // offsety is the distance you want that point to move upwards, in pixels
    // offset can be negative
    // offsetx and offsety are both optional

    var scale = Math.pow(2, map.getZoom());

    var worldCoordinateCenter = map.getProjection().fromLatLngToPoint(latlng);
    var pixelOffset = new google.maps.Point((offsetx/scale) || 0,(offsety/scale) ||0);

    var worldCoordinateNewCenter = new google.maps.Point(
        worldCoordinateCenter.x - pixelOffset.x,
        worldCoordinateCenter.y + pixelOffset.y
    );

    var newCenter = map.getProjection().fromPointToLatLng(worldCoordinateNewCenter);

    map.setCenter(newCenter);

}
Error: User Rate Limit Exceededmap.panBy(250, 0);
Error: User Rate Limit Exceededmap.setCenter()Error: User Rate Limit Exceededmap.setCenter().
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceedednwError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded will
3

Просто нашел другое простейшее решение. Если вы используете метод fitBounds, вы можете передать ему второй необязательный аргумент. Этот аргумент является отступом, который будет учитываться при подборе границ.

// pass single side:
map.fitBounds(bounds, { left: 1000 })

// OR use Number:
map.fitBounds(bounds, 20)

Дальнейшее чтение:официальные документы.

8

Вот пример решения проблемы с использованиемpanBy() метод API карт:http://jsfiddle.net/upsidown/2wej9smf/

3

После тщательного поиска я не смог найти способ сделать это, в том числе с увеличением. К счастьюумный парень понял это. Также естьвозиться здесь

'use strict';

const TILE_SIZE = {
  height: 256,
  width: 256
}; // google World tile size, as of v3.22
const ZOOM_MAX = 21; // max google maps zoom level, as of v3.22
const BUFFER = 15; // edge buffer for fitting markers within viewport bounds

const mapOptions = {
  zoom: 14,
  center: {
    lat: 34.075328,
    lng: -118.330432
  },
  options: {
    mapTypeControl: false
  }
};
const markers = [];
const mapDimensions = {};
const mapOffset = {
  x: 0,
  y: 0
};
const mapEl = document.getElementById('gmap');
const overlayEl = document.getElementById('overlay');
const gmap = new google.maps.Map(mapEl, mapOptions);

const updateMapDimensions = () => {
  mapDimensions.height = mapEl.offsetHeight;
  mapDimensions.width = mapEl.offsetWidth;
};

const getBoundsZoomLevel = (bounds, dimensions) => {
  const latRadian = lat => {
    let sin = Math.sin(lat * Math.PI / 180);
    let radX2 = Math.log((1 + sin) / (1 - sin)) / 2;
    return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2;
  };
  const zoom = (mapPx, worldPx, fraction) => {
    return Math.floor(Math.log(mapPx / worldPx / fraction) / Math.LN2);
  };
  const ne = bounds.getNorthEast();
  const sw = bounds.getSouthWest();
  const latFraction = (latRadian(ne.lat()) - latRadian(sw.lat())) / Math.PI;
  const lngDiff = ne.lng() - sw.lng();
  const lngFraction = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff) / 360;
  const latZoom = zoom(dimensions.height, TILE_SIZE.height, latFraction);
  const lngZoom = zoom(dimensions.width, TILE_SIZE.width, lngFraction);
  return Math.min(latZoom, lngZoom, ZOOM_MAX);
};

const getBounds = locations => {
  let northeastLat;
  let northeastLong;
  let southwestLat;
  let southwestLong;
  locations.forEach(function(location) {
    if (!northeastLat) {
      northeastLat = southwestLat = location.lat;
      southwestLong = northeastLong = location.lng;
      return;
    }
    if (location.lat > northeastLat) northeastLat = location.lat;
    else if (location.lat < southwestLat) southwestLat = location.lat;
    if (location.lng < northeastLong) northeastLong = location.lng;
    else if (location.lng > southwestLong) southwestLong = location.lng;
  });
  const northeast = new google.maps.LatLng(northeastLat, northeastLong);
  const southwest = new google.maps.LatLng(southwestLat, southwestLong);
  const bounds = new google.maps.LatLngBounds();
  bounds.extend(northeast);
  bounds.extend(southwest);
  return bounds;
};

const zoomWithOffset = shouldZoom => {
  const currentzoom = gmap.getZoom();
  const newzoom = shouldZoom ? currentzoom + 1 : currentzoom - 1;
  const offset = {
    x: shouldZoom ? -mapOffset.x / 4 : mapOffset.x / 2,
    y: shouldZoom ? -mapOffset.y / 4 : mapOffset.y / 2
  };
  const newCenter = offsetLatLng(gmap.getCenter(), offset.x, offset.y);
  if (shouldZoom) {
    gmap.setZoom(newzoom);
    gmap.panTo(newCenter);
  } else {
    gmap.setCenter(newCenter);
    gmap.setZoom(newzoom);
  }
};

const setMapBounds = locations => {
  updateMapDimensions();
  const bounds = getBounds(locations);
  const dimensions = {
    width: mapDimensions.width - mapOffset.x - BUFFER * 2,
    height: mapDimensions.height - mapOffset.y - BUFFER * 2
  };
  const zoomLevel = getBoundsZoomLevel(bounds, dimensions);
  gmap.setZoom(zoomLevel);
  setOffsetCenter(bounds.getCenter());
};

const offsetLatLng = (latlng, offsetX, offsetY) => {
  offsetX = offsetX || 0;
  offsetY = offsetY || 0;
  const scale = Math.pow(2, gmap.getZoom());
  const point = gmap.getProjection().fromLatLngToPoint(latlng);
  const pixelOffset = new google.maps.Point((offsetX / scale), (offsetY / scale));
  const newPoint = new google.maps.Point(
    point.x - pixelOffset.x,
    point.y + pixelOffset.y
  );
  return gmap.getProjection().fromPointToLatLng(newPoint);
};

const setOffsetCenter = latlng => {
  const newCenterLatLng = offsetLatLng(latlng, mapOffset.x / 2, mapOffset.y / 2);
  gmap.panTo(newCenterLatLng);
};

const locations = [{
  name: 'Wilshire Country Club',
  lat: 34.077796,
  lng: -118.331151
}, {
  name: '301 N Rossmore Ave',
  lat: 34.077146,
  lng: -118.327805
}, {
  name: '5920 Beverly Blvd',
  lat: 34.070281,
  lng: -118.331831
}];

locations.forEach(function(location) {
  let marker = new google.maps.Marker({
    position: new google.maps.LatLng(location.lat, location.lng),
    title: location.name
  })
  marker.setMap(gmap);
  markers.push(marker);
});

mapOffset.x = overlayEl.offsetWidth;

document.zoom = bool => zoomWithOffset(bool);
document.setBounds = () => setMapBounds(locations);
section {
  height: 180px;
  margin-bottom: 15px;
  font-family: sans-serif;
  color: grey;
}
figure {
  position: relative;
  margin: 0;
  width: 100%;
  height: 100%;
}
figcaption {
  position: absolute;
  left: 15px;
  top: 15px;
  width: 120px;
  padding: 15px;
  background: white;
  box-shadow: 0 2px 5px rgba(0, 0, 0, .3);
}
gmap {
  display: block;
  height: 100%;
}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js"></script>

<section>
  <figure>
    <gmap id="gmap"></gmap>
    <figcaption id="overlay">
      <h4>Tile Overlay</h4>
      <p>To be avoided by the map!</p>
    </figcaption>
  </figure>
</section>
<button onclick="zoom(true)">zoom in</button>
<button onclick="zoom(false)">zoom out</button>
<button onclick="setBounds()">set bounds</button>

Похожие вопросы