使用SVG打造一个可以交互的地图

使用SVG打造一个可以交互的地图

首先还是看看效果

宝岛台湾
交互感觉好像简单,但是这个地图怎么绘制呢?
  • 思路:
    • 利用Xml解析SVG的代码 封装成javaBean 最重要的得到Path
    • 重写OnDraw方法 利用Path绘制台湾地图
    • 重写OnTouchEvent方法,记录手指触摸位置,判断这个位置是否坐落在某个省份上
  • SVG地图
    在drawable中预览

    提示vector下有很多path,一个path对应地图上面一个小块,具体见文章结尾项目

台湾对应的SVG的代码太长,这里就不贴了,这里只做思路解析,文章结尾给出同性交友链接,喜欢就Star,fork

具体步骤
  • 1.创建一个对象用来保存path路径,这里使用了面向对象的思想,让对象自己处理逻辑和绘制
public class PathItem {
    private Path mPath;
    private boolean isSelect;

    public PathItem(Path path) {
        mPath = path;
    }

    /**
     * 是否touch在该path内部
     * @param x
     * @param y
     * @return
     */
    public boolean isTouch(int x, int y) {
       
    }

    public void draw(Canvas canvas, Paint paint) {
      
    }

    public PathItem setSelect(boolean select) {
        isSelect = select;
        return this;
    }
}
  • 2.解析SVG,解析比较耗时,这里开起一个线程解析,下面用到了一个解析path的工具类,在项目中可以找到
 /**
     * 解析path
     */
    private void parserPaths() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 创建DOM工厂对象
                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                try {
                    // DocumentBuilder对象
                    DocumentBuilder db = dbf.newDocumentBuilder();
                    //打开输入流
                    InputStream is = getResources().openRawResource(R.raw.taiwan_maps);
                    // 获取文档对象
                    Document doc = db.parse(is);
                    //获取path元素节点集合
                    NodeList paths = doc.getElementsByTagName("path");
                    PathItem item;
                    for (int i = 0; i < paths.getLength(); i++) {
                        // 取出每一个元素
                        Element personNode = (Element) paths.item(i);
                        //得到android:pathData属性值
                        String nodeValue = personNode.getAttribute("android:pathData");
                        //解析,并创建pathItem
                        item=new PathItem(PathParser.createPathFromPathData(nodeValue));
                        pathItems.add(item);//保存到pathItems集合里
                    }
                    Log.e(TAG, "蜗牛   itemsCount  " + pathItems.size());
                } catch (Exception e) {
                    Log.e(TAG, "蜗牛   解析出错 " );
                }
            }
        }).start();
        postInvalidate();
    }
  • 3.绘制
    • 在pathItem里实现draw()方法
 public void draw(Canvas canvas, Paint paint) {
        if (isSelect) {
            //首先绘制选中的背景阴影
            paint.clearShadowLayer();
            paint.setStyle(Paint.Style.FILL);
            paint.setShadowLayer(8, 0, 0, Color.BLACK);
            canvas.drawPath(mPath,paint);
            //绘制具体显示的
            paint.clearShadowLayer();
            paint.setColor(Color.BLUE);
            paint.setStyle(Paint.Style.FILL);
            canvas.drawPath(mPath,paint);
        } else {
            //绘制具体显示的
            paint.clearShadowLayer();
            paint.setColor(Color.GRAY);
            paint.setStyle(Paint.Style.FILL);
            canvas.drawPath(mPath,paint);
        }
    }
  • 调用item的draw方法
 @Override
    protected void onDraw(Canvas canvas) {
        canvas.save();
        canvas.scale(scale,scale);
        for (PathItem pathItem : pathItems) {
            pathItem.draw(canvas,mPaint);
        }
        canvas.restore();
    }

不出意外走到这里就可以在界面绘制出地图了,接下来处理交互

  • 4.交互
    • 实现PathItem的isTouch方法
 /**
     * 是否touch在该path内部
     * @param x
     * @param y
     * @return
     */
    public boolean isTouch(int x, int y) {
        Region result = new Region();
        //构造一个区域对象。
        RectF r=new RectF();
        //计算path的边界
        mPath.computeBounds(r, true);
        //设置区域路径和剪辑描述的区域
        result.setPath(mPath, new Region((int)r.left,(int)r.top,(int)r.right,(int)r.bottom));
        return result.contains(x, y);
    }
  • 在自定义mapview里面调用isTouch方法
 mDetector=new GestureDetector(new GestureDetector.SimpleOnGestureListener(){
            @Override
            public boolean onDown(MotionEvent e) {
                float x = e.getX()/scale;
                float y = e.getY()/scale;
                for (PathItem pathItem : pathItems) {
                    if (pathItem.isTouch((int) x, (int) y)){
                        pathItem.setSelect(true);
                    }else {
                        pathItem.setSelect(false);
                    }
                }
                invalidate();
                return true;
            }
        });

这里就完成了所有工作了,代码就不具体贴了,链接SVGMapVIew,喜欢就star哦

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容