google-maps-ios-utils icon indicating copy to clipboard operation
google-maps-ios-utils copied to clipboard

Maps: calling GMUHeatmapTileLayer.clearTileCache() has no effect in updating heatmap's options such as radius, gradient etc

Open kvog001 opened this issue 3 years ago • 5 comments

Hi, i believe there is a bug when calling clearTileCache() after changing heatmap's properties such as radius etc,. I have installed GoogleMapsUtils (v6.0.1-beta) via Carthage on an M1 machine.

Environment details

M1 machine Xcode 13.1 Carthage 0.38.0 Google-Maps-Utils 6.0.1-beta

Code example

class Heatmap: UIViewController {

  private var mapView: GMSMapView!
  private var heatmapLayer: GMUHeatmapTileLayer!

  override func viewDidLoad() {
    super.viewDidLoad()
    heatmapLayer = GMUHeatmapTileLayer()
    heatmapLayer.map = mapView

     addUISlider(x: 5, y: 80, width: 170, height: 15, minVal: 0.05, maxVal: 10.0, objcFunc: #selector(self.opacitySliderValueDidChange(_:)))
        
     addUISlider(x: 5, y: 120, width: 170, height: 15, minVal: 10, maxVal: 60, objcFunc: #selector(self.radiusSliderValueDidChange(_:)))
        
  }

  // ...

  func addHeatmap() {

    // Get the data: latitude/longitude positions of police stations.
    guard let path = Bundle.main.url(forResource: "police_stations", withExtension: "json") else {
      return
    }
    guard let data = try? Data(contentsOf: path) else {
      return
    }
    guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
      return
    }
    guard let object = json as? [[String: Any]] else {
      print("Could not read the JSON.")
      return
    }

    var list = [GMUWeightedLatLng]()
    for item in object {
      let lat = item["lat"] as! CLLocationDegrees
      let lng = item["lng"] as! CLLocationDegrees
      let coords = GMUWeightedLatLng(
        coordinate: CLLocationCoordinate2DMake(lat, lng),
        intensity: 1.0
      )
      list.append(coords)
    }

    // Add the latlngs to the heatmap layer.
    heatmapLayer.weightedData = list
  }

  private func addUISlider(
                             x: Int,
                             y: Int,
                             width: Int,
                             height: Int,
                             minVal: Float,
                             maxVal: Float,
                             objcFunc: Selector) {
        
        let slider = UISlider(frame:CGRect(x: x, y: y, width: width, height: height))
        slider.minimumValue = minVal
        slider.maximumValue = maxVal
        slider.isContinuous = true
        slider.addTarget(self, action: objcFunc, for: .valueChanged)
        view.addSubview(slider)
    }

    @objc
    func opacitySliderValueDidChange(_ sender: UISlider!) {
        let step: Float = 0.05
        let stepValue = sender.value / step * step
        sender.value = stepValue
        heatmapLayer.opacity = stepValue
        heatmapLayer.clearTileCache()
    }
    
    @objc
    func radiusSliderValueDidChange(_ sender: UISlider!) {
        let step = 1
        let stepValue = Int(sender.value) / step * step
        sender.value = Float(stepValue)
        radius = UInt(stepValue)
        heatmapLayer.radius = radius
        heatmapLayer.clearTileCache()
    }
}

Changing heatmap's opacity shows instantly in the map, even without calling .clearTileCache() afterwards. Calling it in this case only rerenders the tiles and slows down the zoom in/ zoom out experience.

While creating a new heatmap layer with the desired radius -- seems like the change is taken into considerate only in the initialization. Calling .clearTileCache() afterwards just rerenders the tiles without updating aynthing. Same holds for these other options: gradient, minimumZoomIntensity, maximumZoomIntensity.

Thanks!

kvog001 avatar Apr 20 '22 09:04 kvog001

@kvogli Thank you for opening this issue. 🙏 Please check out these other resources that might be applicable:

This is an automated message, feel free to ignore.

jpoehnelt avatar Apr 20 '22 09:04 jpoehnelt

You have to call heatmapLayer.map = yourMapView first

https://github.com/googlemaps/google-maps-ios-utils/issues/154#issuecomment-343846113

Rexios80 avatar Apr 20 '22 16:04 Rexios80

This should probably be documented here: https://developers.google.com/maps/documentation/ios-sdk/utility/heatmap#change-the-dataset

I had the same issue, and the instructions on that site are pretty much just outright incorrect

Rexios80 avatar Apr 20 '22 16:04 Rexios80

You have to call heatmapLayer.map = yourMapView first

#154 (comment)

Thanks for the help! That seems to work only halfway though - the rendering is still quite laggy after updating the radius and not as responsive as compared to changing the opacity. I'm not sure if this is the final solution or there is a better one (possibly a bug may still persist?)

And yes i agree that the documentation needs an update for this section.

kvog001 avatar Apr 20 '22 20:04 kvog001

I see the same behavior on iOS and Android. Web is the only platform that updates instantly.

Rexios80 avatar Apr 20 '22 21:04 Rexios80