Android加载SVG实现交互式地图绘制

Android加载SVG实现交互式地图绘制

    • Android加载SVG实现交互式地图绘制
        • 效果图
        • 实现思路
        • 准备工作
        • 具体实现

效果图

实现思路

  • 下载SVG文件
  • 将svg资源转换成相应的java代码
  • 解析svg/xml文件
  • 自定义MapView
  • 重写OnTouchEvent通过接回调实现交互

准备工作

1.下载SVG文件
下载地址: https://www.amcharts.com/dl/javascript-maps/

2.svg转换为xml文件(可选,也可以直接解析svg文件)
svg转换为xml文件地址:http://inloop.github.io/svg2android/
AndroidStudio可以安装一个SVG2VectorDrawable 直接进行转换

具体实现

首先先把下载好的svg文件放到raw目录下面 ps:下载下来的文件有大小写,放到raw目录下面只能全部小写,不然编译报错
接下来通过java代码将svg文件解析成为List 集合

    public void getCityItemList() {
    new Thread() {
        @Override
        public void run() {
            try {
                List result = new ArrayList<>();
                long startTime = System.currentTimeMillis();
                InputStream inputStream = mContext.getResources().openRawResource(R.raw.china);
                XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
                parser.setInput(inputStream, "utf-8");
                int eventType;
                while ((eventType = parser.getEventType()) != XmlPullParser.END_DOCUMENT) {
                    if (eventType == XmlPullParser.START_TAG) {
                        String name = parser.getName();
                        if ("path".equals(name)) {
                            String id = parser.getAttributeValue(null, "id");
                            String title = parser.getAttributeValue(null, "title");
                            String pathData = parser.getAttributeValue(null, "d");
                            Path path = PathParser.createPathFromPathData(pathData);
                            Region region = new Region();
                            if (path != null) {
                                RectF r = new RectF();
                                //得到Path的矩形边界
                                path.computeBounds(r, true);
                                // 设置区域路径和剪辑描述的区域
                                region.setPath(path, new Region((int) (r.left), (int) (r.top), (int) (r.right), (int) (r.bottom)));
                            }
                            CityItem cityItem = new CityItem();
                            cityItem.setCityId(id);
                            cityItem.setCityName(title);
                            cityItem.setmPath(path);
                            cityItem.setmRegion(region);
                            result.add(cityItem);
                        }
                    }
                    parser.next();
                }
                Message msg = Message.obtain();
                msg.what = LOAD_FINISH;
                msg.obj = result;
                mHander.sendMessage(msg);
                Log.d("TAG", "加载SVG数据结束耗时->" + (System.currentTimeMillis() - startTime));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }.start();
}

svg文件里面的一个path节点对应解析成一个CityItem ,这样就可以遍历解析得到的List 数据去绘制出每一个Path

        for (CityItem cityItem : list) {
        if (!cityItem.equals(selectCity))
            cityItem.onDraw(canvas, mPaint, false);
    }

完成当前操作效果如下

接下来就是加上交互效果,当点击某一个省份的时候,需要给当前选中的省份加上一个描边和不同的颜色。此时实现View的OnTouch方法,去判读用户点击的点是否包含于地图中的某一个省份,如果包含则将当前省份绘制为选中状态

 /**
 * 处理点击事件
 *
 * @param x 点击的X坐标
 * @param y 点击的Y坐标
 */
private boolean handlerTouch(int x, int y) {
    final List list = cityItemList;
    CityItem cityItem = null;
    if (list == null) return false;
    for (CityItem temp : list) {
        if (temp.isOnTouch((int) (x / scale), (int) (y / scale))) {//除以放大倍数
            cityItem = temp;
            break;
        }
    }
    if (cityItem != null && !cityItem.equals(selectCity)) {
        selectCity = cityItem;
        onMapClickListener.onClick(selectCity);
        postInvalidate();
    }
    return selectCity != null;
}

这样就去别出了选中和未选中的省份,同时通过onMapClickListener接口将选中的数据回调,接下来就是绘制出不同状态的地图

public void onDraw(Canvas canvas, Paint paint, boolean isSelected) {
    if (isSelected) {
        paint.setStrokeWidth(2);
        paint.setColor(Color.BLUE);
        paint.setStyle(Paint.Style.FILL);
        paint.setShadowLayer(8, 0, 0, 0xFFFFFFFF);
        canvas.drawPath(mPath, paint);
        paint.clearShadowLayer();
        paint.setColor(Color.BLUE);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(2);
        canvas.drawPath(mPath, paint);
    } else {
        paint.clearShadowLayer();
        paint.setStrokeWidth(1);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(drawColor);
        canvas.drawPath(mPath, paint);
        paint.setStyle(Paint.Style.STROKE);
        int strokeColor = 0xFFD0E8F4;
        paint.setColor(strokeColor);
        canvas.drawPath(mPath, paint);
    }
}

这样就基本实现一个简单地图的绘制与交互
项目源码 github ps:model->pathmap

你可能感兴趣的:(Andorid)