Fix zoom animation for v3.32 (#559)

* Use the experimental version, to get the new zoom animation.

* Don't use bounds for rendering in 3.32

* Revert the project() and unproject() methods.

Instead, add a new method fromLatLngToContainerPixel() to geo service.

* No need of setting .exp, that is by default

* Comments explaining the significance of API v3.32

* Add _VERSION to const
This commit is contained in:
Stephen Farrar 2018-04-27 12:48:01 -07:00 committed by Michael Diego
parent aec0c08aae
commit 7877008e17
4 changed files with 53 additions and 39 deletions

View File

@ -34,6 +34,9 @@ const K_GOOGLE_TILE_SIZE = 256;
const K_IDLE_TIMEOUT = 100;
const K_IDLE_CLICK_TIMEOUT = 300;
const DEFAULT_MIN_ZOOM = 3;
// Starting with version 3.32, the maps API calls `draw()` each frame during
// a zoom animation.
const DRAW_CALLED_DURING_ANIMATION_VERSION = 32;
function defaultOptions_(/* maps */) {
return {
@ -566,6 +569,11 @@ export default class GoogleMap extends Component {
this._setLayers(this.props.layerTypes);
// Parse `google.maps.version` to capture the major version number.
const versionMatch = maps.version.match(/^3\.(\d+)\./);
// The major version is the first (and only) captured group.
const mapsVersion = versionMatch && Number(versionMatch[1]);
// render in overlay
const this_ = this;
const overlay = Object.assign(new maps.OverlayView(), {
@ -588,6 +596,10 @@ export default class GoogleMap extends Component {
const panes = this.getPanes();
panes.overlayMouseTarget.appendChild(div);
this_.geoService_.setMapCanvasProjection(
maps,
overlay.getProjection()
);
ReactDOM.unstable_renderSubtreeIntoContainer(
this_,
@ -618,11 +630,8 @@ export default class GoogleMap extends Component {
draw() {
const div = overlay.div;
const overlayProjection = overlay.getProjection();
const bounds = map.getBounds();
const ne = bounds.getNorthEast();
const sw = bounds.getSouthWest();
const ptx = overlayProjection.fromLatLngToDivPixel(
new maps.LatLng(ne.lat(), sw.lng())
overlayProjection.fromContainerPixelToLatLng({ x: 0, y: 0 })
);
// need round for safari still can't find what need for firefox
@ -661,25 +670,29 @@ export default class GoogleMap extends Component {
this_._onZoomAnimationStart();
}
const TIMEOUT_ZOOM = 300;
// If draw() is not called each frame during a zoom animation,
// simulate it.
if (mapsVersion < DRAW_CALLED_DURING_ANIMATION_VERSION) {
const TIMEOUT_ZOOM = 300;
if (
new Date().getTime() - this.zoomControlClickTime_ < TIMEOUT_ZOOM
) {
// there is strange Google Map Api behavior in chrome when zoom animation of map
// is started only on second raf call, if was click on zoom control
// or +- keys pressed, so i wait for two rafs before change state
if (
new Date().getTime() - this.zoomControlClickTime_ < TIMEOUT_ZOOM
) {
// there is strange Google Map Api behavior in chrome when zoom animation of map
// is started only on second raf call, if was click on zoom control
// or +- keys pressed, so i wait for two rafs before change state
// this does not fully prevent animation jump
// but reduce it's occurence probability
raf(() =>
raf(() => {
this_.updateCounter_++;
this_._onBoundsChanged(map, maps);
}));
} else {
this_.updateCounter_++;
this_._onBoundsChanged(map, maps);
// this does not fully prevent animation jump
// but reduce it's occurence probability
raf(() =>
raf(() => {
this_.updateCounter_++;
this_._onBoundsChanged(map, maps);
}));
} else {
this_.updateCounter_++;
this_._onBoundsChanged(map, maps);
}
}
}
});
@ -720,11 +733,8 @@ export default class GoogleMap extends Component {
const div = overlay.div;
const overlayProjection = overlay.getProjection();
if (div && overlayProjection) {
const bounds = map.getBounds();
const ne = bounds.getNorthEast();
const sw = bounds.getSouthWest();
const ptx = overlayProjection.fromLatLngToDivPixel(
new maps.LatLng(ne.lat(), sw.lng())
overlayProjection.fromContainerPixelToLatLng({ x: 0, y: 0 })
);
// need round for safari still can't find what need for firefox
const ptxRounded = detectBrowser().isSafari

View File

@ -265,10 +265,9 @@ export default class GoogleMapMarkers extends Component {
? child.props.latLng
: { lat: child.props.lat, lng: child.props.lng };
const pt = this.props.geoService.project(
latLng,
this.props.projectFromLeftTop
);
const pt = this.props.projectFromLeftTop
? this.props.geoService.fromLatLngToContainerPixel(latLng)
: this.props.geoService.project(latLng);
const stylePtPos = {
left: pt.x,

View File

@ -1,5 +1,3 @@
import isEmpty from '../utils/isEmpty';
const BASE_URL = 'https://maps';
const DEFAULT_URL = `${BASE_URL}.googleapis.com`;
const API_PATH = '/maps/api/js?callback=_$_google_map_initialize_$_';
@ -67,18 +65,11 @@ export default (bootstrapURLKeys, heatmapLibrary) => {
}
}
let params = Object.keys(bootstrapURLKeys).reduce(
const params = Object.keys(bootstrapURLKeys).reduce(
(r, key) => `${r}&${key}=${bootstrapURLKeys[key]}`,
''
);
// if no version is defined, we want to get the release version
// and not the experimental version, to do so, we set v=3.31
// src: https://developers.google.com/maps/documentation/javascript/versions
if (isEmpty(bootstrapURLKeys.v)) {
params += '&v=3.31';
}
const baseUrl = getUrl(bootstrapURLKeys.region);
const libraries = heatmapLibrary ? '&libraries=visualization' : '';

View File

@ -24,6 +24,11 @@ export default class Geo {
this.hasSize_ = true;
}
setMapCanvasProjection(maps, mapCanvasProjection) {
this.maps_ = maps;
this.mapCanvasProjection_ = mapCanvasProjection;
}
canProject() {
return this.hasSize_ && this.hasView_;
}
@ -62,6 +67,15 @@ export default class Geo {
return this.transform_.locationPoint(LatLng.convert(ptLatLng));
}
fromLatLngToContainerPixel(ptLatLng) {
if (this.mapCanvasProjection_) {
const latLng = new this.maps_.LatLng(ptLatLng.lat, ptLatLng.lng);
return this.mapCanvasProjection_.fromLatLngToContainerPixel(latLng);
}
return this.project(ptLatLng, true);
}
getWidth() {
return this.transform_.width;
}