ol-extent
Version:
a JavaScript library for openlayers extent
194 lines (176 loc) • 5.59 kB
JavaScript
/**
* Created by FDD on 2017/7/28.
* @desc 图层滤镜
*/
import ol from 'openlayers'
import { on, off, preventDefault } from '../utils';
class LayerMagnify extends ol.interaction.Pointer {
/**
* 处理移动事件
* @param mapBrowserEvent
*/
static handleMoveEvent_ = function (mapBrowserEvent) {
this.mousePosition = mapBrowserEvent['pixel'];
this.getMap().render();
};
/**
* 初始化事件处理机
* @param evt
* @returns {*}
* @private
*/
static handleEvent_ = function (evt) {
return ol.interaction.Pointer.handleEvent.call(this, evt);
};
constructor (options = {}) {
super({
handleEvent: LayerMagnify.handleEvent_,
handleMoveEvent: LayerMagnify.handleMoveEvent_
});
if (options['magnifyLayer']) {
this.magnifyLayer = options['magnifyLayer']
} else {
throw new Error('图层必须传入!')
}
/**
* 当前图层所在位置
* @type {null}
* @private
*/
this._currentLayerIndex = null;
/**
* 默认滤镜半径
* @type {number}
*/
this.radius = (typeof options['radius'] === 'number') ? options['radius'] : 75;
/**
* 滤镜最大半径
* @type {number}
*/
this.minRadius = (typeof options['minRadius'] === 'number') ? options['minRadius'] : 150;
/**
* 滤镜最小半径
* @type {number}
*/
this.maxRadius = (typeof options['maxRadius'] === 'number') ? options['maxRadius'] : 25;
/**
* 滤镜边框宽度
* @type {number}
*/
this.lineWidth = (typeof options['lineWidth'] === 'number') ? options['lineWidth'] : 2;
/**
* 滤镜边线颜色
* @type {number}
*/
this.strokeStyle = (options['strokeStyle'] ? options['strokeStyle'] : 'rgba(0, 0, 0, 0.5)');
/**
* 滤镜放大对应键值
* @type {number}
*/
this.zoomInKeyCode = options['zoomInKeyCode'] !== undefined ? options['zoomInKeyCode'] : 38;
/**
* 滤镜缩小对应键值
* @type {number}
*/
this.zoomOutKeyCode = options['zoomOutKeyCode'] !== undefined ? options['zoomOutKeyCode'] : 40;
/**
* 当前鼠标位置
* @type {null}
*/
this.mousePosition = null;
}
/**
* 初始化渲染事件
* @private
*/
initEvents_ () {
if (this.getMap()) {
on(this.getMap().getTargetElement(), 'mouseout', this.handleMouseOut_, this);
on(document, 'keydown', this.handleKeyDown_, this);
// before rendering the layer, do some clipping
this.magnifyLayer.on('postcompose', this.handlePostcompose_, this);
}
}
/**
* 处理鼠标移除事件
* @param event
* @private
*/
handleMouseOut_ (event) {
this.mousePosition = null;
this.getMap().render();
}
/**
* 处理键盘事件
* @param event
* @private
*/
handleKeyDown_ (event) {
preventDefault(event);
if (event.which === this.zoomInKeyCode) {
this.radius = Math.min(this.radius + 5, 150);
} else if (event.which === this.zoomOutKeyCode) {
this.radius = Math.max(this.radius - 5, 25);
}
this.getMap().render();
}
/**
* 图层开始渲染之前事件处理
* @param event
* @private
*/
handlePostcompose_ (event) {
if (this.mousePosition) {
let [context, pixelRatio] = [event.context, event.frameState.pixelRatio];
let half = this.radius * pixelRatio;
let [centerX, centerY] = [this.mousePosition[0] * pixelRatio, this.mousePosition[1] * pixelRatio];
let [originX, originY, size] = [centerX - half, centerY - half, (2 * half + 1)];
let sourceData = context.getImageData(originX, originY, size, size).data;
let dest = context.createImageData(size, size);
let destData = dest.data;
for (let j = 0; j < size; ++j) {
for (let i = 0; i < size; ++i) {
let dI = i - half;
let dJ = j - half;
let dist = Math.sqrt(dI * dI + dJ * dJ);
let sourceI = i;
let sourceJ = j;
if (dist < half) {
sourceI = Math.round(half + dI / 2);
sourceJ = Math.round(half + dJ / 2);
}
let destOffset = (j * size + i) * 4;
let sourceOffset = (sourceJ * size + sourceI) * 4;
destData[destOffset] = sourceData[sourceOffset];
destData[destOffset + 1] = sourceData[sourceOffset + 1];
destData[destOffset + 2] = sourceData[sourceOffset + 2];
destData[destOffset + 3] = sourceData[sourceOffset + 3];
}
}
context.beginPath();
context.arc(centerX, centerY, half, 0, 2 * Math.PI, false);
context.lineWidth = this.lineWidth * pixelRatio;
context.strokeStyle = this.strokeStyle;
context.putImageData(dest, originX, originY);
context.stroke();
context.restore();
}
}
/**
* 设置地图对象
* @param map
*/
setMap (map) {
if (map && map instanceof ol.Map) {
super.setMap.call(this, map);
this.initEvents_();
} else {
off(this.getMap().getTargetElement(), 'mouseout', this.handleMouseOut_, this);
off(document, 'keydown', this.handleKeyDown_, this);
// after rendering the layer, restore the canvas context
this.magnifyLayer.un('postcompose', this.handlePostcompose_, this);
super.setMap.call(this, map);
}
}
}
export default LayerMagnify