前言
地图上负责与地图交互的UI元素称为地图控件,辅助我们对地图进行操作或者获取地图上的信息。地图控件是DOM元素且可配置。百度地图API中提供了常用的控件,开发者还可以根据实际业务需求实现自定义控件。如果业务模块与地图交互强相关,建议封装为自定义地图控件。本文将着重介绍如何自定义地图控件,如全屏控件、截图控件、鹰眼控件、卷帘控件。
自定义控件
BMapGL.Control() 资料 示例参考 类参考
此类是所有控件的基类,您可以通过此类来实现自定义控件。所有控件均包含Control类的属性、方法和事件。
通过Map.addControl()方法可将控件添加到地图上。
基础类主要负责解决一是DOM内容,二是DOM位置。
DOM内容:需要通过initialize(map: Map )进行设置,并return dom对象。dom元素的事件,可在此处进行定义。
DOM位置:可以通过defaultAnchor、defaultOffset配置。
全屏控件
FullscreenControl
function FullscreenControl() {
this.isFullscreen = false;
this.defaultAnchor = BMAP_ANCHOR_TOP_RIGHT;
this.defaultOffset = new BMapGL.Size(20, 20);
}
FullscreenControl.prototype = new BMapGL.Control();
FullscreenControl.prototype.initialize = function (map) {
// 创建一个dom元素
var div = document.createElement('div');
// 添加文字或图标,后续需要根据当前状态,切换文字或图标
div.appendChild(document.createTextNode('全屏'));
// 设置样式 略
// 绑定事件
div.onclick = function (e) {
if (!!(
window.document.fullscreenEnabled || doc.webkitFullscreenEnabled)) {
let container = map.getContainer();
if (this.isFullscreen) {
let win = window.document;
if (win.exitFullscreen) {
win.exitFullscreen();
} else if (win.webkitCancelFullScreen) {
win.webkitCancelFullScreen();
}
} else if (container.requestFullscreen) {
container.requestFullscreen();
} else if (container.webkitRequestFullscreen) {
container.webkitRequestFullscreen();
}
this.isFullscreen = !this.isFullscreen;
} else {
throw Error('浏览器不支持全屏');
}
}
// 添加DOM元素到地图中
map.getContainer().appendChild(div);
// 将DOM元素返回
return div;
}
//创建控件元素
var myMapCtrl = new FullscreenControl();
//添加到地图中
map.addControl(myMapCtrl);
截图控件
ScreenshotControl
// 截图需要开启Map的preserveDrawingBuffer
// 引入html2canvas插件
function ScreenshotControl() {
this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT;
this.defaultOffset = new BMapGL.Size(20, 20);
}
ScreenshotControl.prototype = new BMapGL.Control();
ScreenshotControl.prototype.initialize = function (map) {
// 创建一个dom元素
var div = document.createElement('div');
// 添加文字或图标,后续需要根据当前状态,切换文字或图标
div.appendChild(document.createTextNode('截图'));
// 设置样式 略
// 绑定事件
div.onclick = (e) => {
this.download();
}
// 添加DOM元素到地图中
map.getContainer().appendChild(div);
// 将DOM元素返回
return div;
}
ScreenshotControl.prototype.toCanvas = function () {
return new Promise(resolve => {
const targetEle = map.getContainer();
const canvas = document.createElement('canvas');
const width = targetEle.offsetWidth;
const height = targetEle.offsetHeight;
canvas.width = width;
canvas.height = height;
const context = canvas.getContext('2d');
html2canvas(targetEle, {
allowTaint: true,
useCORS: true,
width,
height
}).then(canvas => {
const src = canvas.toDataURL('image/png');
const image = new Image();
image.src = src;
image.onload = () => {
context.drawImage(image, 0, 0);
resolve(canvas);
}
})
})
}
ScreenshotControl.prototype.toDataURL = function (imageType) {
return new Promise(resolve => {
this.toCanvas().then((canvas) => {
resolve(canvas.toDataURL(imageType));
})
});
}
ScreenshotControl.prototype.download = function (options) {
let imageType = 'image/png';
let fileName = `screenshot_${new Date().getTime()}`;
if (options) {
if (options.type) {
imageType = options.type;
}
if (options.filename) {
fileName = options.filename;
} else {
if (imageType === 'image/png') {
fileName += '.png'
} else if (imageType === 'image/jpeg') {
fileName += '.jpg'
} else {
fileName += '.png'
}
}
}
this.toDataURL(imageType).then((url) => {
const downloadEle = document.createElement("a");
downloadEle.download = fileName;
downloadEle.href = url;
document.body.appendChild(downloadEle);
downloadEle.click();
downloadEle.remove();
})
}
//创建控件元素
var myCutMapCtrl = new ScreenshotControl();
//添加到地图中
map.addControl(myCutMapCtrl);
鹰眼控件
OverviewControl
基本实现思路如下:
- 创建一个自定义控件,配置好DOM的样式与位置,可添加隐藏关闭按钮
- 利用DOM创建鹰眼地图(eyeMap),配置鹰眼地图不可拖动、不可缩放等
- 实例化鹰眼控件的时候,传入主Map对象,在主Map上监听onmoveend、onzoom_changed、onzoomend事件,获取地图四至范围
- 将四至范围绘制在eyeMap中,设置eyeMap的四至范围,并缩小几级
卷帘控件
SwipeControl
卷帘功能由两个部分组成,操作面板(分割线和按钮)和图层。
逻辑是按钮按下时拖动分割线,根据分割线当前位置控制图层显示部分。
控制原理:利用CSS3的clip特性,实现div的裁剪效果
基本实现思路如下:
- 在一个地图div容器下创建两个Map
- 传入两个Map和地图div容器ID
- 根据地图容器div容器ID构建水平或垂直分割线
- 分割线注册mousedown事件触发document注册mousemove事件,实时计算分割线位置
- document注册mouseup事件用于注销mousemove事件
- 根据分割线位置设置两个Map的css clip样式,实现卷帘的效果
注意问题
地图API提供的地图控件以及基于地图Control类创建的自定义控件,都是相对地图DOM的布局。如果用户希望脱离地图容器布局控制,对于地图提供控件,需要开发者基于API进行封装实现地图控制功能(不建议)。对于自定义控件,则不继承地图Control类,自己进行布局控制即可。