【问题标题】:How to make ripple around circle image in google map Custom marker?如何在谷歌地图自定义标记中围绕圆形图像制作波纹?
【发布时间】:2018-02-01 09:11:06
【问题描述】:

这可能是个愚蠢的问题,但我找不到任何关于这个问题的先前答案的解决方案现在让我发布我的问题,我需要在谷歌地图标记中围绕圆形图像产生涟漪效应,现在让我发布我尝试过的内容到目前为止:

  @Override
    public void onLocationChanged(final Location location) {
        mLastLocation=location;
        GradientDrawable d = new GradientDrawable();
        d.setShape(GradientDrawable.OVAL);
        d.setSize(500,500);
        d.setColor(0x555751FF);
        d.setStroke(5, Color.TRANSPARENT);

        Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth()
                , d.getIntrinsicHeight()
                , Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(bitmap);
        d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        d.draw(canvas);
        final int radius = 100;
        final GroundOverlay circle = mMap.addGroundOverlay(new GroundOverlayOptions()
                .position(new LatLng(location.getLatitude(),location.getLongitude()), 2 * radius).image(BitmapDescriptorFactory.fromBitmap(createMarker(TrackingActivity.this,new LatLng(location.getLatitude(),location.getLongitude())))));
        ValueAnimator valueAnimator = new ValueAnimator();
        valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        valueAnimator.setRepeatMode(ValueAnimator.RESTART);
        valueAnimator.setIntValues(0, radius);
        valueAnimator.setDuration(3000);
        valueAnimator.setEvaluator(new IntEvaluator());
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float animatedFraction = valueAnimator.getAnimatedFraction();
                    circle.setTransparency(animatedFraction);
              //  circle.setDimensions(animatedFraction * radius * 2);
            }
        });
        valueAnimator.start();
        //       mMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(),location.getLongitude())).icon(BitmapDescriptorFactory.fromBitmap(createMarker(this,new LatLng(location.getLatitude(),location.getLongitude())))));
        closeDialog(); 


   public  Bitmap createMarker(Context context, LatLng point) {
        int px = context.getResources().getDimensionPixelSize(R.dimen.map_marker_diameter);
        View markerView = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.circle_imgview, null);
        markerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        markerView.layout(0, 0, px, px);
        markerView.buildDrawingCache();
        CircleImageView bedNumberTextView = markerView.findViewById(R.id.circleimg);
        Bitmap mDotMarkerBitmap = Bitmap.createBitmap(px, px, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mDotMarkerBitmap);
           Picasso.with(this).load("https://fww").into(bedNumberTextView);
        markerView.draw(canvas);
        return mDotMarkerBitmap;
    }
}

上面的代码使我的整个圆形图像产生波纹,但我只想在我的圆形图像周围产生波纹,我该如何实现这一点。即使我尝试使用第三方波纹动画并将我的图像包装在该动画中,但它对我如何才能实现这个朋友不起作用。提前致谢!!

【问题讨论】:

    标签: android google-maps marker


    【解决方案1】:

    试试这个代码。这很容易实现。 我希望这段代码对你有所帮助。

    MapRipple.class

    public class MapRipple {
        private GoogleMap mGoogleMap;
        private LatLng mLatLng, mPrevLatLng;
        private BitmapDescriptor mBackgroundImageDescriptor;  
        private float mTransparency = 0.5f;                  
        private volatile double mDistance = 100;             
        private int mNumberOfRipples = 1;                    
        private int mFillColor = Color.TRANSPARENT;           
        private int mStrokeColor = Color.BLACK;               
        private int mStrokeWidth = 5;                       
        private long mDurationBetweenTwoRipples = 1000;      
        private long mRippleDuration = 2000;                 
        private ValueAnimator mAnimators[];
        private Handler mHandlers[];
        private GroundOverlay mGroundOverlays[];
        private GradientDrawable mBackground;
        private boolean isAnimationRunning = false;
    
        public MapRipple(GoogleMap googleMap, LatLng latLng, Context context) {
            mGoogleMap = googleMap;
            mLatLng = latLng;
            mPrevLatLng = latLng;
            mBackground = (GradientDrawable) ContextCompat.getDrawable(context, R.drawable.map_background);
            mAnimators = new ValueAnimator[4];
            mHandlers = new Handler[4];
            mGroundOverlays = new GroundOverlay[4];
        }
    
    
        public MapRipple withTransparency(float transparency) {
            mTransparency = transparency;
            return this;
        }
    
    
        public MapRipple withDistance(double distance) {
    
            mDistance = distance;
            return this;
        }
    
    
        public MapRipple withLatLng(LatLng latLng) {
            mPrevLatLng = mLatLng;
            mLatLng = latLng;
            return this;
        }
    
    
        public MapRipple withNumberOfRipples(int numberOfRipples) {
            if (numberOfRipples > 4 || numberOfRipples < 1) {
                numberOfRipples = 4;
            }
            mNumberOfRipples = numberOfRipples;
            return this;
        }
    
    
        public MapRipple withFillColor(int fillColor) {
            mFillColor = fillColor;
            return this;
        }
    
    
        public MapRipple withStrokeColor(int strokeColor) {
            mStrokeColor = strokeColor;
            return this;
        }
    
    
        @Deprecated
        public void withStrokewidth(int strokeWidth) {
            mStrokeWidth = strokeWidth;
        }
    
    
        public MapRipple withStrokeWidth(int strokeWidth) {
            mStrokeWidth = strokeWidth;
            return this;
        }
    
    
        public MapRipple withDurationBetweenTwoRipples(long durationBetweenTwoRipples) {
            mDurationBetweenTwoRipples = durationBetweenTwoRipples;
            return this;
        }
    
    
        public boolean isAnimationRunning() {
            return isAnimationRunning;
        }
    
    
        public MapRipple withRippleDuration(long rippleDuration) {
            mRippleDuration = rippleDuration;
            return this;
        }
    
        private final Runnable mCircleOneRunnable = new Runnable() {
            @Override
            public void run() {
                mGroundOverlays[0] = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
                        .position(mLatLng, (int) mDistance)
                        .transparency(mTransparency)
                        .image(mBackgroundImageDescriptor));
                startAnimation(0);
            }
        };
    
        private final Runnable mCircleTwoRunnable = new Runnable() {
            @Override
            public void run() {
                mGroundOverlays[1] = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
                        .position(mLatLng, (int) mDistance)
                        .transparency(mTransparency)
                        .image(mBackgroundImageDescriptor));
                startAnimation(1);
            }
        };
    
        private final Runnable mCircleThreeRunnable = new Runnable() {
            @Override
            public void run() {
                mGroundOverlays[2] = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
                        .position(mLatLng, (int) mDistance)
                        .transparency(mTransparency)
                        .image(mBackgroundImageDescriptor));
                startAnimation(2);
            }
        };
    
        private final Runnable mCircleFourRunnable = new Runnable() {
            @Override
            public void run() {
                mGroundOverlays[3] = mGoogleMap.addGroundOverlay(new GroundOverlayOptions()
                        .position(mLatLng, (int) mDistance)
                        .transparency(mTransparency)
                        .image(mBackgroundImageDescriptor));
                startAnimation(3);
            }
        };
    
        private void startAnimation(final int numberOfRipple) {
            ValueAnimator animator = ValueAnimator.ofInt(0, (int) mDistance);
            animator.setRepeatCount(ValueAnimator.INFINITE);
            animator.setRepeatMode(ValueAnimator.RESTART);
            animator.setDuration(mRippleDuration);
            animator.setEvaluator(new IntEvaluator());
            animator.setInterpolator(new LinearInterpolator());
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    int animated = (int) valueAnimator.getAnimatedValue();
                    mGroundOverlays[numberOfRipple].setDimensions(animated);
                    if (mDistance - animated <= 10) {
                        if (mLatLng != mPrevLatLng) {
                            mGroundOverlays[numberOfRipple].setPosition(mLatLng);
                        }
                    }
                }
            });
            animator.start();
            mAnimators[numberOfRipple] = animator;
        }
    
        private void setDrawableAndBitmap() {
            mBackground.setColor(mFillColor);
            mBackground.setStroke(UiUtil.dpToPx(mStrokeWidth), mStrokeColor);
            mBackgroundImageDescriptor = UiUtil.drawableToBitmapDescriptor(mBackground);
        }
    
    
        public void stopRippleMapAnimation() {
            if (isAnimationRunning) {
                try {
                    for (int i = 0; i < mNumberOfRipples; i++) {
                        if (i == 0) {
                            mHandlers[i].removeCallbacks(mCircleOneRunnable);
                            mAnimators[i].cancel();
                            mGroundOverlays[i].remove();
                        }
                        if (i == 1) {
                            mHandlers[i].removeCallbacks(mCircleTwoRunnable);
                            mAnimators[i].cancel();
                            mGroundOverlays[i].remove();
                        }
                        if (i == 2) {
                            mHandlers[i].removeCallbacks(mCircleThreeRunnable);
                            mAnimators[i].cancel();
                            mGroundOverlays[i].remove();
                        }
                        if (i == 3) {
                            mHandlers[i].removeCallbacks(mCircleFourRunnable);
                            mAnimators[i].cancel();
                            mGroundOverlays[i].remove();
                        }
                    }
                } catch (Exception e) {
                    //no need to handle it
                }
            }
            isAnimationRunning = false;
        }
    
        public void startRippleMapAnimation() {
            if (!isAnimationRunning) {
                setDrawableAndBitmap();
                for (int i = 0; i < mNumberOfRipples; i++) {
                    if (i == 0) {
                        mHandlers[i] = new Handler();
                        mHandlers[i].postDelayed(mCircleOneRunnable, mDurationBetweenTwoRipples * i);
                    }
                    if (i == 1) {
                        mHandlers[i] = new Handler();
                        mHandlers[i].postDelayed(mCircleTwoRunnable, mDurationBetweenTwoRipples * i);
                    }
                    if (i == 2) {
                        mHandlers[i] = new Handler();
                        mHandlers[i].postDelayed(mCircleThreeRunnable, mDurationBetweenTwoRipples * i);
                    }
                    if (i == 3) {
                        mHandlers[i] = new Handler();
                        mHandlers[i].postDelayed(mCircleFourRunnable, mDurationBetweenTwoRipples * i);
                    }
                }
            }
            isAnimationRunning = true;
        }
    }
    

    R.drawable.map_background

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval">
        <size
            android:width="150dp"
            android:height="150dp" />
        <stroke
            android:width="0.5dp"
            android:color="#000000" />
    </shape>
    

    PolyUtil.class

    public class PolyUtil {
    
            private PolyUtil() {}
    
    
            private static double tanLatGC(double lat1, double lat2, double lng2, double lng3) {
                return (tan(lat1) * sin(lng2 - lng3) + tan(lat2) * sin(lng3)) / sin(lng2);
            }
    
    
            private static double mercatorLatRhumb(double lat1, double lat2, double lng2, double lng3) {
                return (mercator(lat1) * (lng2 - lng3) + mercator(lat2) * lng3) / lng2;
            }
    
    
            private static boolean intersects(double lat1, double lat2, double lng2,
                                              double lat3, double lng3, boolean geodesic) {
                // Both ends on the same side of lng3.
                if ((lng3 >= 0 && lng3 >= lng2) || (lng3 < 0 && lng3 < lng2)) {
                    return false;
                }
                // Point is South Pole.
                if (lat3 <= -PI/2) {
                    return false;
                }
                // Any segment end is a pole.
                if (lat1 <= -PI/2 || lat2 <= -PI/2 || lat1 >= PI/2 || lat2 >= PI/2) {
                    return false;
                }
                if (lng2 <= -PI) {
                    return false;
                }
                double linearLat = (lat1 * (lng2 - lng3) + lat2 * lng3) / lng2;
                // Northern hemisphere and point under lat-lng line.
                if (lat1 >= 0 && lat2 >= 0 && lat3 < linearLat) {
                    return false;
                }
                // Southern hemisphere and point above lat-lng line.
                if (lat1 <= 0 && lat2 <= 0 && lat3 >= linearLat) {
                    return true;
                }
                // North Pole.
                if (lat3 >= PI/2) {
                    return true;
                }
    
                return geodesic ?
                    tan(lat3) >= tanLatGC(lat1, lat2, lng2, lng3) :
                    mercator(lat3) >= mercatorLatRhumb(lat1, lat2, lng2, lng3);
            }
    
            public static boolean containsLocation(LatLng point, List<LatLng> polygon, boolean geodesic) {
                return containsLocation(point.latitude, point.longitude, polygon, geodesic);
            }
    
    
            public static boolean containsLocation(double latitude, double longitude, List<LatLng> polygon, boolean geodesic) {
                final int size = polygon.size();
                if (size == 0) {
                    return false;
                }
                double lat3 = toRadians(latitude);
                double lng3 = toRadians(longitude);
                LatLng prev = polygon.get(size - 1);
                double lat1 = toRadians(prev.latitude);
                double lng1 = toRadians(prev.longitude);
                int nIntersect = 0;
                for (LatLng point2 : polygon) {
                    double dLng3 = wrap(lng3 - lng1, -PI, PI);
                    // Special case: point equal to vertex is inside.
                    if (lat3 == lat1 && dLng3 == 0) {
                        return true;
                    }
                    double lat2 = toRadians(point2.latitude);
                    double lng2 = toRadians(point2.longitude);
                    // Offset longitudes by -lng1.
                    if (intersects(lat1, lat2, wrap(lng2 - lng1, -PI, PI), lat3, dLng3, geodesic)) {
                        ++nIntersect;
                    }
                    lat1 = lat2;
                    lng1 = lng2;
                }
                return (nIntersect & 1) != 0;
            }
    
            private static final double DEFAULT_TOLERANCE = 0.1;  // meters.
    
    
            public static boolean isLocationOnEdge(LatLng point, List<LatLng> polygon, boolean geodesic,
                                                   double tolerance) {
                return isLocationOnEdgeOrPath(point, polygon, true, geodesic, tolerance);
            }
    
    
            public static boolean isLocationOnEdge(LatLng point, List<LatLng> polygon, boolean geodesic) {
                return isLocationOnEdge(point, polygon, geodesic, DEFAULT_TOLERANCE);
            }
    
    
            public static boolean isLocationOnPath(LatLng point, List<LatLng> polyline,
                                                   boolean geodesic, double tolerance) {
                return isLocationOnEdgeOrPath(point, polyline, false, geodesic, tolerance);
            }
    
    
            public static boolean isLocationOnPath(LatLng point, List<LatLng> polyline,
                                                   boolean geodesic) {
                return isLocationOnPath(point, polyline, geodesic, DEFAULT_TOLERANCE);
            }
    
            private static boolean isLocationOnEdgeOrPath(LatLng point, List<LatLng> poly, boolean closed,
                                                          boolean geodesic, double toleranceEarth) {
                int idx = locationIndexOnEdgeOrPath(point, poly, closed, geodesic, toleranceEarth);
    
                return (idx >= 0);
            }
    
    
            public static int locationIndexOnPath(LatLng point, List<LatLng> poly,
                                                  boolean geodesic, double tolerance) {
                return locationIndexOnEdgeOrPath(point, poly, false, geodesic, tolerance);
            }
    
    
            public static int locationIndexOnPath(LatLng point, List<LatLng> polyline,
                                                  boolean geodesic) {
                return locationIndexOnPath(point, polyline, geodesic, DEFAULT_TOLERANCE);
            }
    
    
            private static int locationIndexOnEdgeOrPath(LatLng point, List<LatLng> poly, boolean closed,
                                                         boolean geodesic, double toleranceEarth) {
                int size = poly.size();
                if (size == 0) {
                    return -1;
                }
                double tolerance = toleranceEarth / EARTH_RADIUS;
                double havTolerance = hav(tolerance);
                double lat3 = toRadians(point.latitude);
                double lng3 = toRadians(point.longitude);
                LatLng prev = poly.get(closed ? size - 1 : 0);
                double lat1 = toRadians(prev.latitude);
                double lng1 = toRadians(prev.longitude);
                int idx = 0;
                if (geodesic) {
                    for (LatLng point2 : poly) {
                        double lat2 = toRadians(point2.latitude);
                        double lng2 = toRadians(point2.longitude);
                        if (isOnSegmentGC(lat1, lng1, lat2, lng2, lat3, lng3, havTolerance)) {
                            return Math.max(0, idx - 1);
                        }
                        lat1 = lat2;
                        lng1 = lng2;
                        idx++;
                    }
                } else {
    
                    double minAcceptable = lat3 - tolerance;
                    double maxAcceptable = lat3 + tolerance;
                    double y1 = mercator(lat1);
                    double y3 = mercator(lat3);
                    double[] xTry = new double[3];
                    for (LatLng point2 : poly) {
                        double lat2 = toRadians(point2.latitude);
                        double y2 = mercator(lat2);
                        double lng2 = toRadians(point2.longitude);
                        if (max(lat1, lat2) >= minAcceptable && min(lat1, lat2) <= maxAcceptable) {
                            // We offset longitudes by -lng1; the implicit x1 is 0.
                            double x2 = wrap(lng2 - lng1, -PI, PI);
                            double x3Base = wrap(lng3 - lng1, -PI, PI);
                            xTry[0] = x3Base;
                            // Also explore wrapping of x3Base around the world in both directions.
                            xTry[1] = x3Base + 2 * PI;
                            xTry[2] = x3Base - 2 * PI;
                            for (double x3 : xTry) {
                                double dy = y2 - y1;
                                double len2 = x2 * x2 + dy * dy;
                                double t = len2 <= 0 ? 0 : clamp((x3 * x2 + (y3 - y1) * dy) / len2, 0, 1);
                                double xClosest = t * x2;
                                double yClosest = y1 + t * dy;
                                double latClosest = inverseMercator(yClosest);
                                double havDist = havDistance(lat3, latClosest, x3 - xClosest);
                                if (havDist < havTolerance) {
                                    return Math.max(0, idx - 1);
                                }
                            }
                        }
                        lat1 = lat2;
                        lng1 = lng2;
                        y1 = y2;
                        idx++;
                    }
                }
                return -1;
            }
    
    
            private static double sinDeltaBearing(double lat1, double lng1, double lat2, double lng2,
                                                  double lat3, double lng3) {
                double sinLat1 = sin(lat1);
                double cosLat2 = cos(lat2);
                double cosLat3 = cos(lat3);
                double lat31 = lat3 - lat1;
                double lng31 = lng3 - lng1;
                double lat21 = lat2 - lat1;
                double lng21 = lng2 - lng1;
                double a = sin(lng31) * cosLat3;
                double c = sin(lng21) * cosLat2;
                double b = sin(lat31) + 2 * sinLat1 * cosLat3 * hav(lng31);
                double d = sin(lat21) + 2 * sinLat1 * cosLat2 * hav(lng21);
                double denom = (a * a + b * b) * (c * c + d * d);
                return denom <= 0 ? 1 : (a * d - b * c) / sqrt(denom);
            }
    
            private static boolean isOnSegmentGC(double lat1, double lng1, double lat2, double lng2,
                                                 double lat3, double lng3, double havTolerance) {
                double havDist13 = havDistance(lat1, lat3, lng1 - lng3);
                if (havDist13 <= havTolerance) {
                    return true;
                }
                double havDist23 = havDistance(lat2, lat3, lng2 - lng3);
                if (havDist23 <= havTolerance) {
                    return true;
                }
                double sinBearing = sinDeltaBearing(lat1, lng1, lat2, lng2, lat3, lng3);
                double sinDist13 = sinFromHav(havDist13);
                double havCrossTrack = havFromSin(sinDist13 * sinBearing);
                if (havCrossTrack > havTolerance) {
                    return false;
                }
                double havDist12 = havDistance(lat1, lat2, lng1 - lng2);
                double term = havDist12 + havCrossTrack * (1 - 2 * havDist12);
                if (havDist13 > term || havDist23 > term) {
                    return false;
                }
                if (havDist12 < 0.74) {
                    return true;
                }
                double cosCrossTrack = 1 - 2 * havCrossTrack;
                double havAlongTrack13 = (havDist13 - havCrossTrack) / cosCrossTrack;
                double havAlongTrack23 = (havDist23 - havCrossTrack) / cosCrossTrack;
                double sinSumAlongTrack = sinSumFromHav(havAlongTrack13, havAlongTrack23);
                return sinSumAlongTrack > 0;  // Compare with half-circle == PI using sign of sin().
            }
    
    
            public static List<LatLng> simplify(List<LatLng> poly, double tolerance) {
                final int n = poly.size();
                if (n < 1) {
                    throw new IllegalArgumentException("Polyline must have at least 1 point");
                }
                if (tolerance <= 0) {
                    throw new IllegalArgumentException("Tolerance must be greater than zero");
                }
    
                boolean closedPolygon = isClosedPolygon(poly);
                LatLng lastPoint = null;
    
               if (closedPolygon) {
                    final double OFFSET = 0.00000000001;
                    lastPoint = poly.get(poly.size() - 1);
                    poly.remove(poly.size() - 1);
                    poly.add(new LatLng(lastPoint.latitude + OFFSET, lastPoint.longitude + OFFSET));
                }
    
                int idx;
                int maxIdx = 0;
                Stack<int[]> stack = new Stack<>();
                double[] dists = new double[n];
                dists[0] = 1;
                dists[n - 1] = 1;
                double maxDist;
                double dist = 0.0;
                int[] current;
    
                if (n > 2) {
                    int[] stackVal = new int[]{0, (n - 1)};
                    stack.push(stackVal);
                    while (stack.size() > 0) {
                        current = stack.pop();
                        maxDist = 0;
                        for (idx = current[0] + 1; idx < current[1]; ++idx) {
                            dist = distanceToLine(poly.get(idx), poly.get(current[0]),
                                    poly.get(current[1]));
                            if (dist > maxDist) {
                                maxDist = dist;
                                maxIdx = idx;
                            }
                        }
                        if (maxDist > tolerance) {
                            dists[maxIdx] = maxDist;
                            int[] stackValCurMax = {current[0], maxIdx};
                            stack.push(stackValCurMax);
                            int[] stackValMaxCur = {maxIdx, current[1]};
                            stack.push(stackValMaxCur);
                        }
                    }
                }
    
                if (closedPolygon) {
                    poly.remove(poly.size() - 1);
                    poly.add(lastPoint);
                }
    
    
                idx = 0;
                ArrayList<LatLng> simplifiedLine = new ArrayList<>();
                for (LatLng l : poly) {
                    if (dists[idx] != 0) {
                        simplifiedLine.add(l);
                    }
                    idx++;
                }
    
                return simplifiedLine;
            }
    
    
            public static boolean isClosedPolygon(List<LatLng> poly) {
                LatLng firstPoint = poly.get(0);
                LatLng lastPoint = poly.get(poly.size()-1);
                return firstPoint.equals(lastPoint);
            }
    
    
            public static double distanceToLine(final LatLng p, final LatLng start, final LatLng end) {
                if (start.equals(end)) {
                    return computeDistanceBetween(end, p);
                }
    
                final double s0lat = toRadians(p.latitude);
                final double s0lng = toRadians(p.longitude);
                final double s1lat = toRadians(start.latitude);
                final double s1lng = toRadians(start.longitude);
                final double s2lat = toRadians(end.latitude);
                final double s2lng = toRadians(end.longitude);
    
                double s2s1lat = s2lat - s1lat;
                double s2s1lng = s2lng - s1lng;
                final double u = ((s0lat - s1lat) * s2s1lat + (s0lng - s1lng) * s2s1lng)
                        / (s2s1lat * s2s1lat + s2s1lng * s2s1lng);
                if (u <= 0) {
                    return computeDistanceBetween(p, start);
                }
                if (u >= 1) {
                    return computeDistanceBetween(p, end);
                }
                LatLng sa = new LatLng(p.latitude - start.latitude, p.longitude - start.longitude);
                LatLng sb = new LatLng(u * (end.latitude - start.latitude), u * (end.longitude - start.longitude));
                return computeDistanceBetween(sa, sb);
            }
    
    
            public static List<LatLng> decode(final String encodedPath) {
                int len = encodedPath.length();
    
                final List<LatLng> path = new ArrayList<LatLng>();
                int index = 0;
                int lat = 0;
                int lng = 0;
    
                while (index < len) {
                    int result = 1;
                    int shift = 0;
                    int b;
                    do {
                        b = encodedPath.charAt(index++) - 63 - 1;
                        result += b << shift;
                        shift += 5;
                    } while (b >= 0x1f);
                    lat += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
    
                    result = 1;
                    shift = 0;
                    do {
                        b = encodedPath.charAt(index++) - 63 - 1;
                        result += b << shift;
                        shift += 5;
                    } while (b >= 0x1f);
                    lng += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
    
                    path.add(new LatLng(lat * 1e-5, lng * 1e-5));
                }
    
                return path;
            }
            public static String encode(final List<LatLng> path) {
                long lastLat = 0;
                long lastLng = 0;
    
                final StringBuffer result = new StringBuffer();
    
                for (final LatLng point : path) {
                    long lat = Math.round(point.latitude * 1e5);
                    long lng = Math.round(point.longitude * 1e5);
    
                    long dLat = lat - lastLat;
                    long dLng = lng - lastLng;
    
                    encode(dLat, result);
                    encode(dLng, result);
    
                    lastLat = lat;
                    lastLng = lng;
                }
                return result.toString();
            }
    
            private static void encode(long v, StringBuffer result) {
                v = v < 0 ? ~(v << 1) : v << 1;
                while (v >= 0x20) {
                    result.append(Character.toChars((int) ((0x20 | (v & 0x1f)) + 63)));
                    v >>= 5;
                }
                result.append(Character.toChars((int) (v + 63)));
            }
        } 
    

    谷歌地图活动

    MapRipple  mapRipple = new MapRipple(mGoogleMap, new LatLng(gpsTracker.getLatitude(), gpsTracker.getLongitude()), this);
               mapRipple.stopRippleMapAnimation();
               mapRipple.withNumberOfRipples(3);
               mapRipple.withFillColor(Color.parseColor("#FFA3D2E4"));
               mapRipple.withStrokeColor(Color.BLACK);
               mapRipple.withStrokewidth(0);
               mapRipple.withDistance(2000);
               mapRipple.withRippleDuration(12000);
               mapRipple.withDurationBetweenTwoRipples(1000);
               mapRipple.withTransparency(0.5f);
               mapRipple.startRippleMapAnimation();
    

    自定义标记图钉

     mGoogleMap.addMarker(new MarkerOptions()
               .icon(BitmapDescriptorFactory.fromBitmap(YourMarkerPinBitmap))
               .anchor(0.5f, 0.6f)
               .position(new LatLng(gpsTracker.getLatitude(), gpsTracker.getLongitude())));
    

    位置变化

    if (mapRipple != null && mapRipple.isAnimationRunning())
            mapRipple.withLatLng(new LatLng(lati, longi));
    

    【讨论】:

      猜你喜欢
      • 2016-01-16
      • 1970-01-01
      • 1970-01-01
      • 2017-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-29
      相关资源
      最近更新 更多