你可能用到的百度地图效果(附源码)

这段时间需要实现百度地图的一些展示效果,虽然最终效果做出来了,可是这中间也走了很多的弯路,希望有用到的可以直接拿来用,少走一些弯路。百度地图为开发者提供了一系列的接口,点百度接口去百度接口。本文主要用到了以下几个效果:

1、热力图显示

2、自定义图标的聚合显示

3、云麻点显示

热力图显示

百度地图热力图是通过设置热力图半径、颜色、透明度等参数直观展示数据分布情况,而我这段时间所做的,就是通过一段时间内的订单数量,再结合经纬度,在地图上显示热力分布图。百度地图官方的API给的示例很Easy,创建地图实例,初始化参数,生成点的数组,然后创建热力图对象,并将热力图对象添加到地图实例,设置数据源,这样这个热力图的效果就可以展示出来了。(当然申请AK和引入Js就不用说了),这部分源码比较简单,就不展示了,只需要看热力图API相信都是可以明白的。

可是自己做的时候,效果却没这么容易出来。我在做的过程中,开始最大的一处疑问就是,其他代码部分代码都跟官方API示例一样,只是换了个数据源,热力图效果就是出不来。后来在试了无数遍之后,发现如果当前地图放大的级别过大,也就是有些点没有在当前地图可视区域内展示的话,热力图效果是不会出来的!当然了,关于这点没有百度地图官方的解释,也没有得到求证,只是我在开发过程中发现的一个解决方案。如果你也在做这部分,恰好遇到这个问题的话不妨试试。其次为了效果明显,最好是多添加几个点,这样效果会更好一些。以下是效果图:

自定义图标聚合显示

说到这个聚合显示,哎,说多了都是泪啊。本来提出的需求只是需要将数据库中的店铺展示出来,然后点击的时候弹出详细信息的提示框。我一想,这还不简单?通过Handler从后台获取到数据,然后以Json的格式传给前台,然后来个for循环,依次添加到地图不就解决了?第一版我确实是这么干的。拿到数据之后再做foreach……以下是Js脚本。

function LoadMakers(data) {
    var Maker = "[";
    $(data).each(function () {
        var sContent = "<div  style=‘text-align: left;‘><h4 style=‘margin:0 0 5px 0;padding:0.2em 0‘>" + this.pointerTitle + "</h4>";
        if (this.pointImg) {
            sContent = "<div  style=‘text-align: left;‘><h4 style=‘margin:0 0 5px 0;padding:0.2em 0; width:300px‘>" + this.pointerTitle + "</h4>";
            sContent += "<img style=‘float:left;margin:4px;width:104px;height:69px‘ id=‘imgDemo‘ src=‘" + this.pointImg + "‘  title=‘" + this.pointerTitle + "‘/>";
        }
        if (this.address) {
            if (this.pointImg) {
                sContent += "<p style=‘margin:0;line-height:1.5;font-size:13px;width:200px;margin-left:110px‘>" + this.address + "</p>";
            } else {
                sContent += "<p style=‘margin:0;line-height:1.5;font-size:13px;width:200px;‘>" + this.address + "</p>";

            }
        }
        if (this.pointerContent) {
            if (this.pointImg) {
                sContent += "<p style=‘margin:0;line-height:1.5;font-size:13px;width:200px;margin-left:110px‘>" + this.pointerContent + "</p>";
            } else {
                sContent += "<p style=‘margin:0;line-height:1.5;font-size:13px;width:200px;‘>" + this.pointerContent + "</p>";

            }
        }
        sContent += "</div>";
        Maker += "{supId:"+this.spId+",Longitude:" + this.markersLongitude + ",Dimension:" + this.markersDimension + ",Window: { LoadEvent:‘click‘,Content:\"" + sContent + "\"},enableMassClear:true},";
    });
    Maker += "]";
    return eval(Maker);
}

我在本地添加了将近100个点的数据,测试没问题之后就提交到Svn了,然后跟项目经理说这个东东做完了。然后项目经理将数据切成正式数据,叫我给他演示一下。这一演示不要紧啊,脸全没了。正式数据库中有5000多条数据,而我取数据时后台做了过滤,只提取有经纬度的点,即使这样也有1500多条记录。没错,1500多条,这意味着浏览器客户端这边要循环1500多次来做这个操作!然后奇迹就发生了,页面就假死了!无论怎么刷新都没有效果了,即使等了很长时间地图加载出来了,只要稍微一放大或者移动地图页面就会直接挂掉。然后项目经理就一顿巴拉巴拉巴拉,这就是你给我的结果么?

谁让我确实这个东东没做好呢?也没脸跟别人争辩,拿回来重新研究吧。于是在网上搜了一下,发现很多人也都遇到了这个问题,就是当点大于一定的数量之后,浏览器都会出现假死的情况。然后上百度论坛浏览了一下,确实有提到这个问题,当点的数量在150个以内时,这么做是没有问题的,但当点数量大于300个时,这么做就行不通了。百度给出了两种解决方案:

No1:Marker聚合:http://tieba.baidu.com/f?kz=1031097376

No2:数据抽希:比如有10个marker,选择其中6个做为显示点。

这里对比了一下需求,Marker聚合是将所有的点聚合起来,显示一个总数,然后点击的时候再分开;而数据抽希字面的意思是从中选取一部分来展示。而我所接到的任务是展示所有点,显然数据抽希这里是用不上了,那就来聚合吧。这是第二版。

首先简单介绍一下,百度聚合展示提供了开源的类库,只需要在页面中引用即可。以下是Js脚本代码:

             var map = option.Map||new BMap.Map("MapContent");          // 创建地图实例
                                var point = new BMap.Point(116.418261, 39.921984);
                                map.centerAndZoom(point, 10);             // 初始化地图,设置中心点坐标和地图级别
                                map.enableScrollWheelZoom(); // 允许滚轮缩放
                                map.enableKeyboard = true;
                                map.addControl(new BMap.NavigationControl());
                                map.addControl(new BMap.ScaleControl()); // 启用比例尺。
                                map.addControl(new BMap.MapTypeControl()); // 是否启用卫星地图等等。
                                var MAX = resultData.count;
                                var markers = [];
                                var pt = null, mypt = null;
                                var i = 0;
                                var infoWindow;
                                var myIcon = new BMap.Icon("/Admin/Images/red.png", new BMap.Size(28, 37), {
                                });
                                for (; i < MAX; i++) {
                                    pt = new BMap.Point(resultData.data[i].Longitude, resultData.data[i].Dimension);
                                    mypt = new BMap.Marker(pt);
                                    mypt.setIcon(myIcon);
                                    mypt.addEventListener("click", function (no) {
                                        return function () {
                                            infoWindow = LoadMakerInfo(resultData.data[no]);
                                            this.openInfoWindow(infoWindow);
                                            //createInfoWin(resultData.data[no]).redraw();
                                        };
                                    } (i));
                                    markers.push(mypt);
                                }
                                ////最简单的用法,生成一个marker数组,然后调用markerClusterer类即可。
                                var markerClusterer = new BMapLib.MarkerClusterer(map, { markers: markers.reverse(), isAverangeCenter: true,girdSize:100,maxZoom:15 });
                            }

这段代码大部分都很简单,只有一个地方做个简单的说明,网上很多人也问到了这里。就是说循环添加点,然后给每一个点都绑定了Click事件,然后实际点击的时候却弹出的内容都是一样的。这是由于Js的作用域以及闭包引起的,详情请看我的另一篇博客:那些必须要知道的Javascript,这里不再赘述。其中代码里setIcon是为了把百度默认的图标换成我们自己预先设定的图标,下图是运行之后的效果:

与第一版相比,性能确实有了很大的改进,至少在本地加载个1500多条数据已经没问题了。可是通过聚合之后又引入了新的问题,就像上图中的绿色圆圈,有两个4,一个6,正常这些数据点击之后都会散开的,当一直点击的时候应该可以看到没有聚合的点。可是这里出现的问题是有些可以点开,有些居然点不开。开始我以为是数据的问题,以为相隔比较近的点是无法展开的,后来就对数据做了处理,如果有相同的数据则通过加减随机数,确保拿出来的数据没有相同的,可是这个问题还是没有解决。希望有了解的朋友可以告知一二。通过这样聚合,展示数据确实比第一版快很多,可是当在公网上的时候,页面缩放或者移动的时候还是会卡。所以还得重新找解决方案。

这里值得一提的就是百度地图我们可以看到那种鼠标在左边搜索列表滑动,右边地图中搜到的结果跟着变化的那种效果,这里我们也是可以做的。监测左边列表的MoueEnter事件,然后根据当前Enter的点的经纬度创建一个点,然后Foreach右边搜索结果中的点,如果通过point的equals方法,判断是否是同一个点,如果是则改变当前的Icon即可。Js脚本:

function ReDrawMap(data) {
            if (data.markersLongitude && data.markersDimension) {
var tmpInfo = LoadMakerInfo(data);
                var point = new BMap.Point(data.markersLongitude, data.markersDimension); // 创建点坐标
                var mkrs = option.Map.getOverlays();
                var position;
                for (var i = 0; i < mkrs.length; i++) {
                    position = mkrs[i].point;
                    if (position&&position.equals(point)) {
                        mkrs[i].openInfoWindow(tmpInfo);
                    }
                }
            }
        }

云麻点效果展示

最初没有用这个云麻点展示效果是因为一些敏感数据,可是后来发现没有其他合适的解决方案的时候,就采用了这个方案。云麻点效果也就是LBS云存储,用户将数据存放在百度的云服务器,然后直接从百度云获取数据。这个流程是:先在LBS开放平台创建数据表,然后添加需要的字段,然后就可以在后台批量上传数据。数据上传至百度服务器后,会生产相应的云麻点图层,这些图层在加载的时候直接被展示出来,这样可以很大程度上提高性能。现在假设后台数据已经准备完毕了,前台所作的操作:

首先,初始化地图的数据:

 var map = new BMap.Map("MapContent"); //初始化数据
                map.enableScrollWheelZoom();                            // 启用滚轮放大缩小 map.enableContinuousZoom();                             // 启用地图惯性拖拽,默认禁用 map.enableInertialDragging();                           // 启用连续缩放效果,默认禁用。 map.addControl(new BMap.NavigationControl());           // 添加平移缩放控件
                map.addControl(new BMap.ScaleControl());                // 添加比例尺控件
                map.addControl(new BMap.OverviewMapControl());          // 添加缩略地图控件
                map.addControl(new BMap.MapTypeControl());              // 添加地图类型控件
                map.centerAndZoom(new BMap.Point(116.418261, 39.921984), 5); // 初始化地图,设置中心点坐标和地图级别
                map.addControl(new BMap.NavigationControl()); // 启用鱼骨头。
                map.setCurrentCity("北京");                            //由于有3D图,需要设置

然后,设置筛选的条件:

                //检索模块相关代码
                var keyword = "",   //检索关键词
                        page = 0,    //当前页码
                        points = [],   //存储检索出来的结果的坐标数组
                        customLayer = null; //麻点图层
                customLayer = new BMap.CustomLayer({
                    geotableId: 00000,//后台生成表的Id
                    q: ‘‘, //检索关键字
                    tags: ‘‘, //空格分隔的多字符串
                    filter: ‘‘ //过滤条件,参考http://developer.baidu.com/map/lbs-geosearch.htm#.search.nearby
                }); //新建麻点图图层对象
                map.addTileLayer(customLayer); //将麻点图添加到地图当中
                customLayer.addEventListener(‘hotspotclick‘, hotspotclickCallback); //给麻点图添加点击麻点回调函数

                /**
                * 麻点图点击麻点的回调函数
                * @param 麻点图点击事件返回的单条数据
                */
                function hotspotclickCallback(e) {
                if (e.content.phone == "NULL") {
                    e.content.phone = "暂无";
                }
                    var customPoi = e.customPoi,
            str = [];
                    str.push("address = " + customPoi.address);
                    str.push("phoneNumber = " + customPoi.phoneNumber);
                    var content =‘<img src="‘ + e.content.shopPhoto + ‘"style="width:111px;height:83px;float:left;margin-right:5px;"/>‘+ ‘<p style="width:280px;margin:0;line-height:20px;">地址:‘ + customPoi.address + ‘</p>‘;
                    content += ‘<p style="width:280px;margin:0;line-height:20px;">电话:‘ + e.content.phone + ‘</p>‘;
                    //创建检索信息窗口对象
                    var searchInfoWindow = new BMapLib.SearchInfoWindow(map, content, {
                        title: e.content.nickName,  //标题
                        width: 290,              //宽度
                        height: 40,              //高度
                        enableAutoPan: true,    //自动平移
                        enableSendToPhone: true, //是否显示发送到手机按钮
                        searchTypes: [
                BMAPLIB_TAB_SEARCH,   //周边检索
                BMAPLIB_TAB_TO_HERE,  //到这里去
                BMAPLIB_TAB_FROM_HERE //从这里出发
            ]
                    });
                    var point = new BMap.Point(customPoi.point.lng, customPoi.point.lat);
                    searchInfoWindow.open(point); //打开信息窗口
                }

之后就是最关键的一步,请求数据:

                var url = "http://api.map.baidu.com/geosearch/v2/local?callback=?";
                $.getJSON(url, {
                    ‘q‘: ‘‘, //检索关键字
                    ‘page_index‘: page,  //页码
                    // ‘filter‘: filter.join(‘|‘),  //过滤条件
                    ‘region‘: ‘131‘,  //北京的城市id
                    ‘scope‘: ‘2‘,  //显示详细信息
                    ‘geotable_id‘: 00000,
                    ‘page_size‘: 12,
                    ‘ak‘: ‘XXXXXXXX‘  //用户ak
                }, function (e) {
                    renderMap(e, page + 1);
                });

完了之后再调整一下样式,结果如图:

通过LBS云存储,可以很好的解决海量数据加载缓慢的问题,但是这样做的缺点就是一方面数据必须上传到百度的云服务器,另一方面数据维护还是比较麻烦的,必须得通过接口来操作。以上是最近做百度接口总结的一些问题,希望对您能有所帮助,如果您遇到了跟我类似的问题还没有解决,欢迎随时跟我交流。如果您觉得文章对您有一点点作用,一定要顶哦,原创不容易啊!

时间: 2024-10-18 09:58:35

你可能用到的百度地图效果(附源码)的相关文章

细读百度地图点聚合源码(下)---Renderer类解析

上一篇文章分析了ClusterMananger的整体结构和核心算法 细读百度地图点聚合源码(上),此文是接着上一篇来的. 在本文中,我们将学习如何在UI线程中做大量的操作,并且不会造成界面卡顿. 上次我们讲到ClusterManager类中的cluster()方法,调用ClusterTask后台线程处理核心算法,既然有doInBackground()后台任务函数,就会有onPostExecute()函数来处理后台线程返回的结果,这一篇我们就分析怎么处理返回的结果. 那么我们就从返回的结果开始吧!

细读百度地图点聚合源码(上)

之前在项目中需要用到百度地图的点聚合,看了百度提供的demo之后,稍微读了一些源码就能达到需求了,所以并未深入解读源码. 最近有空就把百度实现点聚合的源码从里到外仔细研究了一遍受益良多,在此分享一下. 为了方便研究我把百度demo中点聚合相关的类抽出来,新建了个工程,有需要可以下载来研究.ClusterDemo 整个源码分析过程我分为三个部分: 1.整体结构分析 2.核心算法分析 3.实现点聚合 本篇为上篇,主要分析1,2部分.之后还会有个下篇,着重分析具体如何实现marker点聚合以及一些动画

leaflet-webpack 入门开发系列五地图卷帘(附源码下载)

前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 webpack 配置介绍文档详细的 webpack 文档配置介绍,适合新手查看,我也是边看边学 vscode 安装包下载,我这边用 vscode工具编译开发前端项目,个人觉的这款工具还不错 leaflet api文档介绍,详细介绍 leaflet 每个类的函数以及属性等等 leaflet 在线例子 l

cesium1.63.1api版本贴地贴模型量算工具效果(附源码下载)

前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材.不少订阅者向我反馈之前的那篇(https://xiaozhuanlan.com/topic/8210364597 ) 量算工具的cesiumAPI版本太低,不能适用新版本.所以,推出新版本的量算工具效果,对应版本是cesium1.63.1API的. 内容概览 1.cesium1.63.1API版本贴地量

openlayers6实现webgl点图层渲染效果(附源码下载)

前言:openlayers6推出来的有一段时间,推出来的新特性见:https://github.com/openlayers/openlayers/releases/该版本的主要功能是能够组合具有不同渲染器类型的图层.以前,地图只使用一种渲染策略,并且地图中的所有图层都必须实施该策略.现在,可以使用包含使用不同渲染技术的图层的地图.例如,这使得可以在同一地图中将Canvas(2D)图层与基于WebGL的图层组合在一起.也可以使用自定义渲染器创建图层.因此,您可以拥有一个使用另一个库(例如d3)的

cesium1.65api版本贴地贴模型标绘工具效果(附源码下载)

前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 内容概览 1.cesium1.65api版本贴地贴模型标绘工具效果2.源代码demo下载 效果图如下: 实现思路: 鼠标左键Cesium.ScreenSpaceEventType.LEFT_CLICK 鼠标移动Cesium.ScreenSpaceEventType.MOUSE_MOVE 鼠标右键Ces

js实现轮播图效果(附源码)--原生js的应用

1.js实现轮播图效果 <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="Author" content="奇客艺术"> <meta name="keyword" content="关键字"> <meta name=

10款web前端值得学习的 HTML5 效果附源码

1.jQuery右侧Tab选项卡的焦点图插件 这是一款基于jQuery的焦点图插件,和之前介绍的jQuery焦点图插件类似,它以淡入淡出的动画方式来切换图片,该焦点图插件的特点是右侧有一排Tab选项卡,点击相应选项卡后即可切换对应的图片,应该说这款jQuery焦点图插件还是非常实用的. 在线演示 源码下载 2.超炫 HTML5 粒子效果进度条 我喜欢粒子效果作品,特别是那些能够应用于实际的,例如这个由 Jack Rugile 基于 HTML5 Cavnas 编写的进度条效果.看着这么炫的 Loa

超炫酷的jQuery/HTML5应用效果及源码

jQuery非常强大,我们之前也用jQuery分享过很多实用的插件.HTML5可以让网页变得更加绚丽多彩,将HTML5和jQuery结合使用那将发挥更棒的效果. 今天向大家收集了一些关于HTML5和jQuery的应用及其源码,一起来看看. HTML5动感的火焰燃烧动画特效 这又是一款基于HTML5的超炫动画特效,是一款动感的火焰燃烧动画效果.这款HTML5动画火焰燃烧非常逼真. 核心jQuery代码: $( document ).ready(function() { // Set canvas

wpf 模拟3D效果(和手机浏览图片效果相似)(附源码)

原文 wpf 模拟3D效果(和手机浏览图片效果相似)(附源码) pf的3D是一个很有意思的东西,类似于ps的效果,类似于电影动画的效果,因为动画的效果,(对于3D基础的摄像机,光源,之类不介绍,对于依赖属性也不介绍.),个人认为,依赖属性这个东西,有百分之五十是为了3D而存在.(自己写的类似于demo的东西)先上图,无图无真相这是demo的整个效果图,可以用鼠标移动,触摸屏也可以手指滑动,图片会移动,然后移动结束,会有一个回弹的判断. <Window x:Class="_3Dshow.Wi