Java 如何使用google地图沿多段线移动标记
我正在尝试根据多段线和动画移动标记。与下图类似: 已经在做这种演示了。但我想用谷歌地图实现同样的目标。但是现在我的标记没有沿着路径旋转。 以下是我尝试过的:Java 如何使用google地图沿多段线移动标记,java,android,google-maps,google-maps-markers,Java,Android,Google Maps,Google Maps Markers,我正在尝试根据多段线和动画移动标记。与下图类似: 已经在做这种演示了。但我想用谷歌地图实现同样的目标。但是现在我的标记没有沿着路径旋转。 以下是我尝试过的: private void onReady(List<LatLng> polyz) { for (int i = 0; i < polyz.size() - 1; i++) { LatLng src = polyz.get(i); LatLng dest = polyz.get
private void onReady(List<LatLng> polyz) {
for (int i = 0; i < polyz.size() - 1; i++) {
LatLng src = polyz.get(i);
LatLng dest = polyz.get(i + 1);
Polyline line = map.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude),
new LatLng(dest.latitude, dest.longitude))
.width(2).color(Color.RED).geodesic(true));
}
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(polyz.get(0));
builder.include(polyz.get(polyz.size()-1));
map.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 48));
map.animateCamera(CameraUpdateFactory.zoomTo(7), 1000, null);
BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(R.drawable.car);
marker = map.addMarker(new MarkerOptions()
.position(polyz.get(0))
.title("Curr")
.snippet("Move"));
marker.setIcon(icon);
}
private void onReady(列表polyz){
对于(int i=0;i
还有动画:
private void animateMarker(GoogleMap myMap, final Marker marker, final List<LatLng> directionPoint,
final boolean hideMarker) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = myMap.getProjection();
final long duration = 600000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
int i = 0;
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed
/ duration);
Location location=new Location(String.valueOf(directionPoint.get(i)));
Location newlocation=new Location(String.valueOf(directionPoint.get(i+1)));
marker.setAnchor(0.5f, 0.5f);
marker.setRotation(location.bearingTo(newlocation) - 45);
if (i < directionPoint.size()) {
marker.setPosition(directionPoint.get(i));
}
i++;
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
marker.setVisible(false);
} else {
marker.setVisible(true);
}
}
}
});
}
private void nextTurnAnimation() {
mIndexCurrentPoint++;
if (mIndexCurrentPoint < mPathPolygonPoints.size() - 1) {
LatLng prevLatLng = mPathPolygonPoints.get(mIndexCurrentPoint - 1);
LatLng currLatLng = mPathPolygonPoints.get(mIndexCurrentPoint);
LatLng nextLatLng = mPathPolygonPoints.get(mIndexCurrentPoint + 1);
float beginAngle = (float)(180 * getAngle(prevLatLng, currLatLng) / Math.PI);
float endAngle = (float)(180 * getAngle(currLatLng, nextLatLng) / Math.PI);
animateCarTurn(mCarMarker, beginAngle, endAngle, TURN_ANIMATION_DURATION);
}
}
private void animateMarker(谷歌地图myMap、最终标记标记、最终列表方向点、,
最终布尔hideMarker){
最终处理程序=新处理程序();
最终长启动=SystemClock.uptimeMillis();
Projection proj=myMap.getProjection();
最终长持续时间=600000;
最终插值器插值器=新的线性插值器();
handler.post(新的Runnable(){
int i=0;
@凌驾
公开募捐{
长时间运行=SystemClock.uptimeMillis()-开始;
float t=interpolator.getInterpolation((float)经过
/持续时间);
Location Location=新位置(String.valueOf(directionPoint.get(i));
Location newlocation=新位置(String.valueOf(directionPoint.get(i+1));
定位锚(0.5f,0.5f);
标记器。设置旋转(位置。轴承至(新位置)-45);
if(i
我想你要找的是
您可以设置标记的动画,使其在图形中显示动态运动
各种不同的情况。指定标记的显示方式的步骤
已设置动画,使用标记的动画属性,类型为
google.maps.Animation。支持以下动画值:
-DROP表示当标记第一次放置在地图上时,应将其从地图顶部放置到最终位置。动画将停止
一旦标记停止,动画将恢复为空。这
动画类型通常在创建标记时指定
-BOUNCE表示标记应在适当的位置反弹。反弹标记将继续反弹,直到其动画属性
显式设置为null
以下是指南中的一个片段:
var marker;
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: {lat: 59.325, lng: 18.070}
});
marker = new google.maps.Marker({
map: map,
draggable: true,
animation: google.maps.Animation.DROP,
position: {lat: 59.327, lng: 18.067}
});
marker.addListener('click', toggleBounce);
}
function toggleBounce() {
if (marker.getAnimation() !== null) {
marker.setAnimation(null);
} else {
marker.setAnimation(google.maps.Animation.BOUNCE);
}
}
问题在于创建
位置
对象的方式。您正在使用位置(字符串提供程序)
构造函数,该构造函数使用命名提供程序构造新位置:
默认情况下,时间、纬度和经度为0,该位置没有方位、高度、速度、精度或附加值
在本例中,您不是使用所需的坐标创建一个位置
,而是一个位置
,其提供程序的名称为String.valueOf(directionPoint.get(i))
,但创建的位置
对象的纬度和经度为0
创建位置
对象的正确方法如下:
Location location = new Location(LocationManager.GPS_PROVIDER);
location.setLatitude(directionPoint.get(i).latitude);
location.setLongitude(directionPoint.get(i).longitude);
Location newlocation = new Location(LocationManager.GPS_PROVIDER);
newlocation.setLatitude(directionPoint.get(i+1).latitude);
newlocation.setLongitude(directionPoint.get(i+1).longitude);
无论如何,要考虑到您将获得一个
数组索引OutofBoundsException
,因为您没有考虑i+1
将是==directionPoint.size()
最后。您可以在任务中使用基于自定义标记动画的方法:在所有方向点上分别设置汽车运动和汽车转弯的动画。为此,您需要两种动画:
private void animateMarker(GoogleMap myMap, final Marker marker, final List<LatLng> directionPoint,
final boolean hideMarker) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = myMap.getProjection();
final long duration = 600000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
int i = 0;
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed
/ duration);
Location location=new Location(String.valueOf(directionPoint.get(i)));
Location newlocation=new Location(String.valueOf(directionPoint.get(i+1)));
marker.setAnchor(0.5f, 0.5f);
marker.setRotation(location.bearingTo(newlocation) - 45);
if (i < directionPoint.size()) {
marker.setPosition(directionPoint.get(i));
}
i++;
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
marker.setVisible(false);
} else {
marker.setVisible(true);
}
}
}
});
}
private void nextTurnAnimation() {
mIndexCurrentPoint++;
if (mIndexCurrentPoint < mPathPolygonPoints.size() - 1) {
LatLng prevLatLng = mPathPolygonPoints.get(mIndexCurrentPoint - 1);
LatLng currLatLng = mPathPolygonPoints.get(mIndexCurrentPoint);
LatLng nextLatLng = mPathPolygonPoints.get(mIndexCurrentPoint + 1);
float beginAngle = (float)(180 * getAngle(prevLatLng, currLatLng) / Math.PI);
float endAngle = (float)(180 * getAngle(currLatLng, nextLatLng) / Math.PI);
animateCarTurn(mCarMarker, beginAngle, endAngle, TURN_ANIMATION_DURATION);
}
}
1) 汽车运动动画
2) 汽车转弯动画
在其末端相互调用(末端的汽车运动动画调用汽车转弯动画,反之亦然:末端的汽车转弯动画调用汽车运动动画,因此适用于汽车路径的所有点)
例如,在图中:
1) 汽车从P0
移动到P1
的动画
2) 汽车启动的动画P1
3) 汽车从P1
移动到P2
等等
汽车运动动画可以通过以下方法实现:
private void animateCarMove(final Marker marker, final LatLng beginLatLng, final LatLng endLatLng, final long duration) {
final Handler handler = new Handler();
final long startTime = SystemClock.uptimeMillis();
final Interpolator interpolator = new LinearInterpolator();
// set car bearing for current part of path
float angleDeg = (float)(180 * getAngle(beginLatLng, endLatLng) / Math.PI);
Matrix matrix = new Matrix();
matrix.postRotate(angleDeg);
marker.setIcon(BitmapDescriptorFactory.fromBitmap(Bitmap.createBitmap(mMarkerIcon, 0, 0, mMarkerIcon.getWidth(), mMarkerIcon.getHeight(), matrix, true)));
handler.post(new Runnable() {
@Override
public void run() {
// calculate phase of animation
long elapsed = SystemClock.uptimeMillis() - startTime;
float t = interpolator.getInterpolation((float) elapsed / duration);
// calculate new position for marker
double lat = (endLatLng.latitude - beginLatLng.latitude) * t + beginLatLng.latitude;
double lngDelta = endLatLng.longitude - beginLatLng.longitude;
if (Math.abs(lngDelta) > 180) {
lngDelta -= Math.signum(lngDelta) * 360;
}
double lng = lngDelta * t + beginLatLng.longitude;
marker.setPosition(new LatLng(lat, lng));
// if not end of line segment of path
if (t < 1.0) {
// call next marker position
handler.postDelayed(this, 16);
} else {
// call turn animation
nextTurnAnimation();
}
}
});
}
private void animateCarTurn(final Marker marker, final float startAngle, final float endAngle, final long duration) {
final Handler handler = new Handler();
final long startTime = SystemClock.uptimeMillis();
final Interpolator interpolator = new LinearInterpolator();
final float dAndgle = endAngle - startAngle;
Matrix matrix = new Matrix();
matrix.postRotate(startAngle);
Bitmap rotatedBitmap = Bitmap.createBitmap(mMarkerIcon, 0, 0, mMarkerIcon.getWidth(), mMarkerIcon.getHeight(), matrix, true);
marker.setIcon(BitmapDescriptorFactory.fromBitmap(rotatedBitmap));
handler.post(new Runnable() {
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - startTime;
float t = interpolator.getInterpolation((float) elapsed / duration);
Matrix m = new Matrix();
m.postRotate(startAngle + dAndgle * t);
marker.setIcon(BitmapDescriptorFactory.fromBitmap(Bitmap.createBitmap(mMarkerIcon, 0, 0, mMarkerIcon.getWidth(), mMarkerIcon.getHeight(), m, true)));
if (t < 1.0) {
handler.postDelayed(this, 16);
} else {
nextMoveAnimation();
}
}
});
}
而汽车图标应朝北:
要正确旋转,请应用
nextTurnAnimation()
-在汽车运动结束动画上调用方法以启动汽车转弯动画:
private void animateMarker(GoogleMap myMap, final Marker marker, final List<LatLng> directionPoint,
final boolean hideMarker) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = myMap.getProjection();
final long duration = 600000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
int i = 0;
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed
/ duration);
Location location=new Location(String.valueOf(directionPoint.get(i)));
Location newlocation=new Location(String.valueOf(directionPoint.get(i+1)));
marker.setAnchor(0.5f, 0.5f);
marker.setRotation(location.bearingTo(newlocation) - 45);
if (i < directionPoint.size()) {
marker.setPosition(directionPoint.get(i));
}
i++;
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
marker.setVisible(false);
} else {
marker.setVisible(true);
}
}
}
});
}
private void nextTurnAnimation() {
mIndexCurrentPoint++;
if (mIndexCurrentPoint < mPathPolygonPoints.size() - 1) {
LatLng prevLatLng = mPathPolygonPoints.get(mIndexCurrentPoint - 1);
LatLng currLatLng = mPathPolygonPoints.get(mIndexCurrentPoint);
LatLng nextLatLng = mPathPolygonPoints.get(mIndexCurrentPoint + 1);
float beginAngle = (float)(180 * getAngle(prevLatLng, currLatLng) / Math.PI);
float endAngle = (float)(180 * getAngle(currLatLng, nextLatLng) / Math.PI);
animateCarTurn(mCarMarker, beginAngle, endAngle, TURN_ANIMATION_DURATION);
}
}
mPathPolygonPoints
(汽车行程的地理点)是:
最后,您可以通过调用animateCarMove()
一次来启动所有动画:
animateCarMove(mCarMarker, mPathPolygonPoints.get(0), mPathPolygonPoints.get(1), MOVE_ANIMATION_DURATION);
对于汽车路径的每个点,将自动调用动画的其他步骤
你应该考虑一些“特殊情况”,比如:
1) 改变转角标志(例如,轴承从-120度变为150度)
2) 用户中断动画的可能性
3) 计算路径段长度上的动画持续时间(例如,1km段长度的动画持续时间为1秒,而不是固定的MOVE\u animation\u duration