mapbox / mapbox-gl-native

Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL
https://mapbox.com/mobile
Other
4.35k stars 1.33k forks source link

Changing MGLFillStyleLayer properties while dragging MGLAnnotationView causes Annotation to "jump" back to start point #16474

Open darylteo opened 4 years ago

darylteo commented 4 years ago

https://www.youtube.com/watch?v=Tt0anMYWf88&feature=youtu.be

Here is a demonstration of the behaviour being seen in an app my team is developing.

When dragging the annotation, we are trying to set the fillOpacity of the underlying polygon to show that it is a valid drop target. However, when setting the fillOpacity, the annotation jumps.

You can see the code we are using is not very far from the example provided.

To ensure that the issue can be isolated to the fillOpacity change, I isolated the call with a 1 second timer delay, and the video demonstrates that the issue occurs immediately after 1 second when the highlight appears.

Our team reports that Android does not have this issue.

Thank you very much for your support.


        let point = liveStock.frame.center

        if let destinationPaddockVm = self?.getPaddock(inPoint: point),
          let destinationPaddock = destinationPaddockVm.paddock {
          print(destinationPaddock.name)
        }

        guard let sourcePaddock = sourcePaddockVm.paddock,
          let destinationPaddockVm = self?.getPaddock(inPoint: point),
          let destinationPaddock = destinationPaddockVm.paddock,
          sourcePaddock.id != destinationPaddock.id,
          self?.higlightedPaddockId != destinationPaddock.id else {
          return
        }

        guard let layer = self?.mapView.style?.layer(withIdentifier:"region") as? MGLFillStyleLayer else {
          fatalError("Could not cast to specified MGLFillStyleLayer")
        }

        if let features = self?.mapView.visibleFeatures(at: point, styleLayerIdentifiers: Set(["region"])),
          let feature = features.first,
          let paddockId = feature.attribute(forKey: "PADDOCK_ID") as? Int,
          paddockId != self?.higlightedPaddockId {
          self?.higlightedPaddockId = paddockId
          print("ONCE")

          DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            layer.fillOpacity = NSExpression(format: "TERNARY(PADDOCK_ID = %d, 1, 0)", paddockId)
          }
        }

Steps to reproduce

  1. https://docs.mapbox.com/ios/maps/examples/select-layer/ follow this tutorial
  2. Instead of "tap" allow annotations to be dragged
  3. Change fillopacity while dragging.

Expected behavior

Polygon under the dragged annotation should be highlighted, and annotation remains under touch point.

Actual behavior

Annotation being dragged jumps back to start point.

Configuration

Mapbox SDK versions: 5.9.0 iOS/macOS versions: Catalina 10.15.4 Device/simulator models: iPhone 11 Pro Max Xcode version: 11.4.1

darylteo commented 4 years ago

Oops the video was set to private I have fixed this.

Here is another video showing another global timer firing every 2 seconds, causing the dragged annotation to reset each time.

      Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { timer in
        let randomNumber = Double.random(in: 1...100) / 100.0

        regionLayer.fillOpacity = NSExpression(forConstantValue: randomNumber)
      }

https://youtu.be/tPiByAjQRzo

Based on analysis of code, it looks like any change to the layer invalidates the entire frontend

https://github.com/mapbox/mapbox-gl-native/blob/04edb1dbaa1c660f830f80275dc25dc700d29f1a/platform/glfw/glfw_renderer_frontend.cpp#L26

And when redrawing, the frontend does not take into account that an annotation is currently being dragged and redraws the annotation at it's original point.

darylteo commented 4 years ago

We have considered using MGLSymbolStyleLayer to display the annotations, so that maybe the layer will not be affected by rendering on other layers, but alas this method does not support Drag Drop out of the box. And the Annotation itself is quite complex (with several different types of indicators). So we do want to stick to MGLAnnotationView and UIViews.