Google Maps-制作类似抓取应用程序的动画以显示路径方向 [英] Google Maps - making an animation like grab app to show the path direction

查看:70
本文介绍了Google Maps-制作类似抓取应用程序的动画以显示路径方向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个动画,该动画在路径上做一个移动标记.

I would like to make an animation which does a moving marker along a path.

因此,我考虑了如何使用比路径线稍暗的标记来执行此操作.并非常缓慢地移除和更新其位置,以使其看起来像是在移动.但我只是不认为这就是视频中发生的情况.因为市场完全构成了路径的形状.它流动完美.

so i thought about how to do this using a marker that is slightly darker than the path line. and removing and updating its position very slowly so that it looks like its moving. but i just don't think that's what's happening in the video. because the market takes on the shape of the path entirely. it flows perfectly.

这是我到目前为止所拥有的:

here is what i have so far:

fun showLineAtUsersLocation(loc_destination: LatLng) {
    val currentLoc = activity.getCachedCurrentLoc()
        val pattern = Arrays.asList(Dash(), Gap(convertDpToPixel(6).toFloat()))
        val polyLineOptions: PolylineOptions = PolylineOptions()
                .add(currentLoc)
                .add(loc_destination)
                .geodesic(true)
                .pattern(pattern)
                .width(convertDpToPixel(8).toFloat())
        googleMap.addPolyline(polyLineOptions)
}

但这只是显示从一个点到另一个点的覆盖线.并没有真正走这条路.我应该找什么呢?

but this is just showing an overlay line from one point to the other. not really following a path. What should i be looking for instead?

我看到ios具有一个适用于此GMSStyleSpan的类处理图片.但我找不到在android中的等效项.我没有看到span类或style类,对此我可以参考任何想法吗?甚至在标记上甚至带有AnomatedVectorDrawable

I saw that ios has a has a class good for this GMSStyleSpan to manipuate the image. but i cannot find the equivalent in android. i dont see a span class or style class i can get a reference to any ideas on this ? or even with AnomatedVectorDrawable on the marker instead

推荐答案

对于此类(实际上是任何一种)动画,您可以使用View Canvas动画.这种方法需要基于 MapView - 自定义视图,它实现了:

For such (and actually any kind of) animation you can use View Canvas animation. This approach requires MapView-based custom view, that implements:

  • 在MapView画布上绘制;

  • drawing over the MapView canvas;

自定义线条样式(用圆圈代替简单的线条);

customizing line styles (circles instead of a simple line);

地图纬度/经度坐标的绑定路径

binding path to Lat/Lon coordinates of map

执行动画.

在MapView上绘制需要覆盖dispatchDraw().自定义线条样式需要 setPathEffect() Paint 类的a>方法,该方法可为圆形图章"(以像素为单位),它将重复每个前进"(也以像素为单位),类似于:

Drawing over the MapView needs to override dispatchDraw(). Customizing line styles needs setPathEffect() method of Paint class that allows to create create path for "circle stamp" (in pixels), which will repeated every "advance" (in pixels too), something like that:

mCircleStampPath = new Path();
mCircleStampPath.addCircle(0,0, CIRCLE_RADIUS, Path.Direction.CCW);
mCircleStampPath.close();

用于将屏幕上的路径绑定到纬度/经度坐标 postInvalidateDelayed() .因此,使用基于MapView的自定义EnhancedMapView的完整源代码:

For binding path on screen to Lat/Lon coordinates Projection.toScreenLocation() needed, that requires GoogleMap object so custom view should implements OnMapReadyCallback for receive it. For continuous animation postInvalidateDelayed() can be used. So, with full source code of MapView-based custom EnhancedMapView:

public class EnhancedMapView extends MapView implements OnMapReadyCallback {

    private static final float CIRCLE_RADIUS = 10;
    private static final float CIRCLE_ADVANCE = 3.5f * CIRCLE_RADIUS;   // spacing between each circle stamp
    private static final int FRAMES_PER_SECOND = 30;

    private OnMapReadyCallback mMapReadyCallback;
    private GoogleMap mGoogleMap;
    private LatLng mPointA;
    private LatLng mPointB;

    private float mCirclePhase = 0;                                     // amount to offset before the first circle is stamped
    private Path mCircleStampPath;
    private Paint mPaintLine;
    private final Path mPathFromAtoB = new Path();

    public EnhancedMapView(@NonNull Context context) {
        super(context);
        init();
    }

    public EnhancedMapView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public EnhancedMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public EnhancedMapView(@NonNull Context context, @Nullable GoogleMapOptions options) {
        super(context, options);
        init();
    }

    @Override
    public void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        canvas.save();
        drawLineFomAtoB(canvas);
        canvas.restore();

        // perform continuous animation
        postInvalidateDelayed(1000 / FRAMES_PER_SECOND);
    }

    private void drawLineFomAtoB(Canvas canvas) {
        if (mGoogleMap == null || mPointA == null || mPointB == null) {
            return;
        }

        final Projection mapProjection = mGoogleMap.getProjection();
        final Point pointA = mapProjection.toScreenLocation(mPointA);
        final Point pointB = mapProjection.toScreenLocation(mPointB);

        mPathFromAtoB.rewind();
        mPathFromAtoB.moveTo(pointB.x, pointB.y);
        mPathFromAtoB.lineTo(pointA.x, pointA.y);

        // change phase for circles shift
        mCirclePhase = (mCirclePhase < CIRCLE_ADVANCE)
                ? mCirclePhase + 1.0f
                : 0;
        mPaintLine.setPathEffect(new PathDashPathEffect(mCircleStampPath, CIRCLE_ADVANCE, mCirclePhase, PathDashPathEffect.Style.ROTATE));

        canvas.drawPath(mPathFromAtoB, mPaintLine);
    }

    private void init() {
        setWillNotDraw(false);

        mCircleStampPath = new Path();
        mCircleStampPath.addCircle(0,0, CIRCLE_RADIUS, Path.Direction.CCW);
        mCircleStampPath.close();

        mPaintLine = new Paint();
        mPaintLine.setColor(Color.BLACK);
        mPaintLine.setStrokeWidth(1);
        mPaintLine.setStyle(Paint.Style.STROKE);
        mPaintLine.setPathEffect(new PathDashPathEffect(mCircleStampPath, CIRCLE_ADVANCE, mCirclePhase, PathDashPathEffect.Style.ROTATE));

        postInvalidate();
    }

    @Override
    public void getMapAsync(OnMapReadyCallback callback) {
        mMapReadyCallback = callback;
        super.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;
        mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
            @Override
            public void onCameraMove() {
                invalidate();
            }
        });
        if (mMapReadyCallback != null) {
            mMapReadyCallback.onMapReady(googleMap);
        }
    }

    public void setPoints(LatLng pointA, LatLng pointB) {
        mPointA = pointA;
        mPointB = pointB;
    }

}

MainActivity喜欢:

public class MainActivity extends AppCompatActivity {

    private static final String MAP_VIEW_BUNDLE_KEY = "MapViewBundleKey";
    static final LatLng MAIDAN = new LatLng(50.450891, 30.522843);
    static final LatLng SOPHIA = new LatLng(50.452967, 30.514498);

    static final LatLng INITIAL_MAP_CENTER = new LatLng(50.452011, 30.518766);
    static final int INITIAL_ZOOM = 15;

    private GoogleMap mGoogleMap;
    private EnhancedMapView mMapView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Bundle mapViewBundle = null;
        if (savedInstanceState != null) {
            mapViewBundle = savedInstanceState.getBundle(MAP_VIEW_BUNDLE_KEY);
        }

        mMapView = (EnhancedMapView) findViewById(R.id.mapview);
        mMapView.onCreate(mapViewBundle);
        mMapView.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(GoogleMap googleMap) {
                mGoogleMap = googleMap;
                mMapView.setPoints(MAIDAN, SOPHIA);
                mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(INITIAL_MAP_CENTER, INITIAL_ZOOM));
            }
        });

    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        Bundle mapViewBundle = outState.getBundle(MAP_VIEW_BUNDLE_KEY);
        if (mapViewBundle == null) {
            mapViewBundle = new Bundle();
            outState.putBundle(MAP_VIEW_BUNDLE_KEY, mapViewBundle);
        }

        mMapView.onSaveInstanceState(mapViewBundle);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    protected void onStart() {
        super.onStart();
        mMapView.onStart();
    }

    @Override
    protected void onStop() {
        super.onStop();
        mMapView.onStop();
    }
    @Override
    protected void onPause() {
        mMapView.onPause();
        super.onPause();
    }
    @Override
    protected void onDestroy() {
        mMapView.onDestroy();
        super.onDestroy();
    }
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mMapView.onLowMemory();
    }

}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.test.just.googlemapsgeneral.views.EnhancedMapView
        android:id="@+id/mapview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />

</RelativeLayout>

您得到类似的东西:

NB!您应该使用 Path 而不是绘制线条.那只是方法,而不是完整的解决方案.

NB! You should use Path instead of drawing lines. And that is just approach, not complete solution.

这篇关于Google Maps-制作类似抓取应用程序的动画以显示路径方向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆