如何让 Marker 遍历 Java 中的折线?
How to make a Marker traverse a Polyline in Java?
我正在开发一个应用程序,类似于优步、滴滴等。我在制作车辆动画(从 A 点到 B 点)时遇到问题,我在互联网上找到了这段代码,它效果很好:
public void animateMarker(final LatLng startPosition, final LatLng toPosition,final boolean hideMarke) {
final Handler handler = new Handler();
final Marker m = map.addMarker(new MarkerOptions()
.position(startPosition)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.bus2))
.title("Camión"));
final long start = SystemClock.uptimeMillis();
Projection proj = map.getProjection();
Point startPoint = proj.toScreenLocation(m.getPosition());
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 5000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed
/ duration);
double lng = t * toPosition.longitude + (1 - t)
* startLatLng.longitude;
double lat = t * toPosition.latitude + (1 - t)
* startLatLng.latitude;
m.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarke) {
m.setVisible(false);
} else {
m.setVisible(true);
}
}
}
});
markers_animations.add(m);
}
我有这个方法负责将列表的位置传递给它,其中包含折线所需的所有坐标:
private void controlAnimaciones(List<LatLng> ruta) {
for (int i=0; i<ruta.size()-1; i++) {
if (i<ruta.size()) {
animateMarker3(ruta.get(i), ruta.get(i+1), true);
}
}
}
如果它把标记从 A 点移动到 B 点,它做了我预期的事情,但是,只是通过迭代列表,我不知道如何解释它,有很多标记移动仅从列表的一个元素到下一个元素,然后停止。我想做的是实现单个标记可以遍历列表的所有点,我一直在尝试以某种方式使用我从互联网上获得的代码,试图理解它,但我没有太多成功。我该怎么做?
目前在您发布的代码中,animateMarker
为多段线的每个“线段”创建一个标记 - 它开始和停止标记沿一个线段的移动,并且它这样做 异步。这将具有在每个片段的开始处(同时)创建标记并且每个片段平行(几乎)动画的效果。不是你想要的。
所以你有两件事要改变:
- 在第一个段的开头创建一次标记。
- 在第一个(或前一段)完成后继续第二个和后面的片段的动画。
完成上述操作的简单方法是修改 animateMarker
以接受点列表而不是单个点。点列表是您的折线 (ruta
).
我在修改了你原来的方法的地方做了一些评论。
public void animateMarker(List<LatLng> pts,final boolean hideMarker) {
// Simple check to make sure there are enough points in the list.
if (pts.size() <= 1) {
// need at least two points.
return;
}
final Handler handler = new Handler();
// Use first point in list as start.
final Marker m = mMap.addMarker(new MarkerOptions()
.position(pts.get(0))
.title("Camión"));
Projection proj = mMap.getProjection();
Point startPoint = proj.toScreenLocation(m.getPosition());
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 5000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
// start at first segment
private int segment = 0;
// initial start time
long start = SystemClock.uptimeMillis();
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed
/ duration);
// Use next point in list as destination
double lng = t * pts.get(segment+1).longitude + (1 - t)
* pts.get(segment).longitude;
double lat = t * pts.get(segment+1).latitude + (1 - t)
* pts.get(segment).latitude;
m.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
// check if to move to next segment (or done)
else if (segment < (pts.size()-2)) {
// move to next segment
segment++;
start = SystemClock.uptimeMillis();
handler.postDelayed(this,16);
} else {
if (hideMarker) {
m.setVisible(false);
} else {
m.setVisible(true);
}
}
}
});
markers_animations.add(m);
}
要用您的列表调用动画,只需修改您的
private void controlAnimaciones(List<LatLng> ruta) {
animateMarker(ruta, true);
}
这就是结果。
(请注意,标记移动的“速度”取决于片段的长度。由于每个片段的持续时间是固定的,较长的片段会使标记看起来移动得更快。您可以将其更改为通过改变 duration
作为两点之间距离的函数,任何段的恒定速度。)
请注意,animaterMarker
自然支持多个动画,无需修改。因此,在此示例中,地图 onMapClickListener
在每次地图点击时调用 controlAnimaciones
,出于演示目的,每隔几秒执行一次。
希望对您有所帮助!
我正在开发一个应用程序,类似于优步、滴滴等。我在制作车辆动画(从 A 点到 B 点)时遇到问题,我在互联网上找到了这段代码,它效果很好:
public void animateMarker(final LatLng startPosition, final LatLng toPosition,final boolean hideMarke) {
final Handler handler = new Handler();
final Marker m = map.addMarker(new MarkerOptions()
.position(startPosition)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.bus2))
.title("Camión"));
final long start = SystemClock.uptimeMillis();
Projection proj = map.getProjection();
Point startPoint = proj.toScreenLocation(m.getPosition());
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 5000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed
/ duration);
double lng = t * toPosition.longitude + (1 - t)
* startLatLng.longitude;
double lat = t * toPosition.latitude + (1 - t)
* startLatLng.latitude;
m.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarke) {
m.setVisible(false);
} else {
m.setVisible(true);
}
}
}
});
markers_animations.add(m);
}
我有这个方法负责将列表的位置传递给它,其中包含折线所需的所有坐标:
private void controlAnimaciones(List<LatLng> ruta) {
for (int i=0; i<ruta.size()-1; i++) {
if (i<ruta.size()) {
animateMarker3(ruta.get(i), ruta.get(i+1), true);
}
}
}
如果它把标记从 A 点移动到 B 点,它做了我预期的事情,但是,只是通过迭代列表,我不知道如何解释它,有很多标记移动仅从列表的一个元素到下一个元素,然后停止。我想做的是实现单个标记可以遍历列表的所有点,我一直在尝试以某种方式使用我从互联网上获得的代码,试图理解它,但我没有太多成功。我该怎么做?
目前在您发布的代码中,animateMarker
为多段线的每个“线段”创建一个标记 - 它开始和停止标记沿一个线段的移动,并且它这样做 异步。这将具有在每个片段的开始处(同时)创建标记并且每个片段平行(几乎)动画的效果。不是你想要的。
所以你有两件事要改变:
- 在第一个段的开头创建一次标记。
- 在第一个(或前一段)完成后继续第二个和后面的片段的动画。
完成上述操作的简单方法是修改 animateMarker
以接受点列表而不是单个点。点列表是您的折线 (ruta
).
我在修改了你原来的方法的地方做了一些评论。
public void animateMarker(List<LatLng> pts,final boolean hideMarker) {
// Simple check to make sure there are enough points in the list.
if (pts.size() <= 1) {
// need at least two points.
return;
}
final Handler handler = new Handler();
// Use first point in list as start.
final Marker m = mMap.addMarker(new MarkerOptions()
.position(pts.get(0))
.title("Camión"));
Projection proj = mMap.getProjection();
Point startPoint = proj.toScreenLocation(m.getPosition());
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 5000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
// start at first segment
private int segment = 0;
// initial start time
long start = SystemClock.uptimeMillis();
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed
/ duration);
// Use next point in list as destination
double lng = t * pts.get(segment+1).longitude + (1 - t)
* pts.get(segment).longitude;
double lat = t * pts.get(segment+1).latitude + (1 - t)
* pts.get(segment).latitude;
m.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
// check if to move to next segment (or done)
else if (segment < (pts.size()-2)) {
// move to next segment
segment++;
start = SystemClock.uptimeMillis();
handler.postDelayed(this,16);
} else {
if (hideMarker) {
m.setVisible(false);
} else {
m.setVisible(true);
}
}
}
});
markers_animations.add(m);
}
要用您的列表调用动画,只需修改您的
private void controlAnimaciones(List<LatLng> ruta) {
animateMarker(ruta, true);
}
这就是结果。
(请注意,标记移动的“速度”取决于片段的长度。由于每个片段的持续时间是固定的,较长的片段会使标记看起来移动得更快。您可以将其更改为通过改变 duration
作为两点之间距离的函数,任何段的恒定速度。)
请注意,animaterMarker
自然支持多个动画,无需修改。因此,在此示例中,地图 onMapClickListener
在每次地图点击时调用 controlAnimaciones
,出于演示目的,每隔几秒执行一次。
希望对您有所帮助!