interaction
OpenLayers中表达交互功能的基类是interaction
,它是一个虚基类,不负责实例化,交互功能都继承该基类,实现它的子类包括:
- DoubleClickZoom 双击放大交互功能;
- DragAndDrop 以“拖文件到地图中”的交互添加图层;
- DragBox 拉框,用于划定一个矩形范围,常用于放大地图;
- DragPan 拖拽平移地图;
- DragRotate 拖拽方式旋转地图;
- DragRotateAndZoom 拖拽方式进行缩放和旋转地图;
- DragZoom 拖拽方式缩放地图;
- Draw 绘制地理要素功能;
- Extent 单击并拖动地图来绘制矢量框,并可编辑
- KeyboardPan 键盘方式平移地图;
- KeyboardZoom 键盘方式缩放地图;
- Modify 更改要素;
- MouseWheelZoom 鼠标滚轮缩放功能;
- PinchRotate 手指旋转地图,针对触摸屏;
- PinchZoom 手指进行缩放,针对触摸屏;
- Pointer 鼠标的用户自定义事件基类;
- Select 选择要素功能;
- Snap 鼠标捕捉,当鼠标距离某个要素一定距离之内,自动吸附到要素。
- Translate 拖拽移动选中的要素(新增)
用法
// 先实例化
var select = new Select();
var translate = new Translate({
features: select.getFeatures(),
});
// 可以初始化时添加
var map = new Map({
interactions: defaultInteractions().extend([select, translate]),
layers: [raster, vector],
target: 'map',
view: new View({
center: [0, 0],
zoom: 2,
}),
});
// 也可以后续追加
map.addInteraction(select );
map.addInteraction(translate );
默认交互
地图初始化时,如果没有设置交互类型,就会默认绑定一些预设的交互,包括:
- DragRotate 拖拽旋转
- DoubleClickZoom 双击放大
- DragPan 拖拽平移
- PinchRotate 手指旋转
- PinchZoom 手指缩放
- KeyboardPan 键盘平移
- KeyboardZoom 键盘缩放
- MouseWheelZoom 滚轮缩放
- DragZoom 拖拽缩放
事件机制解析
看下ol的事件绑定和触发,入口 Map.js
function Map(options) {
// ...
if (!options.interactions) {
options.interactions = defaultInteractions({ // 没有指定就加载默认交互
onFocusOnly: true,
});
}
// ...
}
Map的父类 PluggableMap.js
// 构造函数
function PluggableMap(options) {
var _this = _super.call(this) || this;
var optionsInternal = createOptionsInternal(options); // 属性初始化
_this.viewport_ = document.createElement('div'); // 地图容器内的主div
// 监听各属性更新事件
_this.addEventListener(getChangeEventType(MapProperty.LAYERGROUP), _this.handleLayerGroupChanged_);
_this.addEventListener(getChangeEventType(MapProperty.VIEW), _this.handleViewChanged_);
_this.addEventListener(getChangeEventType(MapProperty.SIZE), _this.handleSizeChanged_);
_this.addEventListener(getChangeEventType(MapProperty.TARGET), _this.handleTargetChanged_);
// 通过setProperties更新属性,触发上面监听事件
// 这个方法
_this.setProperties(optionsInternal.values);
}
// 地图容器更新触发的方法
PluggableMap.prototype.handleTargetChanged_ = function () {
var targetElement = this.getTargetElement(); // 获取到地图容器
targetElement.appendChild(this.viewport_);
// 实例化一个浏览器事件处理类
this.mapBrowserEventHandler_ = new MapBrowserEventHandler(this, this.moveTolerance_);
for (var key in MapBrowserEventType) {
// 循环所有支持的浏览器事件类型,逐一绑定,触发方法内循环遍历绑定的interaction
this.mapBrowserEventHandler_.addEventListener(MapBrowserEventType[key], this.handleMapBrowserEvent.bind(this));
}
// 绑定右击事件
this.viewport_.addEventListener(EventType.CONTEXTMENU, this.boundHandleBrowserEvent_, false);
// 绑定滚轮事件
this.viewport_.addEventListener(EventType.WHEEL, this.boundHandleBrowserEvent_, PASSIVE_EVENT_LISTENERS ? { passive: false } : false);
// 绑定键盘事件
this.keyHandlerKeys_ = [
listen(keyboardEventTarget, EventType.KEYDOWN, this.handleBrowserEvent, this),
listen(keyboardEventTarget, EventType.KEYPRESS, this.handleBrowserEvent, this),
];
// 绑定resize事件
if (!this.handleResize_) {
this.handleResize_ = this.updateSize.bind(this);
window.addEventListener(EventType.RESIZE, this.handleResize_, false);
}
}
// 各交互事件触发的方法
PluggableMap.prototype.handleMapBrowserEvent = function (mapBrowserEvent) {
var interactionsArray = this.getInteractions().getArray(); // 取出所有绑定的 Interactions
if (this.dispatchEvent(mapBrowserEvent) !== false) {
for (var i = interactionsArray.length - 1; i >= 0; i--) {
var interaction = interactionsArray[i];
if (!interaction.getActive()) { //判断是否处于激活状态
continue;
}
//调用执行各Interactions子类的处理方法
var cont = interaction.handleEvent(mapBrowserEvent);
if (!cont) {
break;
}
}
}
}
Interactions
的子类DoubleClickZoom
为例,看事件响应部分
DoubleClickZoom.prototype.handleEvent = function (mapBrowserEvent) {
var stopEvent = false;
// 判断下是否触发的是自己,再响应
if (mapBrowserEvent.type == MapBrowserEventType.DBLCLICK) {
var browserEvent = (mapBrowserEvent.originalEvent);
var map = mapBrowserEvent.map;
var anchor = mapBrowserEvent.coordinate;
var delta = browserEvent.shiftKey ? -this.delta_ : this.delta_;
var view = map.getView();
zoomByDelta(view, delta, anchor, this.duration_);
mapBrowserEvent.preventDefault();
stopEvent = true;
}
return !stopEvent;
};
可以看到 ol 的事件基本都是在viewport
和target
上绑着,并没有直接绑定在canvas上
网友评论