一、概述
上一节中我们了解到地图的定位,图层切换,离线地图等基础操作,接下来学习地图的基本操作。
二、本章内容
--- 地图交互设置
--- 地图绘制
1.地图交互设置
在使用地图的时候,不可避免的会涉及到与地图交互问题,如滑动手势,地图缩放,地图旋转,地图logo位置等。我们可以根据需要来决定是否开启某些交互功能。主要用到的就是高德地图API中的 UiSettings 类。通过AMap实例可以获取到UiSettings的实例 uiSettings = aMap.getUiSettings();
①手势设置
//开启放缩手势
uiSettings.setZoomGesturesEnabled(true);
//开启滑动手势
uiSettings.setScrollGesturesEnabled(true);
//开启旋转手势
uiSettings.setRotateGesturesEnabled(true);
//开启双指倾斜手势
uiSettings.setTiltGesturesEnabled(true);
//开启全部手势
uiSettings.setAllGesturesEnabled(true);
//指定手势中心点
//aMap.setPointToCenter(100,100);
//开启中心为手势中心
uiSettings.setGestureScaleByMapCenter(true);
上面这些功能在一般情况下,默认是开启的。当我们有特殊的需求时可以适当的关闭某些手势。
②地图缩放
//是否允许显示地图缩放按钮
uiSettings.setZoomControlsEnabled(true);
//是否允许收拾手势缩放地图
uiSettings.setZoomGesturesEnabled(true);
//设置双击地图放大在地图中心位置放大,false则是在点击位置放大
uiSettings.setZoomInByScreenCenter(true);
//地图缩放按钮的位置
uiSettings.setZoomPosition(AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM);
//AMapOptions.ZOOM_POSITION_RIGHT_CENTER
//AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM
//获取地图缩放按钮位置
Log.e(TAG, "settingZoom: " + uiSettings.getZoomPosition());
③将屏幕中心移动到指定经纬度
//这个类就是设置地图移动的参数,CameraPosition,参数1---要移动到的经纬度,
//参数2---地图的放缩级别zoom,参数3---地图倾斜度,参数4---地图的旋转角度
CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(
new CameraPosition(new LatLng(30.67, 104.07), 10, 0, 0));
//带动画的移动,aMap添加动画监听时,会有动画效果。不添加不会开启动画
aMap.animateCamera(mCameraUpdate, 5000, new AMap.CancelableCallback() {
@Override
public void onFinish() {
}
@Override
public void onCancel() {
}
});
//不带动画的移动
aMap.moveCamera(mCameraUpdate);
④其他设置
//是否显示指南针
uiSettings.setCompassEnabled(true);
//开启比例尺
uiSettings.setScaleControlsEnabled(true);
// 设置logo位置
uiSettings.setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_CENTER);
//AMapOptions.LOGO_POSITION_BOTTOM_LEFTLOGO(左边)
//AMapOptions.LOGO_MARGIN_BOTTOMLOGO(底部)
//AMapOptions.LOGO_MARGIN_RIGHTLOGO(右边)
//AMapOptions.LOGO_POSITION_BOTTOM_CENTER(地图底部居中)
//AMapOptions.LOGO_POSITION_BOTTOM_LEFT(地图左下角)
//AMapOptions.LOGO_POSITION_BOTTOM_RIGHT (地图右下角)
//显示默认的定位按钮
uiSettings.setMyLocationButtonEnabled(true);
// 可触发定位并显示当前位置
aMap.setMyLocationEnabled(true);
//这里设置定位为了在点击定位按钮后,显示地图定位的位置方便查看
//注意这里有个坑,在点击定位后发现定位到了默认的位置(海里面),造成这种情况并不是权限和代码的问题,
//遇到这种情况时,需要手动将GPS定位打开就OK了
MyLocationStyle mls = new MyLocationStyle();
mls.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);
aMap.setMyLocationEnabled(true);
aMap.setMyLocationStyle(mls);
代码
public class InteractiveMapActivity extends BaseActivity {
@BindView(R.id.a_map_view)
MapView aMapView;
@BindView(R.id.button)
Button button;
@BindView(R.id.button2)
Button button2;
@BindView(R.id.button3)
Button button3;
@BindView(R.id.button4)
Button button4;
private Unbinder binder;
private UiSettings uiSettings;
private AMap aMap;
private static final String TAG = "CF";
@Override
public void setContentView(@Nullable Bundle savedInstanceState) {
setContentView(R.layout.acticity_interactive);
binder = ButterKnife.bind(this);
aMapView.onCreate(savedInstanceState);
}
@Override
public void initData() {
aMap = aMapView.getMap();
uiSettings = aMap.getUiSettings();
//设置地图缩放
settingZoom();
//是否显示指南针
uiSettings.setCompassEnabled(true);
//开启比例尺
uiSettings.setScaleControlsEnabled(true);
// 设置logo位置
uiSettings.setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_CENTER);
//AMapOptions.LOGO_POSITION_BOTTOM_LEFTLOGO(左边)
//AMapOptions.LOGO_MARGIN_BOTTOMLOGO(底部)
//AMapOptions.LOGO_MARGIN_RIGHTLOGO(右边)
//AMapOptions.LOGO_POSITION_BOTTOM_CENTER(地图底部居中)
//AMapOptions.LOGO_POSITION_BOTTOM_LEFT(地图左下角)
//AMapOptions.LOGO_POSITION_BOTTOM_RIGHT (地图右下角)
//显示默认的定位按钮
uiSettings.setMyLocationButtonEnabled(true);
// 可触发定位并显示当前位置
aMap.setMyLocationEnabled(true);
//这里设置定位为了在点击定位按钮后,显示地图定位的位置方便查看
//注意这里有个坑,在点击定位后发现定位到了默认的位置(海里面),造成这种情况并不是权限和代码的问题,
//遇到这种情况时,需要手动将GPS定位打开就OK了
MyLocationStyle mls = new MyLocationStyle();
mls.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);
aMap.setMyLocationEnabled(true);
aMap.setMyLocationStyle(mls);
setGestures();
}
private void setGestures() {
//开启放缩手势
uiSettings.setZoomGesturesEnabled(true);
//开启滑动手势
uiSettings.setScrollGesturesEnabled(true);
//开启旋转手势
uiSettings.setRotateGesturesEnabled(true);
//开启双指倾斜手势
uiSettings.setTiltGesturesEnabled(true);
//开启全部手势
uiSettings.setAllGesturesEnabled(true);
//指定手势中心点
// aMap.setPointToCenter(100,100);
//开启中心为手势中心
uiSettings.setGestureScaleByMapCenter(true);
}
private void settingZoom() {
//是否允许显示地图缩放按钮
uiSettings.setZoomControlsEnabled(true);
//是否允许收拾手势缩放地图
uiSettings.setZoomGesturesEnabled(true);
//设置双击地图放大在地图中心位置放大,false则是在点击位置放大
uiSettings.setZoomInByScreenCenter(true);
//地图缩放按钮的位置
uiSettings.setZoomPosition(AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM);
// AMapOptions.ZOOM_POSITION_RIGHT_CENTER
// AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM
//获取地图缩放按钮位置
Log.e(TAG, "settingZoom: " + uiSettings.getZoomPosition());
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onResume() {
super.onResume();
aMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
aMapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
aMapView.onDestroy();
binder.unbind();
super.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
aMapView.onSaveInstanceState(outState);
}
private void moveToTargetPosition() {
//这个类就是设置地图移动的参数,CameraPosition,参数1---要移动到的经纬度,参数2---地图的放缩级别zoom,参数3---地图倾斜度,参数4---地图的旋转角度
CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(
new CameraPosition(new LatLng(30.67, 104.07), 10, 0, 0));
//带动画的移动
aMap.animateCamera(mCameraUpdate, 5000, new AMap.CancelableCallback() {
@Override
public void onFinish() {
}
@Override
public void onCancel() {
}
});
//不带动画的移动
aMap.moveCamera(mCameraUpdate);
}
@OnClick({R.id.button, R.id.button2, R.id.button3, R.id.button4})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.button:
moveToTargetPosition();
break;
case R.id.button2:
showCustomMapBounds(true);
break;
case R.id.button3:
showCustomMapBounds(false);
break;
case R.id.button4:
screenCapture();
break;
}
}
private void showCustomMapBounds(boolean enable) {
if (enable) {
LatLng southwestLatLng = new LatLng(30.67, 104.07);
LatLng northeastLatLng = new LatLng(30.77, 104.17);
LatLngBounds latLngBounds = new LatLngBounds(southwestLatLng, northeastLatLng);
aMap.setMapStatusLimits(latLngBounds);
} else {
aMap.setMapStatusLimits(null);
}
}
/** 地图截屏 */
private void screenCapture() {
aMap.getMapScreenShot(new AMap.OnMapScreenShotListener() {
@Override
public void onMapScreenShot(Bitmap bitmap) {
}
@Override
public void onMapScreenShot(Bitmap bitmap, int i) {
if (null == bitmap) {
return;
}
try {
FileOutputStream fos = new FileOutputStream(
Environment.getExternalStorageDirectory() + "/MyMap/"
+ "test" + ".png");
boolean b = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
try {
fos.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
StringBuffer buffer = new StringBuffer();
if (b)
buffer.append("截屏成功 ");
else {
buffer.append("截屏失败 ");
}
if (i != 0)
buffer.append("地图渲染完成,截屏无网格");
else {
buffer.append("地图未渲染完成,截屏有网格");
}
Toast.makeText(InteractiveMapActivity.this, buffer.toString(), Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
});
}
}
2.地图绘制
①绘制marker
//添加一个默认的marker
LatLng latLng = new LatLng(30.67, 104.07);
MarkerOptions markerOptions = new MarkerOptions()
//必须,设置经纬度
.position(latLng)
//设置title
.title("成都")
//设置内容
.snippet("marker内容");
aMap.addMarker(markerOptions);
//添加一个自定义的marker
LatLng latLng1 = new LatLng(30.67, 104.07);
MarkerOptions mo = new MarkerOptions();
mo.position(latLng1)
//设置透明度
.alpha(0.6f)
//设置title
.title("自定义标题")
//设置内容
.snippet("自定义内容")
//设置锚点,锚点是marker图标的位置,(0,0)-(1,1)
.anchor(0.5f, 1.0f)
//是否可见
.visible(true)
//是否可拖动,注意这里需要长按marker后,才可以拖动
.draggable(true)
//添加自定义marker图标
.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(
getResources(), R.drawable.location)))
//是否平贴地图,倾斜地图,感觉marker不是竖直而是粘贴在地面上
.setFlat(false)
//是否允许显示infoWindow
.infoWindowEnable(true)
//z轴方向的值,重叠
.zIndex(10)
//设置marker图片旋转角度,正北开始逆时针方向计算
.rotateAngle(30.0f)
//设置infoWindow的偏移位置
.setInfoWindowOffset(0, 0);
aMap.addMarker(mo);
//添加一个动画marker
LatLng latLng2 = new LatLng(30.68, 104.07);
MarkerOptions mo1 = new MarkerOptions().icon(BitmapDescriptorFactory.fromBitmap(
BitmapFactory.decodeResource(getResources(), R.drawable.location)))
.title("动画").snippet("生长动画").position(latLng2);
Marker m = aMap.addMarker(mo1);
final Animation animation = new ScaleAnimation(0, 1, 0, 1);
animation.setDuration(2000);
animation.setInterpolator(new AccelerateInterpolator());
m.setAnimation(animation);
m.startAnimation();
//添加一个marker的点击事件
aMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
//当点击的时候添加生长动画
marker.setAnimation(animation);
marker.startAnimation();
//这里在添加点击监听事件后,原来的InfoWindow被取消了,可以在回调方法中手动实现
if (marker.isInfoWindowShown()) {
marker.hideInfoWindow();
} else {
marker.showInfoWindow();
}
return true;
}
});
//添加拖拽事件,注意此回调方法只对设置了可拖拽的marker生效
aMap.setOnMarkerDragListener(new AMap.OnMarkerDragListener() {
@Override
public void onMarkerDragStart(Marker marker) {
Log.e(TAG, "onMarkerDragStart: 被拖拽的Marker标题为->" + marker.getTitle());
}
@Override
public void onMarkerDrag(Marker marker) {
}
@Override
public void onMarkerDragEnd(Marker marker) {
Log.e(TAG, "onMarkerDragEnd: 拖拽完后Maker的经纬度-> lat="
+marker.getPosition().latitude + " lng=" + marker.getPosition().longitude);
}
});
//自定义infoWindow
aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
View view;
@Override
public View getInfoWindow(Marker marker) {
if (view == null) {
view = LayoutInflater.from(DrawActivity.this).inflate(R.layout.custom_info_window, null);
}
findViews(marker, view);
return view;
}
@Override
public View getInfoContents(Marker marker) {
return null;
}
});
aMap.setOnInfoWindowClickListener(new AMap.OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick(Marker marker) {
Log.e(TAG, "onInfoWindowClick: 标题为:" + marker.getTitle() + " 的InfoWindow被点击了");
}
});
/**
* 在点击marker显示infoWindow是,找到相应的控件,修改显示
*/
private void findViews(Marker marker, View view) {
TextView name = view.findViewById(R.id.name);
TextView address = view.findViewById(R.id.address);
name.setText(marker.getTitle());
address.setText(marker.getSnippet());
}
②绘制线
ArrayList<LatLng> points = new ArrayList<>();
points.add(new LatLng(30.66, 104.06));
points.add(new LatLng(30.66, 104.07));
points.add(new LatLng(30.67, 104.07));
points.add(new LatLng(30.67, 104.06));
points.add(new LatLng(30.66, 104.06));
aMap.addPolyline(new PolylineOptions().addAll(points).width(10).color(Color.argb(255, 1, 1, 1)));
ArrayList<LatLng> latlngs = new ArrayList<>();
latlngs.add(new LatLng(30.6595, 104.0595));
latlngs.add(new LatLng(30.6595, 104.0705));
latlngs.add(new LatLng(30.6705, 104.0705));
latlngs.add(new LatLng(30.6705, 104.0595));
latlngs.add(new LatLng(30.6595, 104.0595));
ArrayList<Integer> a = new ArrayList<>();
a.add(0);
a.add(1);
a.add(2);
a.add(3);
//为每条线段添加纹理
ArrayList<BitmapDescriptor> b = new ArrayList<>();
b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.bb)));
b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aa)));
b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.bb)));
b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aa)));
aMap.addPolyline(new PolylineOptions()
//添加多有的经纬度点
.addAll(latlngs)
//绘制线宽
.width(20)
//是否开启纹理贴图
.setUseTexture(true)
//纹理贴图段的index数组
.setCustomTextureIndex(a)
//纹理贴图每段对应的纹理资源图
.setCustomTextureList(b)
//是否虚线,纹理贴图时无效
.setDottedLine(false)
//绘制成大地线
.geodesic(false)
//设置纹理样式
.setCustomTexture(BitmapDescriptorFactory.fromBitmap(
BitmapFactory.decodeResource(getResources(), R.drawable.aa)))
//设置画线的颜色
.color(Color.argb(255, 1, 1, 1))
);
③绘制面
LatLng latLng = new LatLng(30.665, 104.065);
//绘制一个圆
Circle circle = aMap.addCircle(new CircleOptions()
.center(latLng)
.radius(500)
.fillColor(Color.argb(30, 1, 1, 1))
.strokeColor(Color.argb(255, 1, 1, 1))
.strokeWidth(10)
);
circle.setStrokeDottedLineType(0);
// //绘制一个矩形,多边形跟这个一样的
// aMap.addPolygon(new PolygonOptions()
// .addAll(createRectangle(new LatLng(30.665, 104.065), 0.01, 0.01))
// .fillColor(Color.LTGRAY).strokeColor(Color.RED).strokeWidth(5));
//
// // 绘制一个椭圆
// PolygonOptions options = new PolygonOptions();
// int numPoints = 400;
// float semiHorizontalAxis = 2f;
// float semiVerticalAxis = 0.5f;
// double phase = 2 * Math.PI / numPoints;
// for (int i = 0; i <= numPoints; i++) {
// options.add(new LatLng(
// 30.665 + semiVerticalAxis * Math.sin(i * phase),
// 104.065 + semiHorizontalAxis * Math.cos(i * phase)
// ));
// }
//
// Polygon polygon = aMap.addPolygon(options
// .strokeWidth(25)
// .strokeColor(Color.argb(50, 1, 1, 1))
// .fillColor(Color.argb(50, 1, 1, 1))
// );
/**
* 生成一个长方形的四个坐标点
*/
private List<LatLng> createRectangle(LatLng center, double halfWidth,
double halfHeight) {
List<LatLng> latLngs = new ArrayList<LatLng>();
latLngs.add(new LatLng(center.latitude - halfHeight, center.longitude - halfWidth));
latLngs.add(new LatLng(center.latitude - halfHeight, center.longitude + halfWidth));
latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude + halfWidth));
latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude - halfWidth));
return latLngs;
}
④绘制热力图
LatLng center = new LatLng(30.665, 104.065);
//第一步准备数据
LatLng[] data = new LatLng[100];
for (int i = 0; i < data.length; i++) {
double offsetLat = Math.random();
offsetLat /= 10;
double offsetLng = Math.random();
offsetLng /= 10;
LatLng one = new LatLng(center.latitude + offsetLat, center.longitude + offsetLng);
data[i] = one;
}
int[] colors = {Color.rgb(0, 255, 0), Color.rgb(255, 0, 0)};
float[] startPoints = {0.0f, 1.0f};
Gradient gradient = new Gradient(colors, startPoints);
//初始化热力图
HeatmapTileProvider.Builder builder = new HeatmapTileProvider.Builder();
builder.data(Arrays.asList(data))
// .gradient(gradient)
;
HeatmapTileProvider provider = builder.build();
// 初始化 TileOverlayOptions
TileOverlayOptions tileOverlayOptions = new TileOverlayOptions();
// 设置瓦片图层的提供者
tileOverlayOptions.tileProvider(provider);
// 向地图上添加 TileOverlayOptions 类对象
aMap.addTileOverlay(tileOverlayOptions);
⑤绘制长方体
/**------------------------------------地图上绘制3D图形------------------------------*/
aMap.showMapText(false);
aMap.showBuildings(false);
aMap.setCustomRenderer(new CubeMapRender(aMap));
/**------------------------------------地图上绘制3D图形-----------------------------*/
public class CubeMapRender implements CustomRenderer {
private float[] translate_vector = new float[4];
public static float SCALE = 0.005F;// 缩放暂时使用这个
private LatLng center = new LatLng(30.665, 104.065);// 北京市经纬度
private Cube cube ;
private AMap aMap;
float width, height;
public CubeMapRender(AMap aMap) {
this.aMap = aMap;
aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(center,15));
}
float[] mvp = new float[16];
@Override
public void onDrawFrame(GL10 gl) {
if(cube != null) {
Matrix.setIdentityM(mvp, 0);
//偏移
PointF pointF = aMap.getProjection().toOpenGLLocation(center);
Matrix.multiplyMM(mvp,0, aMap.getProjectionMatrix(),0,aMap.getViewMatrix(),0);
Matrix.translateM(mvp, 0 , pointF.x , pointF.y , 0);
int scale = 1;
Matrix.scaleM(mvp, 0 , scale, scale, scale);
cube.drawES20(mvp);
}
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
this.width = width;
this.height = height;
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//创建cube
cube = new Cube(0.2f,0.2f,0.2f);
cube.initShader();
}
@Override
public void OnMapReferencechanged() {
}
}
class Cube {
ArrayList<Float> verticesList = new ArrayList<Float>();
short indices[] = {
0, 4, 5,
0, 5, 1,
1, 5, 6,
1, 6, 2,
2, 6, 7,
2, 7, 3,
3, 7, 4,
3, 4, 0,
4, 7, 6,
4, 6, 5,
3, 0, 1,
3, 1, 2,
};
//
float[] colors = {
1f, 0f, 0f, 1f, // vertex 0 red
0f, 1f, 0f, 1f, // vertex 1 green
0f, 0f, 1f, 1f, // vertex 2 blue
1f, 1f, 0f, 1f, // vertex 3
0f, 1f, 1f, 1f, // vertex 4
1f, 0f, 1f, 1f, // vertex 5
0f, 0f, 0f, 1f, // vertex 6
1f, 1f, 1f, 1f, // vertex 7
};
public Cube(float width, float height, float depth) {
// 地图坐标系比较大,将值放大以免太小看不见
width *= 10000;
height *= 10000;
depth *= 10000;
width /= 2;
height /= 2;
depth /= 2;
//尽量不要让z轴有负数出现
float vertices1[] = {
-width, -height, -0,
width, -height, -0,
width, height, -0,
-width, height, -0,
-width, -height, depth,
width, -height, depth,
width, height, depth,
-width, height, depth,
};
for (int i = 0; i < vertices1.length; i++) {
verticesList.add(vertices1[i]);
}
//index
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(indices.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
indexBuffer = byteBuffer.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
//color
ByteBuffer byteBuffer1 = ByteBuffer.allocateDirect(colors.length * 4);
byteBuffer1.order(ByteOrder.nativeOrder());
colorBuffer = byteBuffer1.asFloatBuffer();
colorBuffer.put(colors);
colorBuffer.position(0);
init();
}
private FloatBuffer vertextBuffer;
private ShortBuffer indexBuffer;
private FloatBuffer colorBuffer;
private void init() {
if (vertextBuffer == null) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(verticesList.size() * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vertextBuffer = byteBuffer.asFloatBuffer();
}
vertextBuffer.clear();
for (Float f : verticesList) {
vertextBuffer.put(f);
}
vertextBuffer.position(0);
}
class MyShader {
String vertexShader = "precision highp float;\n" +
" attribute vec3 aVertex;//顶点数组,三维坐标\n" +
" attribute vec4 aColor;//颜色数组,三维坐标\n" +
" uniform mat4 aMVPMatrix;//mvp矩阵\n" +
" varying vec4 color;//\n" +
" void main(){\n" +
" gl_Position = aMVPMatrix * vec4(aVertex, 1.0);\n" +
" color = aColor;\n" +
" }";
String fragmentShader = "//有颜色 没有纹理\n" +
" precision highp float;\n" +
" varying vec4 color;//\n" +
" void main(){\n" +
" gl_FragColor = color;\n" +
" }";
int aVertex,aMVPMatrix,aColor;
int program;
public void create() {
int vertexLocation = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
int fragmentLocation = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(vertexLocation,vertexShader);
GLES20.glCompileShader(vertexLocation);
GLES20.glShaderSource(fragmentLocation,fragmentShader);
GLES20.glCompileShader(fragmentLocation);
program = GLES20.glCreateProgram();
GLES20.glAttachShader(program,vertexLocation);
GLES20.glAttachShader(program,fragmentLocation);
GLES20.glLinkProgram(program);
aVertex = GLES20.glGetAttribLocation(program, "aVertex");
aMVPMatrix = GLES20.glGetUniformLocation(program,"aMVPMatrix");
aColor = GLES20.glGetAttribLocation(program,"aColor");
}
}
MyShader shader;
public void initShader() {
shader = new MyShader();
shader.create();
}
public void drawES20(float[] mvp) {
GLES20.glUseProgram(shader.program);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnableVertexAttribArray(shader.aVertex);
//顶点指针
GLES20.glVertexAttribPointer(shader.aVertex, 3, GLES20.GL_FLOAT, false, 0, vertextBuffer);
//颜色指针
GLES20.glEnableVertexAttribArray(shader.aColor);
GLES20.glVertexAttribPointer(shader.aColor,4, GLES20.GL_FLOAT,false,0,colorBuffer);
GLES20.glUniformMatrix4fv(shader.aMVPMatrix,1,false,mvp,0);
//开始画
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
GLES20.glDisableVertexAttribArray(shader.aVertex);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
}
}
⑥绘制平滑移动的物体
//这里选择一个公交站,获取经过改公交站的一路公交车的路线
//让小车再这个路线上移动
BusStationQuery bsq;
BusStationSearch bss;
bsq = new BusStationQuery("天华一路", "成都");
bss = new BusStationSearch(this, bsq);
bss.setOnBusStationSearchListener(new BusStationSearch.OnBusStationSearchListener() {
@Override
public void onBusStationSearched(BusStationResult busStationResult, int i) {
List<BusStationItem> data = busStationResult.getBusStations();
if (data != null && data.size() > 0) {
final LatLonPoint busStationPoint = data.get(0).getLatLonPoint();
List<BusLineItem> dataBus = data.get(0).getBusLineItems();
if (dataBus != null && dataBus.size() > 0) {
BusLineItem bli = dataBus.get(0);
BusLineQuery blq = new BusLineQuery(
bli.getBusLineId(), BusLineQuery.SearchType.BY_LINE_ID, bli.getCityCode());
blq.setPageSize(10);
blq.setPageNumber(1);
BusLineSearch busLineSearch = new BusLineSearch(getApplicationContext(), blq);
busLineSearch.setOnBusLineSearchListener(new BusLineSearch.OnBusLineSearchListener() {
@Override
public void onBusLineSearched(BusLineResult busLineResult, int i) {
List<LatLonPoint> d = busLineResult.getBusLines().get(0).getDirectionsCoordinates();
List<LatLng> driverPath = new ArrayList<>();
for (LatLonPoint one : d) {
driverPath.add(new LatLng(one.getLatitude(), one.getLongitude()));
}
moveToPosition(busStationPoint.getLatitude(), busStationPoint.getLongitude());
aMap.addPolyline(new PolylineOptions()
.addAll(driverPath)
.width(20)
//是否开启纹理贴图
.setUseTexture(true)
//绘制成大地线
.geodesic(false)
//设置纹理样式
.setCustomTexture(BitmapDescriptorFactory.fromBitmap(
BitmapFactory.decodeResource(getResources(),
R.drawable.custtexture)))
//设置画线的颜色
.color(Color.argb(200, 0, 0, 0)));
final SmoothMoveMarker smoothMarker = new SmoothMoveMarker(aMap);
// 设置滑动的图标
smoothMarker.setDescriptor(BitmapDescriptorFactory.fromResource(
R.mipmap.icon_car));
// 设置滑动的轨迹左边点
smoothMarker.setPoints(driverPath);
// 设置滑动的总时间
smoothMarker.setTotalDuration(30);
// 开始滑动
smoothMarker.startSmoothMove();
}
});
busLineSearch.searchBusLineAsyn();
}
} else {
Log.e(TAG, "onBusStationSearched: no data");
}
Log.e(TAG, "onBusStationSearched: " + i);
}
});
bss.searchBusStationAsyn();
绘制的代码
public class DrawActivity extends BaseActivity {
private static final String TAG = "CF";
@BindView(R.id.draw_map_view)
MapView drawMapView;
private Unbinder binder;
private AMap aMap;
@Override
public void setContentView(@Nullable Bundle savedInstanceState) {
setContentView(R.layout.activity_draw_map);
binder = ButterKnife.bind(this);
drawMapView.onCreate(savedInstanceState);
aMap = drawMapView.getMap();
}
@Override
public void initData() {
//绘制Marker
// drawMarker();
//绘制线段
// drawLine();
//绘制面
// drawSurface();
//绘制热力图
drawThermodynamic();
//绘制3D模型
draw3DModel();
// drawSmoothMove();
}
//绘制平滑移动
private void drawSmoothMove() {
//这里选择一个公交站,获取经过改公交站的一路公交车的路线
//让小车再这个路线上移动
BusStationQuery bsq;
BusStationSearch bss;
bsq = new BusStationQuery("天华一路", "成都");
bss = new BusStationSearch(this, bsq);
bss.setOnBusStationSearchListener(new BusStationSearch.OnBusStationSearchListener() {
@Override
public void onBusStationSearched(BusStationResult busStationResult, int i) {
List<BusStationItem> data = busStationResult.getBusStations();
if (data != null && data.size() > 0) {
final LatLonPoint busStationPoint = data.get(0).getLatLonPoint();
List<BusLineItem> dataBus = data.get(0).getBusLineItems();
if (dataBus != null && dataBus.size() > 0) {
BusLineItem bli = dataBus.get(0);
BusLineQuery blq = new BusLineQuery(bli.getBusLineId(), BusLineQuery.SearchType.BY_LINE_ID, bli.getCityCode());
blq.setPageSize(10);
blq.setPageNumber(1);
BusLineSearch busLineSearch = new BusLineSearch(getApplicationContext(), blq);
busLineSearch.setOnBusLineSearchListener(new BusLineSearch.OnBusLineSearchListener() {
@Override
public void onBusLineSearched(BusLineResult busLineResult, int i) {
List<LatLonPoint> d = busLineResult.getBusLines().get(0).getDirectionsCoordinates();
List<LatLng> driverPath = new ArrayList<>();
for (LatLonPoint one : d) {
driverPath.add(new LatLng(one.getLatitude(), one.getLongitude()));
}
moveToPosition(busStationPoint.getLatitude(), busStationPoint.getLongitude());
aMap.addPolyline(new PolylineOptions()
.addAll(driverPath)
.width(20)
//是否开启纹理贴图
.setUseTexture(true)
//绘制成大地线
.geodesic(false)
//设置纹理样式
.setCustomTexture(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.custtexture)))
//设置画线的颜色
.color(Color.argb(200, 0, 0, 0)));
final SmoothMoveMarker smoothMarker = new SmoothMoveMarker(aMap);
// 设置滑动的图标
smoothMarker.setDescriptor(BitmapDescriptorFactory.fromResource(R.mipmap.icon_car));
// 设置滑动的轨迹左边点
smoothMarker.setPoints(driverPath);
// 设置滑动的总时间
smoothMarker.setTotalDuration(30);
// 开始滑动
smoothMarker.startSmoothMove();
}
});
busLineSearch.searchBusLineAsyn();
}
} else {
Log.e(TAG, "onBusStationSearched: no data");
}
Log.e(TAG, "onBusStationSearched: " + i);
}
});
bss.searchBusStationAsyn();
}
private void draw3DModel() {
moveToDefaultPosition();
aMap.showMapText(false);
aMap.showBuildings(false);
aMap.setCustomRenderer(new CubeMapRender(aMap));
}
/**
* ----------------------------------------热力图---------------------------------------------------------
*/
private void drawThermodynamic() {
moveToDefaultPosition();
LatLng center = new LatLng(30.665, 104.065);
//第一步准备数据
LatLng[] data = new LatLng[100];
for (int i = 0; i < data.length; i++) {
double offsetLat = Math.random();
offsetLat /= 10;
double offsetLng = Math.random();
offsetLng /= 10;
LatLng one = new LatLng(center.latitude + offsetLat, center.longitude + offsetLng);
data[i] = one;
}
int[] colors = {Color.rgb(0, 255, 0), Color.rgb(255, 0, 0)};
float[] startPoints = {0.0f, 1.0f};
Gradient gradient = new Gradient(colors, startPoints);
//初始化热力图
HeatmapTileProvider.Builder builder = new HeatmapTileProvider.Builder();
builder.data(Arrays.asList(data))
// .gradient(gradient)
;
HeatmapTileProvider provider = builder.build();
// 初始化 TileOverlayOptions
TileOverlayOptions tileOverlayOptions = new TileOverlayOptions();
// 设置瓦片图层的提供者
tileOverlayOptions.tileProvider(provider);
// 向地图上添加 TileOverlayOptions 类对象
aMap.addTileOverlay(tileOverlayOptions);
}
/**
* ----------------------------------------热力图---------------------------------------------------------
* */
/**
* -----------------------------------------Marker相关----------------------------------------------------
* */
/**
* 地图上marker相关
*/
private void drawMarker() {
//添加一个默认的marker
LatLng latLng = new LatLng(30.67, 104.07);
MarkerOptions markerOptions = new MarkerOptions()
//必须,设置经纬度
.position(latLng)
//设置title
.title("成都")
//设置内容
.snippet("marker内容");
aMap.addMarker(markerOptions);
//添加一个自定义的marker
LatLng latLng1 = new LatLng(30.67, 104.07);
MarkerOptions mo = new MarkerOptions();
mo.position(latLng1)
//设置透明度
.alpha(0.6f)
//设置title
.title("自定义标题")
//设置内容
.snippet("自定义内容")
//设置锚点,锚点是marker图标的位置,(0,0)-(1,1)
.anchor(0.5f, 1.0f)
//是否可见
.visible(true)
//是否可拖动,注意这里需要长按marker后,才可以拖动
.draggable(true)
//添加自定义marker图标
.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.location)))
//是否平贴地图,倾斜地图,感觉marker不是竖直而是粘贴在地面上
.setFlat(false)
//是否允许显示infoWindow
.infoWindowEnable(true)
//z轴方向的值,重叠
.zIndex(10)
//设置marker图片旋转角度,正北开始逆时针方向计算
.rotateAngle(30.0f)
//设置infoWindow的偏移位置
.setInfoWindowOffset(0, 0);
aMap.addMarker(mo);
//添加一个动画marker
LatLng latLng2 = new LatLng(30.68, 104.07);
MarkerOptions mo1 = new MarkerOptions().icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.location)))
.title("动画").snippet("生长动画").position(latLng2);
Marker m = aMap.addMarker(mo1);
final Animation animation = new ScaleAnimation(0, 1, 0, 1);
animation.setDuration(2000);
animation.setInterpolator(new AccelerateInterpolator());
m.setAnimation(animation);
m.startAnimation();
//添加一个marker的点击事件
aMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
//当点击的时候添加生长动画
marker.setAnimation(animation);
marker.startAnimation();
//这里在添加点击监听事件后,原来的InfoWindow被取消了,可以在回调方法中手动实现
if (marker.isInfoWindowShown()) {
marker.hideInfoWindow();
} else {
marker.showInfoWindow();
}
return true;
}
});
//添加拖拽事件,注意此回调方法只对设置了可拖拽的marker生效
aMap.setOnMarkerDragListener(new AMap.OnMarkerDragListener() {
@Override
public void onMarkerDragStart(Marker marker) {
Log.e(TAG, "onMarkerDragStart: 被拖拽的Marker标题为->" + marker.getTitle());
}
@Override
public void onMarkerDrag(Marker marker) {
}
@Override
public void onMarkerDragEnd(Marker marker) {
Log.e(TAG, "onMarkerDragEnd: 拖拽完后Maker的经纬度-> lat=" + marker.getPosition().latitude + " lng=" + marker.getPosition().longitude);
}
});
//自定义infoWindow
aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
View view;
@Override
public View getInfoWindow(Marker marker) {
if (view == null) {
view = LayoutInflater.from(DrawActivity.this).inflate(R.layout.custom_info_window, null);
}
findViews(marker, view);
return view;
}
@Override
public View getInfoContents(Marker marker) {
return null;
}
});
aMap.setOnInfoWindowClickListener(new AMap.OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick(Marker marker) {
Log.e(TAG, "onInfoWindowClick: 标题为:" + marker.getTitle() + " 的InfoWindow被点击了");
}
});
moveToDefaultPosition();
}
private void moveToDefaultPosition() {
//移动到marker位置
CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(
new CameraPosition(
new LatLng(30.665, 104.065),
15,
0,
0
)
);
aMap.moveCamera(mCameraUpdate);
}
private void moveToPosition(double lat, double lng) {
//移动到marker位置
CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(
new CameraPosition(
new LatLng(lat, lng),
13,
0,
0
)
);
aMap.moveCamera(mCameraUpdate);
}
/**
* 在点击marker显示infoWindow是,找到相应的控件,修改显示
*/
private void findViews(Marker marker, View view) {
TextView name = view.findViewById(R.id.name);
TextView address = view.findViewById(R.id.address);
name.setText(marker.getTitle());
address.setText(marker.getSnippet());
}
/**
* -----------------------------------------Marker相关----------------------------------------------------
*/
/**
* -----------------------------------------Line相关------------------------------------------------------
*/
private void drawLine() {
moveToDefaultPosition();
ArrayList<LatLng> points = new ArrayList<>();
points.add(new LatLng(30.66, 104.06));
points.add(new LatLng(30.66, 104.07));
points.add(new LatLng(30.67, 104.07));
points.add(new LatLng(30.67, 104.06));
points.add(new LatLng(30.66, 104.06));
aMap.addPolyline(new PolylineOptions().addAll(points).width(10).color(Color.argb(255, 1, 1, 1)));
ArrayList<LatLng> latlngs = new ArrayList<>();
latlngs.add(new LatLng(30.6595, 104.0595));
latlngs.add(new LatLng(30.6595, 104.0705));
latlngs.add(new LatLng(30.6705, 104.0705));
latlngs.add(new LatLng(30.6705, 104.0595));
latlngs.add(new LatLng(30.6595, 104.0595));
ArrayList<Integer> a = new ArrayList<>();
a.add(0);
a.add(1);
a.add(2);
a.add(3);
ArrayList<BitmapDescriptor> b = new ArrayList<>();
b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.bb)));
b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aa)));
b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.bb)));
b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aa)));
aMap.addPolyline(new PolylineOptions()
//添加多有的经纬度点
.addAll(latlngs)
//绘制线宽
.width(20)
//是否开启纹理贴图
.setUseTexture(true)
//纹理贴图段的index数组
.setCustomTextureIndex(a)
//纹理贴图每段对应的纹理资源图
.setCustomTextureList(b)
//是否虚线,纹理贴图时无效
.setDottedLine(false)
//绘制成大地线
.geodesic(false)
//设置纹理样式
.setCustomTexture(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aa)))
//设置画线的颜色
.color(Color.argb(255, 1, 1, 1))
);
}
/**
* -----------------------------------------Line相关------------------------------------------------------
*/
/**
* -----------------------------------------绘制几何图形相关------------------------------------------------------
*/
private void drawSurface() {
moveToDefaultPosition();
LatLng latLng = new LatLng(30.665, 104.065);
//绘制一个圆
Circle circle = aMap.addCircle(new CircleOptions()
.center(latLng)
.radius(500)
.fillColor(Color.argb(30, 1, 1, 1))
.strokeColor(Color.argb(255, 1, 1, 1))
.strokeWidth(10)
);
circle.setStrokeDottedLineType(0);
// //绘制一个矩形,多边形跟这个一样的
// aMap.addPolygon(new PolygonOptions()
// .addAll(createRectangle(new LatLng(30.665, 104.065), 0.01, 0.01))
// .fillColor(Color.LTGRAY).strokeColor(Color.RED).strokeWidth(5));
//
// // 绘制一个椭圆
// PolygonOptions options = new PolygonOptions();
// int numPoints = 400;
// float semiHorizontalAxis = 2f;
// float semiVerticalAxis = 0.5f;
// double phase = 2 * Math.PI / numPoints;
// for (int i = 0; i <= numPoints; i++) {
// options.add(new LatLng(
// 30.665 + semiVerticalAxis * Math.sin(i * phase),
// 104.065 + semiHorizontalAxis * Math.cos(i * phase)
// ));
// }
//
// Polygon polygon = aMap.addPolygon(options
// .strokeWidth(25)
// .strokeColor(Color.argb(50, 1, 1, 1))
// .fillColor(Color.argb(50, 1, 1, 1))
// );
}
/**
* 生成一个长方形的四个坐标点
*/
private List<LatLng> createRectangle(LatLng center, double halfWidth,
double halfHeight) {
List<LatLng> latLngs = new ArrayList<LatLng>();
latLngs.add(new LatLng(center.latitude - halfHeight, center.longitude - halfWidth));
latLngs.add(new LatLng(center.latitude - halfHeight, center.longitude + halfWidth));
latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude + halfWidth));
latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude - halfWidth));
return latLngs;
}
/**
* -----------------------------------------绘制几何图形相关------------------------------------------------------
*/
@Override
protected void onResume() {
super.onResume();
drawMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
drawMapView.onPause();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
List<Marker> list = aMap.getMapScreenMarkers();
if (list != null && list.size() > 0) {
for (Marker one : list) {
one.destroy();
}
}
drawMapView.onDestroy();
//这里注意,butterknife注销一定要在所有销毁的最后,否则会出现空指针异常
binder.unbind();
super.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
drawMapView.onSaveInstanceState(outState);
}
}
网友评论