Animate camera to position and set panning in google maps

后端 未结 1 494
广开言路
广开言路 2021-01-21 12:03

I\'m trying to achieve similar to how navigation in google maps works, check the below image for reference. In google maps, the marker looks to be at a static location except th

相关标签:
1条回答
  • 2021-01-21 12:39

    The code is completely implemented in the onLocationChanged but as documented some of it can be extracted during init.

    Essentially what is being done is a shadow target is computed from the current location using the distance derived from a screen pixel offset, extrapolated using a computed bearing from last location.

    In the screen recording (below), the green circle represents the current location (also depicted by the map location dot) and the blue circle represents the shadow target which is always in the center of the screen as a result of being the target of the map animate.

    Here's a quick drawing of concept:

    And the code (with a screen recording below):

    @Override
    public void onLocationChanged(Location location) {
    
        // First point processing
        if (lastLocation == null) {
    
            // save last location
            lastLocation = location;
    
            // initial camera
            CameraPosition.Builder b = CameraPosition.builder().
                    zoom(15.0F).
                    target(new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()));
            CameraUpdate cu = CameraUpdateFactory.newCameraPosition(b.build());
            mMap.animateCamera(cu);
            return;
        }
    
        // subsequent updates
    
        LatLng oldPos = new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude());
        LatLng newPos = new LatLng(location.getLatitude(), location.getLongitude());
    
        // ignore very small position deviations (prevents wild swinging)
        double d = SphericalUtil.computeDistanceBetween(oldPos, newPos);
        if (d < 10) {
            return;
        }
    
    
        // compute our own bearing (do not use location bearing)
        double bearing = SphericalUtil.computeHeading(oldPos, newPos);
    
        //-----------------------------------------------
        // Next section really only needs to be done once
    
        // Compute distance of pixels on screen using some desirable "offset"
    
        Projection p = mMap.getProjection();
        Point  bottomRightPoint = p.toScreenLocation(p.getVisibleRegion().nearRight);
        Point center = new Point(bottomRightPoint.x/2,bottomRightPoint.y/2);
        Point offset = new Point(center.x, (center.y + 300));
    
        LatLng centerLoc = p.fromScreenLocation(center);
        LatLng offsetNewLoc = p.fromScreenLocation(offset);
    
        // this computed value only changes on zoom
        double offsetDistance = SphericalUtil.computeDistanceBetween(centerLoc, offsetNewLoc);
        //-----------------------------------------------
    
    
        // Compute shadow target position from current position (see diagram)
        LatLng shadowTgt = SphericalUtil.computeOffset(newPos,offsetDistance,bearing);
    
        // update circles
        if (centerCircle != null) {
            centerCircle.setCenter(shadowTgt);
        } else {
            centerCircle = mMap.addCircle(new CircleOptions().strokeColor(Color.BLUE).center(shadowTgt).radius(50));
        }
        if (carCircle != null) {
            carCircle.setCenter(newPos);
        } else {
            carCircle = mMap.addCircle(new CircleOptions().strokeColor(Color.GREEN).center(newPos).radius(50));
        }
    
    
        // update camera
    
        CameraPosition.Builder b = CameraPosition.builder();
        b.zoom(15.0F);
        b.bearing((float)(bearing));
        b.target(shadowTgt);
        CameraUpdate cu = CameraUpdateFactory.newCameraPosition(b.build());
        mMap.animateCamera(cu);
    
        // save location as last for next update
        lastLocation = location;
    }
    

    Notes:

    • When the zoom changes, the offsetDistance needs to be recomputed. (But as noted it does not need to be done every location changed.)
    • Bearing is shown in concept diagram as 0-360 but is actually -180-180.
    • As you can see, most of the work is done in the SphericalUtil class.

    0 讨论(0)
提交回复
热议问题