腾讯地图SDK Android版开发 8 覆盖物示例2动画

前文介绍了腾讯地图Marker支持多种动画类型:

  • 帧动画;
  • Animation动画(包括平移、旋转、透明、缩放和组合动画)。

本文重点介绍Marker动画相关的类和接口,以及示例代码。

动画相关的类和接口

帧动画

Marke支持轮播的功能。BitmapDescriptorFactory.fromBitmaps(Bitmap... bitmaps)可创建多图BitmapDescriptor对象,通过icon方法传入多图,并通过iconLooper设定轮播模式。

类型方法说明
MarkerOptionsicon(BitmapDescriptor icon)设置标注的样式
MarkerOptionsiconLooper(boolean enable)设置图标轮播模式。默认周期时长为300ms
MarkerOptionsiconLooper(boolean enable, int duration)设置图标轮播模式
  • BitmapDescriptorFactory
类型方法说明
static BitmapDescriptorfromBitmaps(Bitmap… bitmaps)创建多图BitmapDescriptor对象。
static BitmapDescriptorfromBitmaps(TencentMapContext context, Bitmap… bitmaps)创建多图BitmapDescriptor对象。

Animation动画

Marker还支持Animation动画,目前支持平移、缩放、旋转、渐变和组合动画。通过MarkersetAnimation方法设置。

Marker接口继承关系

  • Marker继承自多个接口类。
  • 其中Animationable包括动画相关的方法。
类型方法说明
voidsetAnimation(animation);设置 Marker 覆盖物的动画
booleanstartAnimation();开启 Marker 覆盖物的动画
voidstartAnimation(animation);设置并开启 Marker 覆盖物的动画
  • 注意:平移动画若要恢复起始位置时,可在动画开始前后,分别调用Marker类下面两个方法:
说明说明
voidsetFixingPoint(int x, int y)设置这个Marker固定在屏幕上的坐标点。
voidsetFixingPointEnable(boolean bFix)设置这个Marker是否可以固定在屏幕上不动
Accessible
«interface»
Marker
+void setFixingPoint(int x, int y)
+void setFixingPointEnable(boolean bFix)
Alphable
Anchorable
«interface»
Animationable
+void setAnimation(animation)
+boolean startAnimation()
+void startAnimation(animation)
Clickable
Collisionable
Draggable
Levelable
Removable
Rotatable
Scalable
Tagable
Visible
IOverlay

Animation 接口类及其子接口类

动画类别接口类说明
接口Animation地图Overlay的动画基类
平移动画ITranslateAnimation创建动画使用
TencentMapComponent.createTranslateAnimation(LatLng)
旋转动画IRotateAnimation创建动画使用
TencentMapComponent.createRotateAnimation(float, float, float, float, float)
渐变动画IAlphaAnimationAlpha创建动画使用
TencentMapComponent.createAlphaAnimation(float, float)
缩放动画IScaleAnimation创建动画使用
TencentMapComponent.createScaleAnimation(float, float, float, float)
一组动画IAnimationSet创建动画使用
TencentMapComponent.createAnimationSet(boolean)
IEmergeAnimation这个动画最初是给Polyline出现时用的
创建动画使用
TencentMapComponent.createEmergeAnimation(LatLng)
  • 动画接口及其子接口类关系如下图:
ITranslateAnimation
«interface»
Animation
IRotateAnimation
IAlphaAnimationAlpha
IScaleAnimation
IAnimationSet
IEmergeAnimation
  • TencentMap地图接口和TencentMapComponent地图组件接口关系如下图:
«interface»
TencentMap
+TencentMapContext getMapContext()
«interface»
TencentMapComponent
+ITranslateAnimation createTranslateAnimation(latLng)
+IRotateAnimation createRotateAnimation(fromdegree, todegree, pivotx, pivoty, pivotz)
+IAlphaAnimation createAlphaAnimation(fromAlpha, toAlpha)
+IScaleAnimation createScaleAnimation(fromX, toX, fromY, toY)
+IAnimationSet createAnimationSet(shareInterpolator)
+IEmergeAnimation createEmergeAnimation(startPoint)
Animationable
类型方法说明
AnimationListenergetAnimationListener()获取动画监听
longgetDuration()获取动画时长
InterpolatorgetInterpolator()获取拦截器
voidsetAnimationListener(AnimationListener listener)设置动画的状态回调
voidsetDuration(long duration)设置动画的持续时间
voidsetInterpolator(Interpolator interpolator)设置动画播放进度的拦截器
  • AnimationListener 动画侦听
// 动画播放的状态监听器
public interface AnimationListener {
    // 动画开始播放回调函数
    void onAnimationStart();

    // 动画结束播放回调
    void onAnimationEnd();
}
IAnimationSet
说明说明
booleanaddAnimation(Animation animation)添加一个动画
voidcleanAnimation()清除所有动画
TencentMapComponent 地图组件接口类
说明说明
ITranslateAnimationcreateTranslateAnimation(LatLng target)创建平移动画
IRotateAnimationcreateRotateAnimation(float fromdegree, float todegree, float pivotx, float pivoty, float pivotz)创建旋转动画
IAlphaAnimationcreateAlphaAnimation(float fromAlpha, float toAlpha)创建渐变动画
IScaleAnimationcreateScaleAnimation(float fromX, float toX, float fromY, float toY)创建缩放动画
IAnimationSetcreateAnimationSet(boolean shareInterpolator)创建动画集合
IEmergeAnimationcreateEmergeAnimation(LatLng startPoint)创建动画从哪点开始然后向两端扩展,当然也可以设置为起点或是终点。

Marker 动画示例

界面布局

在这里插入图片描述

  • 布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MapMarkerAnimationActivity">

    <com.tencent.tencentmap.mapsdk.maps.TextureMapView
        android:id="@+id/mapview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@id/bottomView"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.appcompat.widget.LinearLayoutCompat
        android:id="@+id/bottomView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/mapview">

        <RadioGroup
            android:id="@+id/RadioGroup"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/background_dark"
            android:gravity="center_horizontal"
            android:orientation="horizontal"
            android:paddingHorizontal="10dp">

            <RadioButton
                android:id="@+id/frameAnimation"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:checked="true"
                android:onClick="setAnimationFlag"
                android:text="帧动画"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <RadioButton
                android:id="@+id/animation"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setAnimationFlag"
                android:text="Animation动画"
                android:textColor="@color/white"
                android:textStyle="bold" />

        </RadioGroup>

    </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

MapMarkAnimate类

  • 以下是MapMarkAnimate部分代码。

常量

public final static String FRAME_ANIMATION = "Frame"; // 帧动画

public final static String TRANSFORMATION_ANIMATION = "Transformation"; // 平移动画
public final static String ROTATE_ANIMATION = "Rotate"; // 旋转动画
public final static String ALPHA_ANIMATION = "Alpha"; // 透明度动画
public final static String SCALE_ANIMATION = "Scale"; // 缩放动画
public final static String SINGLE_SCALE_ANIMATION = "SingleScale"; // 单边缩放动画 X或Y方向
public final static String ANIMATION_SET = "AnimationSet"; // 组合动画

成员变量

// 覆盖物列表
List<Removable> overlays = new ArrayList<>();
// 选中的状态
List<String> selectedFlags = new ArrayList<>();
// 坐标点集
List<LatLng> points = new ArrayList<>();

ArrayList<BitmapDescriptor> bitmaps = new ArrayList<>();

初始值

selectedFlags.add(FRAME_ANIMATION);
selectedFlags.add(FRAME_ANIMATION);
selectedFlags.add(FRAME_ANIMATION);

points.add(new LatLng(39.97923, 116.357428));
points.add(new LatLng(39.94923, 116.397428));
points.add(new LatLng(39.97923, 116.437428));
points.add(new LatLng(39.92353, 116.490705));
points.add(new LatLng(40.023537, 116.289429));
points.add(new LatLng(40.022211, 116.406137));

int[] drawableIds = BubbleIcons.Number;
for (int drawableId : drawableIds) {
    BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(drawableId);
    bitmaps.add(bitmap);
}

创建覆盖物

public void addMarkers() {
    if (selectedFlags.isEmpty())
        return;

    int markerSize = selectedFlags.size();
    for (int i = 0; i < markerSize; ++i) {
        LatLng point = points.get(i);
        String flag = selectedFlags.get(i);
        switch (flag) {
        case FRAME_ANIMATION:
            addFrameAnimation(point, bitmaps);
            break;
        default:
            addAnimation(point, bitmaps.get(i), flag);
            break;
        }
    }
}
创建Marker(帧动画)
private void addFrameAnimation(LatLng point, ArrayList<BitmapDescriptor> bitmaps) {
    Bitmap[] icons = new Bitmap[bitmaps.size()];
    for (int i = 0; i < bitmaps.size(); ++i) {
        icons[i] = bitmaps.get(i).getBitmap(context);
    }
    // 创建多图BitmapDescriptor对象。
    BitmapDescriptor icon = BitmapDescriptorFactory.fromBitmaps(icons);

    boolean enable = true;// 是否轮播
    int duration = 1000; // 轮播时间(ms)
    MarkerOptions option = new MarkerOptions(point)
            .icon(icon)
            .iconLooper(enable, duration) // 设置图标轮播模式
            .anchor(0.5f, 1.0f); // 设置标注的锚点。默认值为 0.5f, 0.5f

    Marker marker = map.addMarker(option);
    overlays.add(marker);
}
创建Marker(Animation动画)
private void addAnimation(LatLng point, BitmapDescriptor bitmap, String flag) {
    Animation animation = null;
    switch (flag) {
    case TRANSFORMATION_ANIMATION:
        animation = getTransformation(point);
        break;
    case ROTATE_ANIMATION:
        animation = getRotateAnimation();
        break;
    case ALPHA_ANIMATION:
        animation = getAlphaAnimation();
        break;
    case SCALE_ANIMATION:
        animation = getScaleAnimation();
        break;
    case SINGLE_SCALE_ANIMATION:
        animation = getSingleScaleAnimation();
        break;
    case ANIMATION_SET:
        animation = getAnimationSet();
        break;
    }

    if (animation == null)
        return;

    MarkerOptions option = new MarkerOptions(point)
            .icon(bitmap)
            .anchor(0.5f, 1.0f); // 设置标注的锚点。默认值为 0.5f, 0.5f

    Marker marker = map.addMarker(option);
    overlays.add(marker);

    if (TRANSFORMATION_ANIMATION.equals(flag)) {
        Point screenPoint = map.getProjection().toScreenLocation(point);
        // 设置这个Marker固定在屏幕上的坐标点。
        marker.setFixingPoint(screenPoint.x, screenPoint.y);
        animation.setAnimationListener(new AnimationListener() {
            @Override
            public void onAnimationStart() {
                // 动画开始播放回调函数
            }

            @Override
            public void onAnimationEnd() {
                // 动画结束播放回调
                // 设置这个Marker是否可以固定在屏幕上不动
                marker.setFixingPointEnable(false);
            }
        });
    }
    marker.setAnimation(animation);
    marker.startAnimation();
}
创建Animation
  • 创建平移动画、旋转动画、透明度动画、缩放动画、单边缩放动画、创建组合动画。
// 创建平移动画
Animation getTransformation(LatLng point) {
    Point pt1 = map.getProjection().toScreenLocation(point);
    Point pt2 = new Point(pt1.x, pt1.y - 100);
    // 目标坐标点
    LatLng toPoint = map.getProjection().fromScreenLocation(pt2);

    TencentMapContext mapContext = map.getMapContext();
    // 创建平移动画
    ITranslateAnimation animation = mapContext.createTranslateAnimation(toPoint);

    // 设置动画的持续时间
    animation.setDuration(500);

    // 动画播放的状态监听器
    animation.setAnimationListener(new AnimationListener() {
        @Override
        public void onAnimationStart() {
            // 动画开始播放回调函数
        }

        @Override
        public void onAnimationEnd() {
            // 动画结束播放回调
        }
    });

    return animation;
}

// 创建旋转动画
Animation getRotateAnimation() {
    float fromdegree = 0; // 开始角度 [0-360]
    float todegree = 360; // 结束角度 [0-360]
    float pivotx = 0; // 轴心x坐标
    float pivoty = 0; // 轴心y坐标
    float pivotz = 0; // 轴心z坐标

    // 创建旋转动画
    TencentMapContext mapContext = map.getMapContext();
    IRotateAnimation animation = mapContext.createRotateAnimation(fromdegree, todegree,
            pivotx, pivoty, pivotz);

    // 设置动画的持续时间
    animation.setDuration(1000);

    return animation;
}

// 创建透明度动画
Animation getAlphaAnimation() {
    float fromAlpha = 0.0f; // 开始alpha通道值 [0,1]
    float toAlpha = 1.0f; //  结束alpha通道值 [0,1]

    TencentMapContext mapContext = map.getMapContext();
    // 创建渐变动画
    IAlphaAnimation animation = mapContext.createAlphaAnimation(fromAlpha, toAlpha);

    // 设置动画的持续时间
    animation.setDuration(3000);

    return animation;
}

// 创建缩放动画
Animation getScaleAnimation() {
    float fromX = 0.0f; // 相对于X方向宽度的开始倍率
    float toX = 1.0f; // 相对于X方向宽度的结束倍率
    float fromY = 0.0f; // 相对于Y方向长度的开始倍率
    float toY = 1.0f; // 相对于Y方向长度的结束倍率

    TencentMapContext mapContext = map.getMapContext();
    // 创建缩放动画
    IScaleAnimation animation = mapContext.createScaleAnimation(fromX, toX, fromY, toY);

    // 设置动画的持续时间
    animation.setDuration(2000);

    return animation;
}

// 单边缩放动画
Animation getSingleScaleAnimation() {
    float fromX = 0.0f; // 相对于X方向宽度的开始倍率
    float toX = 1.0f; // 相对于X方向宽度的结束倍率
    float fromY = 1.0f; // 相对于Y方向长度的开始倍率
    float toY = 1.0f; // 相对于Y方向长度的结束倍率

    TencentMapContext mapContext = map.getMapContext();
    // 创建缩放动画
    IScaleAnimation animation = mapContext.createScaleAnimation(fromX, toX, fromY, toY);

    // 设置动画的持续时间
    animation.setDuration(1000);

    return animation;
}

// 添加组合动画
Animation getAnimationSet() {
    boolean shareInterpolator = true; // 是否使用相同的插值器
    TencentMapContext mapContext = map.getMapContext();
    // 创建缩放动画
    IAnimationSet animation = mapContext.createAnimationSet(shareInterpolator);

    // 添加一个动画
    animation.addAnimation(getAlphaAnimation(map));
    animation.addAnimation(getRotateAnimation(map));
    animation.addAnimation(getSingleScaleAnimation(map));
    animation.addAnimation(getScaleAnimation(map));

    return animation;
}

移除覆盖物

public void removeOverlay() {
    // 清除地图上所有的标注类(Marker、Polyline、Polygon,TileOverlay除外)
    // map.clearAllOverlays();

    // 从地图移除覆盖物
    for (Removable overlay : overlays) {
        if (!overlay.isRemoved())
            overlay.remove();
    }
    overlays.clear();
}

设置属性

public void setFlags(List<String> flags) {
    selectedFlags.clear();
    selectedFlags.addAll(flags);

    removeOverlay();
    addMarkers();
}

加载地图和释放地图

public void onMapLoaded() {
    addMarkers();
}

public void onMapDestroy() {
    removeOverlay();

//    for (BitmapDescriptor bitmap : bitmaps) {
//        bitmap.recycle();
//    }
    bitmaps = null;
}

MapMarkerAnimationActivity类

  • 以下是MapMarkerAnimationActivity类部分代码

控件响应事件

public void setAnimationFlag(View view) {
    boolean checked = ((RadioButton) view).isChecked();
    int id = view.getId();
    if (!checked)
        return;

    List<String> flags;
    if (id == R.id.frameAnimation) {
        flags = Arrays.asList(
                MapMarkerAnimation.FRAME_ANIMATION,
                MapMarkerAnimation.FRAME_ANIMATION,
                MapMarkerAnimation.FRAME_ANIMATION);
    } else if (id == R.id.animation) {
        flags = Arrays.asList(
                MapMarkerAnimation.TRANSFORMATION_ANIMATION,
                MapMarkerAnimation.ROTATE_ANIMATION,
                MapMarkerAnimation.ALPHA_ANIMATION,
                MapMarkerAnimation.SCALE_ANIMATION,
                MapMarkerAnimation.SINGLE_SCALE_ANIMATION,
                MapMarkerAnimation.ANIMATION_SET);
    } else {
        return;
    }
    mapMarkerAnimation.setFlags(flags);
}

运行效果图

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值