百度地图API标注+时间轴组件

工作时被要求到的,结合百度地图api做一个动态展示标注变化的组件,要求地图展示某一天的标注,时间轴要求可以动态播放每一天的标注变化...然后我就开始coding...

准备工作:

  1. 申请百度api密钥(具体方法我也不多写了,大家应该都会)
  2. 了解一下百度地图API的开发指南和类参考文档(如果嫌麻烦的话 可以直接看Demo示例)

一、首先,先加载地图,你可以用实际的经纬度定位、浏览器定位、根据ip定位、根据城市名定位,这个你可以自己选择

// 创建Map实例,设置地图允许的最小/大级别
var map = this.map;
map.centerAndZoom(new BMap.Point(121.365593, 37.528502), 15); // 初始化地图,用城市名设置地图中心点
//map.enableScrollWheelZoom(true); //启用滚轮放大缩小

centerAndZoom(center:Point, zoom:Number)

参数解释:

  1. Point(lng:Number, lat:Number)  以指定的经度和纬度创建一个地理点坐标。
  2. zoom:number         地图缩放级别

二、标注的使用(覆盖物)

结合百度地图api示例Demo 设置点的新图标和添加多个点示例 结合一下,就可以改写成添加多个地图标注

//编写自定义函数,创建标注
        addMarker: function(point, label, status) {
            //        var marker = new BMap.Marker(point);
            var myIcon = new BMap.Icon("images/rubbish_" + status + ".png", new BMap.Size(32, 32), {
                anchor: new BMap.Size(16, 32), //中心点设置
                infoWindowAnchor: new BMap.Size(16, 4) //消息框位置5
            });
            var marker = new BMap.Marker(point, {
                icon: myIcon
            });
            TimerLine.map.addOverlay(marker);
            //跳动的动画
            //                marker.setAnimation(BMAP_ANIMATION_BOUNCE);
            marker.setAnimation(BMAP_ANIMATION_DROP);
            var p = marker.getPosition();
            var content = "<table>";
            content = content + "<tr><td> 编号:" + label.content + "</td></tr>";
            content = content + "<tr><td> 坐标:" + p.lng + "," + p.lat + "</td></tr>";
            content = content + "<tr><td> 状态:" + status + "</td></tr>";
            content += "</table>";
            var infowindow = new BMap.InfoWindow(content);
            //添加绑定事件
            addEvent(marker, 'click', getAttr);
            function getAttr() {
                this.openInfoWindow(infowindow);
            }
    }

百度地图标注添加看懂了,接下来就是动态添加标注,并且随和日期的变化而变化,比如展示垃圾箱的动态变化,8.3号清理了颜色为绿色,8.6号没清理为红色..

思想:

  1. 动态:就要使用ajax异步获取数据
  2. 变化:就要使用定时器(setInterval或者 setTimeout)
    setInterval 循环调用
    setTimeout 延迟调用 1次     具体区别可以自行百度
  3. 动手写插件
function addEvent(dom, type, fn) {
    //对于支持DOM2级事件处理程序addeventListener方法的浏览器
    if (dom.addEventListener) {
        dom.addEventListener(type, fn, false);
    } else if (dom.attachEvent) {
        //对于不支持addEventListener方法但支持attchEvent方法的浏览器    
        dom.attachEvent('on' + type, fn);
    } else {
        //对于不支持以上两种,但支持on+'事件名'的浏览器
        dom['on' + type] = fn;
    }
}
var TimerLine = {
    data: {
        containerDiv: 'timerline', //容器盒子id
        datesDiv:'dates',//日期盒子id
        btnsDiv:'timerlineBtns',
        btns: {
            play: "timerbtn-play",
            stop: "timerbtn-stop",
            pre:"timerbtn-pre",
            next:"timerbtn-next"
        },
        processDiv:'processbar',    //进度条div
    },
    protect:{
        lock_play:false,
        lock_stop:false,
        index_label:1,
        index_process:0
    },
    rubbish_datas: [], //用来存储ajax获取到的数据
    index: 0, //变化的index
    Interval_label: null,
    Interval_process:null,
    map: new BMap.Map("allmap", {
        minZoom: 14,
        maxZoom: 20
    }),
    Utils: {
        //编写自定义函数,创建标注
        addMarker: function(point, label, status) {
            //        var marker = new BMap.Marker(point);
            var myIcon = new BMap.Icon("images/rubbish_" + status + ".png", new BMap.Size(32, 32), {
                anchor: new BMap.Size(16, 32), //中心点设置
                infoWindowAnchor: new BMap.Size(16, 4) //消息框位置5
            });
            var marker = new BMap.Marker(point, {
                icon: myIcon
            });
            TimerLine.map.addOverlay(marker);
            //跳动的动画
            //                marker.setAnimation(BMAP_ANIMATION_BOUNCE);
            marker.setAnimation(BMAP_ANIMATION_DROP);
            var p = marker.getPosition();
            var content = "<table>";
            content = content + "<tr><td> 编号:" + label.content + "</td></tr>";
            content = content + "<tr><td> 坐标:" + p.lng + "," + p.lat + "</td></tr>";
            content = content + "<tr><td> 状态:" + status + "</td></tr>";
            content += "</table>";
            var infowindow = new BMap.InfoWindow(content);
            //添加绑定事件
            addEvent(marker, 'click', getAttr);
            function getAttr() {
                this.openInfoWindow(infowindow);
            }
        },
        /**
         * 地图标注方法
         * 参数:        datas:标注物数组{date:"",info:{}}
         *             index:序数(日期)
         * */
        mapSetLabel: function(datas, n,isInterval) {
            TimerLine.map.clearOverlays();
            var index;
            console.log(TimerLine.protect.index_label);
            if(isInterval){
                TimerLine.protect.index_label++;
                if (TimerLine.protect.index_label >= TimerLine.rubbish_datas.length - 1) {
                    TimerLine.protect.index_label = TimerLine.rubbish_datas.length - 1;
                    clearInterval(TimerLine.Interval_label);
                    TimerLine.protect.lock_play=false;
                }
            }
            
            if (n == null) {
                if(TimerLine.protect.index_label==0){
                    TimerLine.protect.index_label=1
                }
                index = TimerLine.protect.index_label;
            } else {
                index = parseInt(n);
                TimerLine.protect.index_label = index;
            }
            
            var info = datas[index].info;
            var info_count=0;
            var addMarker_Interval=setInterval(function(){
                var p = info[info_count].point.split(',');
                var p_x = parseFloat(p[0].toString()); //纬度
                var p_y = parseFloat(p[1].toString()); //经度
                //创建label标签
                var label = new BMap.Label(info[info_count].title, {
                    offset: new BMap.Size(20, -10)
                });
                //创建标注点
                var point = new BMap.Point(p_x, p_y);
                //状态(垃圾箱状态)
                var status = info[info_count].status;            
                //添加标注的方法
                TimerLine.Utils.addMarker(point, label, status);
                info_count++;
                if(info_count>=info.length){
                    clearInterval(addMarker_Interval);
                }
            },0);

        },
        //添加日期点击事件绑定 dates li click
        bindEvent: function() {
            var datesDiv = document.getElementById("dates");
            addEvent(datesDiv,'click',function(e){
                var event = e || window.e;
                var target = event.target || event.srcElement;
                for(var i=0;i<TimerLine.rubbish_datas.length;i++){
                    if(target.innerText==TimerLine.rubbish_datas[i].date){
//        
                        TimerLine.protect.index_process=i;
                        TimerLine.protect.index_label=i;
                        //播放解锁
                        if(TimerLine.protect.lock_play)    TimerLine.protect.lock_play=false;
                        TimerLine.Utils.mapSetLabel(TimerLine.rubbish_datas, i,false);
                        TimerLine.Utils.Setprocess(i,false);
                        return ;
                    }
                }
            })
        },
        //进度条滚动
        Setprocess:function(index,isInterval){
            if(isInterval){
                TimerLine.protect.index_process++;
                console.log(TimerLine.protect.index_process);
                console.log(TimerLine.rubbish_datas.length);
                if(TimerLine.protect.index_process >= TimerLine.rubbish_datas.length-1){
                    TimerLine.protect.index_process = TimerLine.rubbish_datas.length-1;
                    clearInterval(TimerLine.Interval_process);
                    TimerLine.protect.lock_play=false;
                }
            }
            var datesDiv = document.getElementById("dates");
            var processDiv = document.getElementById(TimerLine.data.processDiv);
            if(index==null){
                processDiv.style.width =parseInt(processDiv.style.width)+datesDiv.getElementsByTagName('li')[0].offsetWidth+'px';
            }else{
                processDiv.style.width =datesDiv.getElementsByTagName('li')[0].offsetWidth*parseInt(index+1)+'px';
            }
            
        }
        
    },
    //TimerLine初始化
    init: function() {
        this.createMap();
        this.ajaxCreate();
        //事件绑定
        this.bindEvent();
    },
    createMap: function() {
        // 创建Map实例,设置地图允许的最小/大级别
        var map = this.map;
        map.centerAndZoom(new BMap.Point(121.365593, 37.528502), 15); // 初始化地图,用城市名设置地图中心点
        //map.enableScrollWheelZoom(true); //启用滚轮放大缩小
    },
    ajaxCreate: function() {
        var That = this;
        var containerDiv = That.data.containerDiv;
        $.ajax({
            type: "get",
            url: "js/json.json",
            dataType: 'json',
            success: function(data) {
                containerDiv = document.getElementById(containerDiv); //容器id
                That.rubbish_datas = data.result.datas; //
                //console.log(That.rubbish_datas);
                That.create(containerDiv, That.rubbish_datas);
                //日期时间绑定
                That.Utils.bindEvent();
            }
        });
    },
    create: function(containerDiv, datas) {
        var That = this;
        var datasDiv ='<div class="processcontainer"><div id="processbar" style="width:120px;"></div></div>';
//        var datasDiv = '<ul id="dates" class="timerlineul dates clearfix">';
        datasDiv += '<ul id="dates" class="timerlineul dates clearfix">';
        for (var i = 0; i < datas.length; i++) {
            datasDiv += '<li>' + datas[i].date + '</li>';
        }
        datasDiv += '</ul>';    
        document.getElementById(That.data.btnsDiv).innerHTML='<div class="timerline-btns clearfix"><div id="timerbtn-pre" class="iconfont icon-shangyishou"></div><div id="timerbtn-play" class="iconfont icon-zanting"></div><div id="timerbtn-next" class="iconfont icon-xiayishou"></div></div>'
        //创建第一天的标注
        this.Utils.mapSetLabel(datas, 0,false);
        
//        console.log(TimerLine.index);
        That.datas = datas;
        containerDiv.innerHTML = datasDiv;
    },
    //播放 暂停 委托事件----时间绑定
    bindEvent: function() {
        if (this.data.btns == null)
            return;
        var That = this;
        addEvent(document.getElementById(That.data.btnsDiv), 'click', function(e) {
            var event = e || window.e;
            var target = event.target || event.srcElement;
            //播放事件
            if (target.id == That.data.btns.play) {
                if(!TimerLine.protect.lock_play){
                    if(TimerLine.protect.index_label >= TimerLine.rubbish_datas.length-1){
                        TimerLine.protect.index_label=0;
                        var processDiv = document.getElementById(TimerLine.data.processDiv);
                        var datesDiv = document.getElementById("dates");
                        processDiv.style.width = datesDiv.getElementsByTagName('li')[0].offsetWidth+'px';
                    }
                    if(TimerLine.protect.index_process >= TimerLine.rubbish_datas.length-1){
                        TimerLine.protect.index_process=0;
                    }
//                
                    TimerLine.Interval_label = setInterval("TimerLine.Utils.mapSetLabel(TimerLine.rubbish_datas,null,true)", 1000);
                    TimerLine.Interval_process = setInterval("TimerLine.Utils.Setprocess(null,true)",1000);    
                    $("#timerbtn-play").attr("class","iconfont icon-zanting1");
                    //播放枷锁
                    TimerLine.protect.lock_play=true;
                    //暂停解锁
                    TimerLine.protect.lock_stop=false;
                }else if(TimerLine.protect.lock_play){
                    $("#timerbtn-play").attr("class","iconfont icon-zanting");
                    TimerLine.Interval_label&&clearInterval(TimerLine.Interval_label);
                    TimerLine.Interval_process&&clearInterval(TimerLine.Interval_process);
                    //播放解锁
                    TimerLine.protect.lock_play=false;
                    //暂停加锁
                    TimerLine.protect.lock_stop=true;
                }
            }
            
            if(target.id == That.data.btns.pre){
                if(TimerLine.protect.index_label==0) return;
                TimerLine.Utils.mapSetLabel(TimerLine.rubbish_datas, TimerLine.protect.index_label-1,false);
                TimerLine.Utils.Setprocess(TimerLine.protect.index_process-1,false);
                TimerLine.protect.index_process=TimerLine.protect.index_process-1;
            }
            if(target.id == That.data.btns.next){
                if(TimerLine.protect.index_label==TimerLine.rubbish_datas.length-1) return;
                TimerLine.Utils.mapSetLabel(TimerLine.rubbish_datas, TimerLine.protect.index_label+1,false);
                TimerLine.Utils.Setprocess(TimerLine.protect.index_process+1,false);
                TimerLine.protect.index_process=TimerLine.protect.index_process+1;
            }
        });
    }
}

TimerLine.init();

以上是我自己手写的组件代码,对设计模式了解还是一般.本来是想用原型模式写,不过在setInterval时候,方法没法调用原型方法,让后我就改成了单例模式

TimeLine组件介绍

  1. data:数据容器绑定

  2. protect 保护属性 (对播放、暂停、时间轴index、标注index)

  3. rubbish_datas 存储ajax读取的数据

  4. Interval_label 百度地图标注定时器

  5. Interval_process 时间轴定时器

  6. Utils 工具类

  7. init() TimeLine初始化

  8. createMap() 创建百度地图

  9. ajaxCreate() 获取数据,创建容器(create()),时间绑定(bindEvent())

遇到的问题:

  1. 两个定时器运行时,公共index 容易读取错误,一个定时器修改了index 另一个定时器还没修改,这样造成了创建标注与当前时间不符合,

注:要将修改公共变量尽量写在一个方法中。公共变量最好不要在多个方法中公用,容易在增减的时候出现不必要的BUG

  1. 定时器运行到最后一天的时候要将定时器清除。

程序如图:
百度地图API标注+时间轴组合的组件效果图

附上预览地址
更多内容可以订阅本人微信公众号,一起开启前端小白进阶的世界!

前端Demon

不给 Demo 地址 是不是对不起你们。哈哈😁
可以关注微信公众号 回复百度地图时间轴组件 ,即可收到 Demo 的地址。

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

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,089评论 4 62
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,649评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,043评论 25 707
  • 1 这一周,爸爸妈妈都很辛苦。先是妈妈去了北京,主要办两件事,其中一个是和我婆婆一起办美国签证的面签,在京的几天也...
    润青jingjing阅读 269评论 0 0
  • 2016年6月20号,我最后一天在自己的岗位上工作。没有和你说感谢,没有和你说再见,我离开了。不必沮丧,无需失落,...
    不回头的姑凉阅读 272评论 0 0