The Method of Setting Map Scaling Proportion in ArcGis
mMapView.setViewpointScaleAsync(scale);
demand
Click on the zoom button (+"-) on the map and let the map zoom according to the map layer. For example, a map contains the following layers. Each layer has a zoom scale. When we click on the zoom button (+"-), we need to set the zoom scale of the map according to the different level s below.
"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
}
]
code implementation
1. Layer Information Acquisition Tool Class
In order to zoom by layer, we need to get the layer information of the corresponding map service first. The tool class ReturnJson.java is used. We should pay attention to the networking request and execute it in the sub-thread. Using URL format is "your map server url"+? f=pjson, for example:
http://119.97.224.2:8399/PBS/rest/services/MapsRoad/MapServer?f=pjson
Note that your map service address does not end with'/'. It should be in the same format as the example, followed directly by MapServer? f=pjson.
public class ReturnJson {
public ReturnJson(String strURL) {
//Judge 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();
}
}
}
// Save the scaling ratio in parsing 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");
for (int i = 0; i < jsonArray_lods.length(); i++) {
TileInfoBean.LodsBean lodsBean = new TileInfoBean.LodsBean();
JSONObject jsonObject3 = (JSONObject) jsonArray_lods.opt(i);
lodsBean.setLevel(jsonObject3.getInt("level"));
lodsBean.setResolution(jsonObject3.getDouble("resolution"));
lodsBean.setScale(jsonObject3.getDouble("scale"));
list.add(lodsBean);
}
infoBean.setLods(list);
MyApplication.getInstance().setTileInfoBean(infoBean);
} catch (Exception e) {
// TODO: handle exception
}
}
}
The related tool class in the code, MyUtils.isUrl(strURL)
/**
* Match URL address
*/
public static boolean isUrl(String str) {
return match(str, "(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]");
}
/**
* Regular Expression Matching
* @param text Text to be matched
* @param reg regular expression
* @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();
}
The related entity class in the code, TileInfoBean.java, because I only need layer information, so the defined entity class only contains layer information, if there are other requirements can be redefined.
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. Use of Layer Information Acquisition Tool Class
Called when loading the map, be careful to execute in the sub-thread
new Thread(new Runnable() {
@Override
public void run() {
new ReturnJson(url); //Scaling Ratio of Stored Maps
}
}).start();
3. Click and zoom
case R.id.scale_max: // + operation
changeScale(MAX);
break;
case R.id.scale_min: // - operation
changeScale(MIN);
break;
private double CurrentScale = 15500;
...
//Changing Map Scaling Ratio by Layer
private void changeScale(String type) {
TileInfoBean bean = instance.getTileInfoBean();
if (bean == null) {
new CenterHintToast(MainActivity.this, "Failed to obtain scaling ratio");
return;
}
List<TileInfoBean.LodsBean> lods = bean.getLods();
if (lods == null || lods.size() <= 0) return;
double mapScale = mMapView.getMapScale();
for (int i = 0; i < lods.size() - 1; i++) {
if (MAX.equals(type)) { // + Operations (enlarging maps, reducing display areas)
if (mapScale <= lods.get(i).getScale() && mapScale > lods.get(i+1).getScale()) {
CurrentScale = lods.get(i+1).getScale();
}
} else if (MIN.equals(type)) { // - Operations (Reducing Maps, Enlarging Display Areas)
if (mapScale < lods.get(i).getScale() && mapScale >= lods.get(i+1).getScale()) {
CurrentScale = lods.get(i).getScale();
}
}
}
mMapView.setViewpointScaleAsync(CurrentScale);
}
The above for loop uses I < lods. size () - 1 instead of I < lods. size () to prevent subscripts from crossing the bounds, because the operation uses i+1
4, the end
ok, so that's it. With the above code, when the map is zoomed to the maximum or minimum scale, the map will no longer zoom, and the code will still execute, except that the zoom ratio set for the map will not change the value of CurrentScale.
In addition, it doesn't matter if you zoom the map using gesture recognition before clicking on the zoom button "+"-", because the code above takes the current zoom ratio of the map for calculation.