首页 > 请教一个问题, 百度地图的javascript api 能否用触摸方式动态画一个圆或者矩形?

请教一个问题, 百度地图的javascript api 能否用触摸方式动态画一个圆或者矩形?

如题,请教下解决思路。


我自己实现了一下,可以自己在百度地图上随便画图形,基本原理就是,监听touch事件,touchMove,保存当前的经纬度,转化为pixel坐标,重复绘制线段,当touchEnd时,绘制矩形图形。最后会连接首位2点,并判断矩形是否有效,同时如果在画得过程中已经有闭合图形,则终止画图。

演示地址,需要使用手机浏览测试:

JS 实现代码:

var app = app || {};

app.BM = {
    map: false,
    init: function() {
        // 百度地图API功能
        this.map = new BMap.Map("allmap");    // 创建Map实例
        this.map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);  // 初始化地图,设置中心点坐标和地图级别
        this.map.addControl(new BMap.MapTypeControl());   //添加地图类型控件
        this.map.setCurrentCity("北京");          // 设置地图显示的城市 此项是必须设置的

        this.map.enableScrollWheelZoom();     //开启鼠标滚轮缩放
        this.map.enableDragging();
    }
};

// 电子围栏
// @todo 数据交互部分
app.Fence = {
    cache_points: [], // 缓存折线数据,取消操作时,重新画图。

    polyline:false, // 百度折线覆盖物
    points: [], // 折线数据 [H,H,H,...] H{lat:"",lng:""}
    coordinate: [], // 像素数据 [P,P,...] P{x:"",y:""}
    cur_point: false, 
    cur_pixel: false,
    isOver: false, // 围栏是否已经完成
    cross_at: false, // 相交的点索引  
    state: 0, // 界面状态 0 待设定状态, 1 开始设定, 2 设定完成

    polygon: false, // 完成后的栏栅覆盖物

    polylineOption: {strokeColor:"blue", strokeWeight:4, strokeOpacity:0.5},

    init: function() {
        app.BM.init();      
        this.initClickEvent();
    },

    initClickEvent: function() {
        // 设定或取消
        document.getElementById('action').addEventListener('click', this.clickSettingHandler, false);       
        // 确定或重新设定事件监听
        document.getElementById('setok').addEventListener('click', this.setOKHandler, false);
        document.getElementById('reset').addEventListener('click', this.resetHandler, false);
    },

    clickSettingHandler: function(){        
        if (app.Fence.state == 0)
        {
            app.Fence.initTouchEvent();

            if (app.Fence.polygon){
                app.BM.map.removeOverlay(app.Fence.polygon);                
            }

            app.Fence.resetData();
            app.Fence.state = 1;                                        

            app.Fence.setElementHidden('fence_show');           
            app.Fence.setElementDisplay('fence_begin_draw');                    
            document.getElementById('action').innerHTML = "取消"; 

        } else {                                                                    
            app.Fence.removeTouchEvent();           

            if (app.Fence.polyline) {
                app.BM.map.removeOverlay(app.Fence.polyline);
            }

            app.Fence.resetData();          
            app.Fence.state = 0;                    

            if (app.Fence.cache_points) {
                app.Fence.polygon = new BMap.Polygon(app.Fence.cache_points, app.Fence.polylineOption);
                app.BM.map.addOverlay(app.Fence.polygon);
            }                                                       

            app.Fence.setElementDisplay('fence_show');          
            app.Fence.setElementHidden('fence_begin_draw');
            document.getElementById('action').innerHTML = "设定";                 
        } 
    },

    finishDrawing: function(){
        app.Fence.state = 2;
        // 画图完成后立即清除移动
        app.Fence.removeTouchEvent();

        app.Fence.setElementHidden('fence_begin_draw');
        app.Fence.setElementDisplay('fence_end_draw');                  
    },

    drawPolygon: function(){
        app.BM.map.removeOverlay(app.Fence.polyline);       
        app.Fence.polygon = new BMap.Polygon(app.Fence.points, app.Fence.polylineOption);
        app.BM.map.addOverlay(app.Fence.polygon);
    },
    removeClickEvent: function(){           
        document.getElementById('setok').removeEventListener('click', app.Fence.setOKHandler, false);
        document.getElementById('reset').removeEventListener('click', app.Fence.resetHandler, false);
    },
    setOKHandler: function(){
        app.Fence.state = 0;                
        // 最后画一个多边形polygon                  
        app.Fence.drawPolygon();

        app.Fence.setElementDisplay('fence_show');          
        app.Fence.setElementHidden('fence_end_draw');
        document.getElementById('action').innerHTML = "设定";

        document.getElementById('setting_state').innerHTML = "电子栏栅设定成功";                
        // 缓存数据
        app.Fence.cache_points = app.Fence.points;  

        // @todo 同步数据到服务器
    },  
    // 不满意,重新画图
    resetHandler: function(){           
        app.Fence.state = 1;        

        app.BM.map.removeOverlay(app.Fence.polyline);       
        app.Fence.resetData();              
        app.Fence.initTouchEvent();

        app.Fence.setElementHidden('fence_end_draw');
        app.Fence.setElementDisplay('fence_begin_draw');            
    },
    // 触摸事件 @important 开始画图时init 画完图后remove
    initTouchEvent: function(){
        app.BM.map.addEventListener("touchstart", app.Fence.touchStartHandler, false);
        app.BM.map.addEventListener("touchend", app.Fence.touchEndHandler, false);        
        app.BM.map.addEventListener("touchmove", app.Fence.touchMoveHandler, false);
    },
    removeTouchEvent: function(){
        app.BM.map.removeEventListener("touchstart", app.Fence.touchStartHandler, false);
        app.BM.map.removeEventListener("touchend", app.Fence.touchEndHandler, false);        
        app.BM.map.removeEventListener("touchmove", app.Fence.touchMoveHandler, false);
    },
    touchStartHandler: function(){
        app.BM.map.disableDragging(); 
        app.Bm.map.disableScrollWheelZoom(); 
    },
    touchEndHandler: function(){        
        // 正确的画完图形  
        if (app.Fence.isOver){
            app.Fence.finishDrawing();          
        } else {
            if (!app.Fence.finalCheckIsCrossed())
            {            
                var last = app.Fence.points.length - 1;
                app.Fence.polyline = new BMap.Polyline([app.Fence.points[0], app.Fence.points[last]], app.Fence.polylineOption);  //创建多边形
                app.BM.map.addOverlay(app.Fence.polyline);
                app.Fence.finishDrawing();
            }
            else
            {
                alert("电子栏栅设定错误,请重新设定!");
                app.BM.map.removeOverlay(app.Fence.polyline);
                app.Fence.resetData(); 
                app.Fence.state = 1;
                app.Fence.setElementHidden('fence_end_draw');
                app.Fence.setElementDisplay('fence_begin_draw');                
            }   
        }           
        app.BM.map.enableDragging();
        app.BM.map.enableScrollWheelZoom();
    },
    touchMoveHandler: function(e){
        app.Fence.cur_point = e.point;
        app.Fence.cur_pixel = e.pixel;
        app.Fence.points.push(e.point);
        app.Fence.coordinate.push(e.pixel);

        if (app.Fence.checkIsCrossed()) 
        {           
            app.Fence.redrawPolyline();
            app.Fence.isOver = true;  
        }           
        else
        {
            if (!app.Fence.isOver) app.Fence.redraw();  
        }   
    },
    checkIsCrossed: function(){
        var last = app.Fence.coordinate.length - 1;
        for (var i = 1; i < last - 2; i++)
        {
            if (last > 5 && app.Fence.intersect(app.Fence.coordinate[last-1], app.Fence.coordinate[last], app.Fence.coordinate[i-1], app.Fence.coordinate[i]))
            {      
                app.Fence.cross_at = i;
                return true;                
            }                       
        }       
        return false;
    },
    finalCheckIsCrossed: function(){
        var last = app.Fence.coordinate.length - 1;
        for (var i = 2; i < last - 2; i++)
        {
            if (app.Fence.intersect(app.Fence.coordinate[i-1], app.Fence.coordinate[i], app.Fence.coordinate[0], app.Fence.coordinate[last]))
            {                                                            
                return true;                
            }                       
        }  
        return false;
    },
    redrawPolyline: function(){                     
        app.Fence.points.splice(0, app.Fence.cross_at);         
        // 重画图形
        if (app.Fence.polyline) {
            app.BM.map.removeOverlay(app.Fence.polyline);           
        }                   
        if (app.Fence.points)
        {
            app.Fence.polyline = new BMap.Polyline(app.Fence.points, app.Fence.polylineOption);  //创建多边形
            app.BM.map.addOverlay(app.Fence.polyline);   //增加多边形    

            var last = app.Fence.points.length -1 ;
            app.Fence.polyline = new BMap.Polyline([app.Fence.points[0], app.Fence.points[last]], app.Fence.polylineOption);  //创建多边形
            app.BM.map.addOverlay(app.Fence.polyline);              
        }           
    },
    redraw: function(){
        if (app.Fence.polyline) {           
            app.BM.map.removeOverlay(app.Fence.polyline);           
        }                   
        if (app.Fence.points)
        {
            app.Fence.polyline = new BMap.Polyline(app.Fence.points, app.Fence.polylineOption);  //创建多边形
            app.BM.map.addOverlay(app.Fence.polyline);   //增加多边形        
        }  
    },
    /* 叉积 判断2条线段是否相交 */
    mult: function(a, b, c) {
        return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
    },
    /* pa, pb为一条线段两端点 pc, pd为另一条线段的两端点 相交返回true, 不相交返回false*/
    intersect: function(pa, pb, pc, pd) {
        if ( Math.max(pa.x, pb.x)<Math.min(pc.x, pd.x) )
        {
            return false;
        }
        if ( Math.max(pa.y, pb.y)<Math.min(pc.y, pd.y) )
        {
            return false;
        }
        if ( Math.max(pc.x, pd.x)<Math.min(pa.x, pb.x) )
        {
            return false;
        }
        if ( Math.max(pc.y, pd.y)<Math.min(pa.y, pb.y) )
        {
            return false;
        }
        if ( app.Fence.mult(pc, pb, pa)*app.Fence.mult(pb, pd, pa)<0 )
        {
            return false;
        }
        if ( app.Fence.mult(pa, pd, pc)*app.Fence.mult(pd, pb, pc)<0 )
        {
            return false;
        }
        return true;
    },
    resetData: function(){       
        app.Fence.polyline = false;
        app.Fence.points = [];
        app.Fence.coordinate = [];              

        app.Fence.isOver = false;
        app.Fence.cur_point = false;
        app.Fence.cur_pixel = false; 
        app.Fence.polygon = false; 
    },
    setElementDisplay:function(id){
        document.getElementById(id).style.display = "block";
    },
    setElementHidden: function(id){
        document.getElementById(id).style.display = "none";
    }
};

触摸时获取触摸点的经纬度,然后调用api里画圆的方法画圆


http://developer.baidu.com/map/reference/index.phptitle=Class:%E8%A6%8...百度地图API的Circle类画圆

【热门文章】
【热门文章】