您的位置:首页 > 运维架构

[置顶] OpenLayer3 之 实现拉框放大功能

2017-02-25 23:16 316 查看
几天前,有人给我发邮件询问如何实现划定一个矩形区域实现放大功能,即所谓的“拉框放大”,在 ol3 中,其实已有实现鼠标拖拽放大地图功能,默认需要配合
shift
,按住
shift
,拖拽鼠标的同时,地图会放大,该组件名为
ol.interaction.DragZoom
,该组件的缺点是不实用(哪一个非专业人员会想的按住
shift
拖动)。本文首先介绍该组件的实现,随后基于该组件,在地图上放置拉框按钮,实现一个较为实用的拖拽放大功能。

本文完整代码共享在了GitHub中:https://github.com/QingyaFan/openlayers3-examples

ol.interaction.DragZoom

拉框放大,首先你要拉框,然后根据用户拉出的矩形区域放大到合适地图视口的最大级别。拉框也不必我们实现,ol3 也已经有实现:
ol.interaction.DragBox
,为了基于 dragbox 组件实现拉框,
ol.interaction.DragZoom
继承了
ol.interaction.DragBox
。具体实现如下:

// dragzoom 构造函数
ol.interaction.DragZoom = function(opt_options) {
var options = opt_options ? opt_options : {};
// 触发拉框放大功能的情形
// 此处为按下 shift 键,mac 是 cmd 键
var condition = options.condition ? options.condition :  ol.events.condition.shiftKeyOnly;
// 放大过程的时间
this.duration_ = options.duration !== undefined ? options.duration : 200;
// 是放大还是缩小,默认放大
this.out_ = options.out !== undefined ? options.out : false;
// 调用 dragbox 的构造函数,并将样式赋予 dragbox,如果没有指定,默认 `ol-dragzoom`
ol.interaction.DragBox.call(this, {
condition: condition,
className: options.className || 'ol-dragzoom'
});
};
// 继承 dragzoom
ol.inherits(ol.interaction.DragZoom, ol.interaction.DragBox);


处理完拉框,那么当拉框结束时,需要获取用户框定的区域,并实现地图的缩放,这里利用了 dragbox 的 boxend 事件:

ol.interaction.DragZoom.prototype.onBoxEnd = function() {

// 获取 map 实例
var map = this.getMap();

var view = /** @type {!ol.View} */ (map.getView());
var size = /** @type {!ol.Size} */ (map.getSize());

// 获取用户框定的坐标范围
var extent = this.getGeometry().getExtent();

// 设置为拉框缩小时应进行的处理
if (this.out_) {
var mapExtent = view.calculateExtent(size);
var boxPixelExtent = ol.extent.createOrUpdateFromCoordinates([
map.getPixelFromCoordinate(ol.extent.getBottomLeft(extent)),
map.getPixelFromCoordinate(ol.extent.getTopRight(extent))]);
var factor = view.getResolutionForExtent(boxPixelExtent, size);

ol.extent.scaleFromCenter(mapExtent, 1 / factor);
extent = mapExtent;
}

var resolution = view.constrainResolution(view.getResolutionForExtent(extent, size));

var center = ol.extent.getCenter(extent);
center = view.constrainCenter(center);

// 设置缩放时动画效果
view.animate({
resolution: resolution,
center: center,
duration: this.duration_,
easing: ol.easing.easeOut
});

};


实现拉框放大控件

在地图上放置拉框按钮,样式依赖了 bootstrap:

<div id="map" class="map">
<div class="x-zoom-icons">
<span id="zoom_in" class="glyphicon glyphicon-zoom-in"></span>
</div>
</div>


接下来初始化空间,并绑定触发事件:

var dragzoomActive = false;
// 初始化一个拉框控件
var dragZoom = new ol.interaction.DragZoom({
condition: ol.events.condition.always,
// out: true, // 此处为设置拉框完成时放大还是缩小
});
map.addInteraction(dragZoom);
dragZoom.setActive(false);
// 绑定放大缩小按钮事件
document.querySelector("#zoom_in").addEventListener('click', function() {
if (dragzoomActive) {
dragZoom.setActive(false);
dragzoomActive = false;
document.querySelector("#map").style.cursor = "default";
} else {
dragZoom.setActive(true);
dragzoomActive = true;
document.querySelector("#map").style.cursor = "crosshair";
}
}, false);


这样就可以很好的实现拉框放大,当然,如果你不喜欢默认的框样式,你可以修改,默认使用的
ol-dragzoom
这个类名,你也可以在初始化时指定,这在上面的代码注释中说明了。实现的效果如下:



拉框后:



总结

实现起来还是很容易,不过这个交互组件并不能动态设置
out_
属性,这样我们不得不实例化两个 dragzoom 实例,才能同时实现放大和缩小,有待改进,有时间看看能不能 push 一下。

好的,就这样。

本文完整代码共享在了GitHub中:https://github.com/QingyaFan/openlayers3-examples
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: