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

You may also like...