我正在使用谷歌地图v2。 我在地图上有一个标记,这个标记每次都会改变旋转。 我想动画制作者的旋转以平滑旋转。 任何人都可以帮忙吗
答案 0 :(得分:6)
我的实现平滑标记移动与制造商图像旋转(当它设置为FLAT [重要]时)。将标记平滑地移动到所请求的位置,并将其以适当的方向旋转到所需的程度。例如,当从5deg移动到355deg时,它会逆时针移动,当355deg移动到5deg时,它会顺时针移动。
public void animateMarker(final Location location)
{
if (myMarkerLOC != null) {
final LatLngInterpolator latLngInterpolator = new LatLngInterpolator.LinearFixed();
ValueAnimator valueAnimator = new ValueAnimator();
final LatLng startPosition = myMarkerLOC.getPosition();
final float startRotation = myMarkerLOC.getRotation();
final float angle = 180 - Math.abs(Math.abs(startRotation - location.getBearing()) - 180);
final float right = WhichWayToTurn(startRotation, location.getBearing());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
try {
if (myMarkerLOC == null) // oops... destroying map during animation...
{
return;
}
float v = animation.getAnimatedFraction();
LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, PositionUtil.toLatLng(location));
float rotation = startRotation + right * v * angle;
myMarkerLOC.setRotation((float) rotation);
myMarkerLOC.setPosition(newPosition);
} catch (Exception ex) {
// I don't care atm..
}
}
});
valueAnimator.setFloatValues(0, 1);
valueAnimator.setDuration(300);
valueAnimator.start();
}
}
private float WhichWayToTurn(float currentDirection, float targetDirection)
{
float diff = targetDirection - currentDirection;
if (Math.abs(diff) == 0)
{
return 0;
}
if(diff > 180)
{
return -1;
}
else
{
return 1;
}
}
public interface LatLngInterpolator
{
public LatLng interpolate(float fraction, LatLng a, LatLng b);
public class Linear implements LatLngInterpolator
{
@Override
public LatLng interpolate(float fraction, LatLng a, LatLng b)
{
double lat = (b.latitude - a.latitude) * fraction + a.latitude;
double lng = (b.longitude - a.longitude) * fraction + a.longitude;
return new LatLng(lat, lng);
}
}
public class LinearFixed implements LatLngInterpolator
{
@Override
public LatLng interpolate(float fraction, LatLng a, LatLng b) {
double lat = (b.latitude - a.latitude) * fraction + a.latitude;
double lngDelta = b.longitude - a.longitude;
// Take the shortest path across the 180th meridian.
if (Math.abs(lngDelta) > 180) {
lngDelta -= Math.signum(lngDelta) * 360;
}
double lng = lngDelta * fraction + a.longitude;
return new LatLng(lat, lng);
}
}
}
缺少" toLatLong"的实施方法:
public static LatLng toLatLng(final Location location)
{
return new LatLng(location.getLatitude(), location.getLongitude());
}
我希望有所帮助。
答案 1 :(得分:4)
boolean isRotating = false;
public void rotateMarker(final Marker marker, final float toRotation) {
if(!isRotating) {
isRotating = true;
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final float startRotation = marker.getRotation();
final long duration = 1000;
float deltaRotation = Math.abs(toRotation - startRotation) % 360;
final float rotation = (deltaRotation > 180 ? 360 - deltaRotation : deltaRotation) *
((toRotation - startRotation >= 0 && toRotation - startRotation <= 180) || (toRotation - startRotation <= -180 && toRotation - startRotation >= -360) ? 1 : -1);
final LinearInterpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
marker.setRotation((startRotation + t * rotation) % 360);
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
isRotating = false;
}
}
});
}
}
这是我旋转标记的方式,我不知道这是最好的代码。 但我认为它会阻止错误的轮换。编辑:添加var isRotating(感谢@TrầnVănHuy)
答案 2 :(得分:2)
static public void rotateMarker(final Marker marker, final float toRotation, GoogleMap map) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final float startRotation = marker.getRotation();
final long duration = 1555;
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);
float rot = t * toRotation + (1 -t) * startRotation;
marker.setRotation(-rot > 180 ? rot/2 : rot);
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
}
});
}
我设法做到了:)
答案 3 :(得分:1)
用@Bhagaskara Liancer回答。添加var isMarkerRotating,帮助标记顺利旋转。
private boolean isMarkerRotating = false;
public void rotateMarker(final Marker marker, final float toRotation) {
if(!isMarkerRotating){
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final float startRotation = marker.getRotation();
final long duration = 1000;
float deltaRotation = Math.abs(toRotation - startRotation) % 360;
final float rotation = (deltaRotation > 180 ? 360 - deltaRotation : deltaRotation) * ((toRotation - startRotation >= 0 && toRotation - startRotation <= 180)
|| (toRotation - startRotation <=-180 && toRotation- startRotation>= -360) ? 1 : -1);
final LinearInterpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
@Override
public void run() {
isMarkerRotating = true;
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
marker.setRotation((startRotation + t* rotation)%360);
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}else {
isMarkerRotating = false;
}
}
});
}
}
答案 4 :(得分:1)
这是一个简单的例子 您可以使用以下MarkerAnimation类为旋转设置动画标记。
import android.graphics.Point;
import android.location.Location;
import android.os.Handler;
import android.os.SystemClock;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import com.gogrocerycart.settings.Constants;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.Projection;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
/**
* Created by Vinil Chandran on 7/6/18.
*/
public class MarkerAnimation {
private static Location fromPosition;
private static float angle = 0;
public static void move(GoogleMap mMap, final Marker marker, final Location toPosition) {
if (fromPosition != null && marker != null && toPosition != null) {
final Handler handlerRotation = new Handler();
final long startAngle = SystemClock.uptimeMillis();
final float startRotation = marker.getRotation();
final long durationRotation = 300;
final Interpolator interpolatorRotation = new LinearInterpolator();
float bearing = fromPosition.bearingTo(toPosition);
Print.e("Bearing:" + bearing);
angle = bearing<0?(360+bearing):bearing;
angle = angle%360f;
Print.e("Angle:" + angle);
handlerRotation.post(new Runnable() {
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - startAngle;
float t = interpolatorRotation.getInterpolation((float) elapsed / durationRotation);
float rot = t * angle + (1 - t) * startRotation;
float mAngle = -rot > 180 ? rot / 2 : rot;
marker.setRotation(mAngle);
if (t < 1.0) {
handlerRotation.postDelayed(this, 16);
} else {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection projection = mMap.getProjection();
Point startPoint = projection.toScreenLocation(marker.getPosition());
final LatLng startLatLng = projection.fromScreenLocation(startPoint);
final long duration = Constants.LOCATION_REQUEST_INTERVAL;
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.getLongitude() + (1 - t)
* startLatLng.longitude;
double lat = t * toPosition.getLatitude() + (1 - t)
* startLatLng.latitude;
marker.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
}
});
}
}
});
}
fromPosition = toPosition;
}
}
当位置发生变化时,只需调用以下代码即可移动标记。
if (carMarker != null) {
MarkerAnimation.move(mMap,carMarker, location);
}
答案 5 :(得分:0)
您可能希望使用MarkerOption rotation method
public MarkerOptions rotation (float rotation)
将标记的旋转设置为顺时针方向 标记的锚点。旋转轴垂直于 标记。旋转0对应于的默认位置 标记。当标记在地图上是平的时,默认位置为 北对齐并且旋转使得标记始终保持 平放在地图上。当标记是广告牌时,默认位置 指向并且旋转使得标记始终是 对着镜头。默认值为0.
使用new返回调用该方法的对象 旋转集。
答案 6 :(得分:0)
遇到同样的问题,在我的情况下,我使用了ValueAnimator
static public void rotateMarker(final Marker marker, final float toRotation) {
ValueAnimator animator = ValueAnimator.ofFloat(marker.getRotation(), toRotation);
animator.setDuration(duration);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float rotate = Float.parseFloat(animation.getAnimatedValue().toString());
marker.setRotation(rotate);
}
});
animator.start();
}
答案 7 :(得分:0)
Alexander Kolesnik的回答似乎是最简单的。
这是它的Kotlin扩展版本。
您可以传入一个插值器,以免发生一些抖动。
fun Marker.animateRotation(toRotation: Float, interpolator: TimeInterpolator? = AccelerateDecelerateInterpolator()) {
val animator = ValueAnimator.ofFloat(rotation, toRotation)
animator.duration = 500
animator.interpolator = interpolator
animator.addUpdateListener {
rotation = it.animatedValue as? Float ?: return@addUpdateListener
}
animator.start()
}