Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable control of Google Maps Marker tracksViewChanges property. #1705

Merged

Conversation

heysailor
Copy link
Contributor

@heysailor heysailor commented Oct 16, 2017

Fixes issue #1031, enabling use of custom marker images and views in
Google Maps on iOS and android.

As detailed in the Google Maps Marker documentation (kudos to
@hughvidos), map markers track view changes by default. This has meant
however that custom marker images or views on iOS and android, when
using Google Maps, cause high continuous CPU load.

The recommended use of tracksViewChanges is to enable when the marker
is being rendered or animated, then to disable it.

An example of use of tracksViewChanges would be to set it to false once
onMapReady has fired. This can be accomplished by toggling a state
property (e.g. initialized), and passing it to the child map markers
in their tracksViewChanges prop. Markers would then render correctly
on map load; CPU use falls off once the tracking ceases.

...
constructor(props) {
  super(props);
  this.state = {
    initialized: false,
  };
}
...
onMapReady = () => {
  this.setState({ initialized: true });
};
...
 render() {
   return (
    <MapView
      provider={PROVIDER_GOOGLE}
      ...
      onMapReady={this.onMapReady}
      ...
      >
        <Marker
          coordinate={...}
          tracksViewChanges={!this.state.initialized}
        />
     </MapView>
  );
 ...

Fixes issue react-native-maps#1031, enabling use of custom marker images and views in
Google Maps on iOS and android.

As detailed in the Google Maps Marker documentation (kudos to
@hughvidos), map markers track view changes by default. This has meant
however that custom marker images or views on iOS and android, when
using Google Maps, cause high continuous CPU load.

The recommended use of tracksViewChanges is to enable when the marker
is being rendered or animated, then to disable it.

An example of use of tracksViewChanges would be to set it to false once
onMapReady has fired. This can be accomplished by toggling a state
property (e.g. `initialized`), and passing it to the child map markers
in their `tracksViewChanges` prop. Markers would then render correctly
on map load; CPU use falls off once the tracking ceases.
@compojoom
Copy link
Contributor

@heysailor - thanks for your pull request! I just tested it and it really helps to lower the CPU load on iOS.

Just a note to others:

  • In my case I didn't need to have my markers move around once the map is loaded, but I had a onPress event that would render a bigger Marker. This wasn't working when tracksViewChanges is set to false. This is normal behavior and is described in the docs as well:

To decide when to set the tracksViewChanges property, you should weigh up performance considerations against the advantages of having the marker redrawn automatically. For example:

If you have a series of changes to make, you can change the property to YES then back to NO.
When an animation is running or the contents are being loaded asynchronously, you should keep the property set to YES until the actions are complete.

https://developers.google.com/maps/documentation/ios-sdk/marker#customize_the_marker_image

What I did in my case was to set the trackViewChanges to true in the Marker's class componentWillReceiveProps. And then to set it to false in the componentDidUpdate. I also had to use a timeout in the componentDidUpdate, because if you set it immediately tracksViewChanges stops the rendering of the marker - so depending on how many ms you got to render you could either finish with a fully rendered marker or partially rendered marker.

The only thing I wonder about is - why we don't have to do all this things on googleMaps for android...

@danielgindi
Copy link
Contributor

This is quite an important PR. I hope it gets merged soon.

@wbyoung
Copy link
Contributor

wbyoung commented Sep 14, 2018

A note about this should probably also be included in the docs.

@slorber
Copy link
Contributor

slorber commented Dec 12, 2018

Hey,

If we have an Animated marker with a native driver animation, does this still apply?
What is the recommended way to run a spring/timing animation on a marker, using native driver and best performances?

Using tracksViewChanges=false seems to disable native driver animations

I tried the following and it didn't work, any idea?

    const scale = computeRiskAreaMarkerScale(this.state.region)
      this.setState({ markersTracksViewChanges: true }, () => {
        Animated.spring(this.riskAreaMarkerScaleAnimated, {
          toValue: scale,
          stiffness: 150,
          damping: 20,
          useNativeDriver: true
        }).start(result => {
          if (result.finished) {
            this.setState({ markersTracksViewChanges: false })
          }
        })
      })

@EskelCz
Copy link

EskelCz commented Aug 21, 2019

@heysailor Is there a way to update the marker manually, when tracksViewChanges is set to false? That would simplify things a lot.

@heysailor
Copy link
Contributor Author

heysailor commented Aug 21, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants