如何更正 google 地图 v2 中标记的平滑移动?
How to correct smooth moving the marker in google maps v2?
在我的应用程序中需要显示从一个点到另一个点的平滑 "move" google 地图标记。
我对动画使用以下方法:
public void animateMarker(final Marker marker, final LatLng toPosition,
final boolean hideMarker) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = mMap.getProjection();
Point startPoint = proj.toScreenLocation(marker.getPosition());
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 500;
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;
marker.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
marker.setVisible(false);
} else {
marker.setVisible(true);
}
}
}
});
}
但由于只是为新位置创建了一个新标记(尽管旧标记未被删除):
我从 project mentioned in the official video 复制了一些代码。
我尝试用这段代码和这个 seems to be working for me 重现它,所以希望我的代码能对你有所帮助,哪怕是一点点。
static final LatLng SomePos = new LatLng(37.7796354, -122.4159606);
try {
if (googleMap == null) {
googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
}
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
googleMap.setMyLocationEnabled(true);
googleMap.setTrafficEnabled(false);
googleMap.setIndoorEnabled(false);
googleMap.setBuildingsEnabled(true);
googleMap.getUiSettings().setZoomControlsEnabled(true);
googleMap.moveCamera(CameraUpdateFactory.newLatLng(SomePos));
googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
.target(googleMap.getCameraPosition().target)
.zoom(17)
.bearing(30)
.tilt(45)
.build()));
myMarker = googleMap.addMarker(new MarkerOptions()
.position(SomePos)
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher))
.title("Hello world"));
googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener()
{
@Override
public boolean onMarkerClick(Marker arg0) {
final LatLng startPosition = myMarker.getPosition();
final LatLng finalPosition = new LatLng(37.7801569,-122.4148528);
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final Interpolator interpolator = new AccelerateDecelerateInterpolator();
final float durationInMs = 3000;
final boolean hideMarker = false;
handler.post(new Runnable() {
long elapsed;
float t;
float v;
@Override
public void run() {
// Calculate progress using interpolator
elapsed = SystemClock.uptimeMillis() - start;
t = elapsed / durationInMs;
v = interpolator.getInterpolation(t);
LatLng currentPosition = new LatLng(
startPosition.latitude*(1-t)+finalPosition.latitude*t,
startPosition.longitude*(1-t)+finalPosition.longitude*t);
myMarker.setPosition(currentPosition);
// Repeat till progress is complete.
if (t < 1) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
myMarker.setVisible(false);
} else {
myMarker.setVisible(true);
}
}
}
});
return true;
}
});
} catch (Exception e) {
e.printStackTrace();
}
我知道这是一个老问题但是...
您可以为此任务使用值插值器:
fun changePositionSmoothly(marker:Marker?, newLatLng: LatLng){
if(marker == null){
return;
}
val animation = ValueAnimator.ofFloat(0f, 100f)
var previousStep = 0f
val deltaLatitude = newLatLng.latitude - marker.position.latitude
val deltaLongitude = newLatLng.longitude - marker.position.longitude
animation.setDuration(1500)
animation.addUpdateListener { updatedAnimation ->
val deltaStep = updatedAnimation.getAnimatedValue() as Float - previousStep
previousStep = updatedAnimation.getAnimatedValue() as Float
marker.position = LatLng(marker.position.latitude + deltaLatitude * deltaStep * 1/100, marker.position.longitude + deltaStep * deltaLongitude * 1/100)
}
animation.start()
}
在Java
void changePositionSmoothly(Marker marker, LatLng newLatLng) {
if (marker == null) {
return;
}
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
final float[] previousStep = {0f};
double deltaLatitude = newLatLng.latitude - marker.getPosition().latitude;
double deltaLongitude = newLatLng.longitude - marker.getPosition().latitude;
animation.setDuration(1500);
animation.addUpdateListener(animation1 -> {
float deltaStep = (Float) animation1.getAnimatedValue() - previousStep[0];
previousStep[0] = (Float) animation1.getAnimatedValue();
marker.setPosition(new LatLng(marker.getPosition().latitude + deltaLatitude * deltaStep * 1 / 100, marker.getPosition().latitude + deltaStep * deltaLongitude * 1 / 100));
});
animation.start();
}
为了防止错误累积,在动画结束时可以设置新的位置,但这对大多数情况来说已经足够了。
在我的应用程序中需要显示从一个点到另一个点的平滑 "move" google 地图标记。 我对动画使用以下方法:
public void animateMarker(final Marker marker, final LatLng toPosition,
final boolean hideMarker) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = mMap.getProjection();
Point startPoint = proj.toScreenLocation(marker.getPosition());
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 500;
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;
marker.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
marker.setVisible(false);
} else {
marker.setVisible(true);
}
}
}
});
}
但由于只是为新位置创建了一个新标记(尽管旧标记未被删除):
我从 project mentioned in the official video 复制了一些代码。
我尝试用这段代码和这个 seems to be working for me 重现它,所以希望我的代码能对你有所帮助,哪怕是一点点。
static final LatLng SomePos = new LatLng(37.7796354, -122.4159606);
try {
if (googleMap == null) {
googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
}
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
googleMap.setMyLocationEnabled(true);
googleMap.setTrafficEnabled(false);
googleMap.setIndoorEnabled(false);
googleMap.setBuildingsEnabled(true);
googleMap.getUiSettings().setZoomControlsEnabled(true);
googleMap.moveCamera(CameraUpdateFactory.newLatLng(SomePos));
googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
.target(googleMap.getCameraPosition().target)
.zoom(17)
.bearing(30)
.tilt(45)
.build()));
myMarker = googleMap.addMarker(new MarkerOptions()
.position(SomePos)
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher))
.title("Hello world"));
googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener()
{
@Override
public boolean onMarkerClick(Marker arg0) {
final LatLng startPosition = myMarker.getPosition();
final LatLng finalPosition = new LatLng(37.7801569,-122.4148528);
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final Interpolator interpolator = new AccelerateDecelerateInterpolator();
final float durationInMs = 3000;
final boolean hideMarker = false;
handler.post(new Runnable() {
long elapsed;
float t;
float v;
@Override
public void run() {
// Calculate progress using interpolator
elapsed = SystemClock.uptimeMillis() - start;
t = elapsed / durationInMs;
v = interpolator.getInterpolation(t);
LatLng currentPosition = new LatLng(
startPosition.latitude*(1-t)+finalPosition.latitude*t,
startPosition.longitude*(1-t)+finalPosition.longitude*t);
myMarker.setPosition(currentPosition);
// Repeat till progress is complete.
if (t < 1) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
myMarker.setVisible(false);
} else {
myMarker.setVisible(true);
}
}
}
});
return true;
}
});
} catch (Exception e) {
e.printStackTrace();
}
我知道这是一个老问题但是...
您可以为此任务使用值插值器:
fun changePositionSmoothly(marker:Marker?, newLatLng: LatLng){
if(marker == null){
return;
}
val animation = ValueAnimator.ofFloat(0f, 100f)
var previousStep = 0f
val deltaLatitude = newLatLng.latitude - marker.position.latitude
val deltaLongitude = newLatLng.longitude - marker.position.longitude
animation.setDuration(1500)
animation.addUpdateListener { updatedAnimation ->
val deltaStep = updatedAnimation.getAnimatedValue() as Float - previousStep
previousStep = updatedAnimation.getAnimatedValue() as Float
marker.position = LatLng(marker.position.latitude + deltaLatitude * deltaStep * 1/100, marker.position.longitude + deltaStep * deltaLongitude * 1/100)
}
animation.start()
}
在Java
void changePositionSmoothly(Marker marker, LatLng newLatLng) {
if (marker == null) {
return;
}
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
final float[] previousStep = {0f};
double deltaLatitude = newLatLng.latitude - marker.getPosition().latitude;
double deltaLongitude = newLatLng.longitude - marker.getPosition().latitude;
animation.setDuration(1500);
animation.addUpdateListener(animation1 -> {
float deltaStep = (Float) animation1.getAnimatedValue() - previousStep[0];
previousStep[0] = (Float) animation1.getAnimatedValue();
marker.setPosition(new LatLng(marker.getPosition().latitude + deltaLatitude * deltaStep * 1 / 100, marker.getPosition().latitude + deltaStep * deltaLongitude * 1 / 100));
});
animation.start();
}
为了防止错误累积,在动画结束时可以设置新的位置,但这对大多数情况来说已经足够了。