GIS地图学习笔记六之按图层缩放地图
目录
ArcGis中设置地图缩放比例的方法
mMapView.setViewpointScaleAsync(scale);
需求
点击地图上的缩放按钮“+”“-” ,让地图按照地图的图层进行缩放,比如一个地图包含以下图层,每一个图层都有一个缩放比例scale,就是我们在点击缩放按钮“+”“-” 的时候需要按照下面的不同层级(level)的缩放比(scale)来设置地图的缩放比。
"lods": [
{
"level": 0,
"resolution": 0.009746272279880825,
"scale": 4096000
},
{
"level": 1,
"resolution": 0.004873136139940413,
"scale": 2048000
},
{
"level": 2,
"resolution": 0.0024365680699702063,
"scale": 1024000
},
{
"level": 3,
"resolution": 0.0012182840349851032,
"scale": 512000
},
{
"level": 4,
"resolution": 6.091420174925516E-4,
"scale": 256000
},
{
"level": 5,
"resolution": 3.045710087462758E-4,
"scale": 128000
},
{
"level": 6,
"resolution": 1.522855043731379E-4,
"scale": 64000
},
{
"level": 7,
"resolution": 7.614275218656895E-5,
"scale": 32000
},
{
"level": 8,
"resolution": 3.8071376093284474E-5,
"scale": 16000
},
{
"level": 9,
"resolution": 1.9035688046642237E-5,
"scale": 8000
},
{
"level": 10,
"resolution": 9.517844023321119E-6,
"scale": 4000
},
{
"level": 11,
"resolution": 4.758922011660559E-6,
"scale": 2000
},
{
"level": 12,
"resolution": 2.3794610058302796E-6,
"scale": 1000
},
{
"level": 13,
"resolution": 1.1897305029151398E-6,
"scale": 500
}
]
代码实现
1、图层信息获取工具类
要实现按图层缩放,我们需要先来获取对应地图服务的图层信息,使用的工具类ReturnJson.java
,使用handler 返回地图服务地址、地图最大缩放比和最小缩放比,注意有联网请求,需要在子线程中执行。使用url格式是“your map server url ”+”?f=pjson” , 例如:
http://119.97.224.2:8399/PBS/rest/services/MapsRoad/MapServer?f=pjson
注意你的地图服务地址不要用 “/” 结尾,要和示例相同的格式 ,直接在MapServer后面接?f=pjson 。
public class ReturnJson {
private Handler mHandler;
private String mURL;
public ReturnJson(String strURL, Handler handler) {
this.mHandler = handler;
this.mURL = strURL;
//判断strURL
String end = "";
if (!TextUtils.isEmpty(strURL)) {
end = strURL.substring(strURL.length() - 1, strURL.length());
}else {
return;
}
HttpURLConnection httpConnection = null;
try {
if (!MyUtils.isUrl(strURL))return;
if ("/".equals(end)) {
strURL = strURL.substring(0,strURL.length() - 1);
}
URL url = new URL(strURL+"?f=pjson");
byte[] buf = new byte[1024];
httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.connect();
InputStream in = httpConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuffer response = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
String string = response.toString();
httpConnection.disconnect();
ExplainJson(string);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (httpConnection != null){
httpConnection.disconnect();
}
}
}
// 解析json中缩放比率保存起来
private void ExplainJson(String retStr) {
try {
TileInfoBean infoBean = new TileInfoBean();
ArrayList<TileInfoBean.LodsBean> list = new ArrayList<>();
JSONObject tileInfo = new JSONObject(retStr).getJSONObject("tileInfo");
JSONArray jsonArray_lods = tileInfo.getJSONArray("lods");
if (jsonArray_lods!=null&&jsonArray_lods.length()>0){
//最大值的缩放比
JSONObject jsonObjectMax = (JSONObject) jsonArray_lods.opt(0);
double fastScale = jsonObjectMax.getDouble("scale");
//最小值的缩放比
JSONObject jsonObjectMin = (JSONObject) jsonArray_lods.opt(jsonArray_lods.length()-1);
double lastScale = jsonObjectMin.getDouble("scale");
Message message = new Message();
message.what = 13;
Bundle bundle = new Bundle();
bundle.putString("url",mURL);
bundle.putDouble("fastScale",fastScale);
bundle.putDouble("lastScale",lastScale);
message.setData(bundle);
mHandler.sendMessage(message);
}
for (int i = 0; i < jsonArray_lods.length(); i++) {
TileInfoBean.LodsBean lodsBean = new TileInfoBean.LodsBean();
JSONObject jsonObject3 = (JSONObject) jsonArray_lods.opt(i);
int level = jsonObject3.getInt("level");
double scale = jsonObject3.getDouble("scale");
double resolution = jsonObject3.getDouble("resolution");
lodsBean.setLevel(level);
lodsBean.setResolution(resolution);
lodsBean.setScale(scale);
list.add(lodsBean);
}
infoBean.setLods(list);
MyApplication.getInstance().setTileInfoBean(infoBean);
} catch (Exception e) {
// TODO: handle exception
}
}
}
代码中相关的工具类,MyUtils.isUrl(strURL)
/**
* 匹配URL地址
*/
public static boolean isUrl(String str) {
return match(str, "(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]");
}
/**
* 正则表达式匹配
* @param text 待匹配的文本
* @param reg 正则表达式
* @return
*/
private static boolean match(String text, String reg) {
if (TextUtils.isEmpty(text) || TextUtils.isEmpty(reg)) return false;
return Pattern.compile(reg).matcher(text).matches();
}
代码中相关的实体类,TileInfoBean.java
,因为我只需要图层信息,所以定义的实体类只包含图层的相关信息,如果有其他需求可以自己重新定义。
public class TileInfoBean implements Parcelable{
private List<LodsBean> lods;
public List<LodsBean> getLods() {
return lods;
}
public void setLods(List<LodsBean> lods) {
this.lods = lods;
}
protected TileInfoBean(Parcel in) {
}
public TileInfoBean() {
}
public static final Creator<TileInfoBean> CREATOR = new Creator<TileInfoBean>() {
@Override
public TileInfoBean createFromParcel(Parcel in) {
return new TileInfoBean(in);
}
@Override
public TileInfoBean[] newArray(int size) {
return new TileInfoBean[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
public static class LodsBean {
private int level;
private double resolution;
private double scale;
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public double getResolution() {
return resolution;
}
public void setResolution(double resolution) {
this.resolution = resolution;
}
public double getScale() {
return scale;
}
public void setScale(double scale) {
this.scale = scale;
}
}
}
2、加载地图,获取图层信息
在加载地图的时候调用,注意要在子线程中执行
new Thread(new Runnable() {
@Override
public void run() {
new ReturnJson(url,mHandler); //存地图缩放比例
}
}).start();
3、点击缩放
case R.id.scale_max: // + 运算
changeScale(MAX);
break;
case R.id.scale_min: // - 运算
changeScale(MIN);
break;
private double CurrentScale = 15500;
...
//改变地图缩放比例--按图层
private void changeScale(String type) {
TileInfoBean bean = instance.getTileInfoBean();
if (bean == null) {
new CenterHintToast(MainActivity.this, "获取缩放比例失败");
return;
}
List<TileInfoBean.LodsBean> lods = bean.getLods();
if (lods == null || lods.size() <= 0) return;
double mapScale = mMapView.getMapScale();
double fastScale = lods.get(0).getScale();
double lastScale = lods.get(lods.size() - 1).getScale();
if (mapScale>=fastScale&&MIN.equals(type))return;
if (mapScale<=lastScale&&MAX.equals(type))return;
for (int i = 0; i < lods.size() - 1; i++) {
if (MAX.equals(type)) { // + 运算(放大地图、显示区域变小)
if (mapScale <= lods.get(i).getScale() && mapScale > lods.get(i+1).getScale()) {
CurrentScale = lods.get(i+1).getScale();
}
} else if (MIN.equals(type)) { // - 运算(缩小地图、显示区域变大)
if (mapScale < lods.get(i).getScale() && mapScale >= lods.get(i + 1).getScale()) {
CurrentScale = lods.get(i).getScale();
}
}
}
mMapView.setViewpointScaleAsync(CurrentScale);
}
上面for
循环的时候使用i < lods.size() - 1
而不是i < lods.size()
是为了防止下标越界,因为运算使用了i+1
4、利用图层信息配置地图最大、最小缩放比
获取地图配置信息成功后,利用handler传递信息,配置地图最大和最小缩放比,并设置地图中心点及当前显示比例。
//--获取地图配置信息成功
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 13:
Bundle data = msg.getData();
String url = data.getString("url");
MinScale = data.getDouble("fastScale");
MaxScale = data.getDouble("lastScale");
ArcGISTiledLayer tiledLayer = new ArcGISTiledLayer(url);
tiledLayer.setMinScale(MinScale); //控制缩小,数值越大,缩小倍数越大,看的范围越广
tiledLayer.setMaxScale(MaxScale); //控制放大,数值越小,放大倍数越高
Basemap basemap = new Basemap(tiledLayer);
mArcGISMap = new ArcGISMap(basemap);
mMapView.setMap(mArcGISMap);
Point point = CoordinateFormatter.fromLatitudeLongitude(center, SpatialReferences.getWgs84());
mMapView.setViewpointCenterAsync(point, CurrentScale);
break;
}
}
};
5、结束
ok,到这里就写完了,使用上面的代码,当地图缩放到最大或最小比例之后,地图将不再缩放,代码还是会执行,只是给地图设置的缩放比CurrentScale
的数值不会变化。
另外,如果你在点击缩放按钮“+”“-” 之前先使用手势识别进行了地图缩放也没有关系,因为上面的代码取的是地图当前的缩放比进行计算的。
转载自:https://blog.csdn.net/m0_37168878/article/details/79081602