我正在寻找一种使android设备中的Google地图上两个标记之间的点动起来的方法。
所以我最后想要的是两个图像之间的以下行:
,它将像以下典型的Google折线实现一样使用:
让我们说有一个点A和一个点B。如果将用户直接指向点B,则该线会从点A动画到点B,因此用户知道将沿着该方向行走。
要实现这一点,我想我可以从折线中取出点并删除它们,然后再添加回去 迅速地。因此,假设我在polyLine中有5个点,我将删除位置1,然后放回去,然后删除位置2,然后放回去,以模拟此动画。
但是它不起作用。一旦设置了折线,看来我无法更改它。你有什么建议吗?
val dotPattern = Arrays.asList(Dot(), Gap(convertDpToPixel(7).toFloat()))
val polyLineOptions: PolylineOptions = PolylineOptions()
.add(usersLocation)
.add(users_destination)
.pattern(dotPattern)
.width(convertDpToPixel(6).toFloat())
dottedPolyLine = googleMap.addPolyline(polyLineOptions)
dottedPolyLine?.points?.removeAt(1)//作为测试,如果我的想法是尝试删除一个点,但此处看起来像一个点表示当前位置或目的地,因此总会有2个。我认为一个点将是点之一。
答案 0 :(得分:1)
您可以在this answer中使用基于MapView的自定义视图View Canvas动画:
此方法要求 基于
MapView
custom view, 实现:
在MapView画布上绘制;
自定义线条样式(用圆圈代替简单的线条);
地图纬度/经度坐标的绑定路径
执行动画。
在MapView上绘制需要覆盖
dispatchDraw()
。 自定义线型需求setPathEffect()
的方法Paint
允许为“圆形图章”创建创建路径的类(在 像素),它将重复每个“前进”(也以像素为单位), 像这样的东西:mCircleStampPath = new Path(); mCircleStampPath.addCircle(0,0, CIRCLE_RADIUS,Path.Direction.CCW); mCircleStampPath.close();
用于将屏幕上的路径绑定到纬度/经度坐标
Projection.toScreenLocation()
需要,这需要GoogleMap
对象,因此自定义视图应实现OnMapReadyCallback
收到它。连续动画postInvalidateDelayed()
可以使用。
但不直接绘制从点A到点B的路径,而是从点A到从点A动画到点B的点C。要获得点C的当前位置,可以使用SphericalUtil.interpolate()
中的Google Maps Android API Utility Library 。像这样:
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 static final int ANIMATION_DURATION = 10000;
private OnMapReadyCallback mMapReadyCallback;
private GoogleMap mGoogleMap;
private LatLng mPointA;
private LatLng mPointB;
private LatLng mPointC;
private float mCirclePhase = 0; // amount to offset before the first circle is stamped
private Path mCircleStampPath;
private Paint mPaintLine;
private final Path mPathFromAtoC = new Path();
private long mStartTime;
private long mElapsedTime;
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 one shot animation
mElapsedTime = System.currentTimeMillis() - mStartTime;
if (mElapsedTime < ANIMATION_DURATION) {
postInvalidateDelayed(1000 / FRAMES_PER_SECOND);
}
}
private void drawLineFomAtoB(Canvas canvas) {
if (mGoogleMap == null || mPointA == null || mPointB == null) {
return;
}
// interpolate current position
mPointC = SphericalUtil.interpolate(mPointA, mPointB, (float) mElapsedTime / (float)ANIMATION_DURATION);
final Projection mapProjection = mGoogleMap.getProjection();
final Point pointA = mapProjection.toScreenLocation(mPointA);
final Point pointC = mapProjection.toScreenLocation(mPointC);
mPathFromAtoC.rewind();
mPathFromAtoC.moveTo(pointC.x, pointC.y);
mPathFromAtoC.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(mPathFromAtoC, 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));
// start animation
mStartTime = System.currentTimeMillis();
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;
}
}
NB!这只是想法,而不是经过全面测试的代码。