ol-ext
Version:
A set of cool extensions for OpenLayers (ol) in node modules structure
173 lines (165 loc) • 5.77 kB
JavaScript
/* Copyright (c) 2016 Jean-Marc VIGLINO,
released under the CeCILL-B license (French BSD license)
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
*/
import ol_filter_Base from './Base.js'
import {asString as ol_color_asString} from 'ol/color.js'
/** Mask drawing using an ol.Feature
* @constructor
* @requires ol_filter
* @extends {ol_filter_Base}
* @param {Object} [options]
* @param {ol.Feature} [options.feature] feature to mask with
* @param {ol.style.Fill} [options.fill] style to fill with
* @param {number} [options.shadowWidth=0] shadow width, default no shadow
* @param {boolean} [options.shadowMapUnits=false] true if the shadow width is in mapUnits
* @param {ol.colorLike} [options.shadowColor='rgba(0,0,0,.5)'] shadow color, default
* @param {boolean} [options.inner=false] mask inner, default false
* @param {boolean} [options.wrapX=false] wrap around the world, default false
*/
var ol_filter_Mask = class olfilterMask extends ol_filter_Base {
constructor(options) {
options = options || {};
super(options);
if (options.feature) {
switch (options.feature.getGeometry().getType()) {
case 'Polygon':
case 'MultiPolygon':
this.feature_ = options.feature;
break;
default: break;
}
}
this.set('inner', options.inner);
this._fillColor = options.fill ? ol_color_asString(options.fill.getColor()) || 'rgba(0,0,0,0.2)' : 'rgba(0,0,0,0.2)';
this._shadowColor = options.shadowColor ? ol_color_asString(options.shadowColor) || 'rgba(0,0,0,0.5)' : 'rgba(0,0,0,0.5)';
this.set('shadowWidth', options.shadowWidth || 0);
this.set('shadowMapUnits', options.shadowMapUnits === true);
}
/** Set filter fill color
* @param {ol/colorLike} color
*/
setFillColor(color) {
this._fillColor = color ? ol_color_asString(color) || 'rgba(0,0,0,0.2)' : 'rgba(0,0,0,0.2)';
}
/** Set filter shadow color
* @param {ol/colorLike} color
*/
setShadowColor(color) {
this._shadowColor = color ? ol_color_asString(color) || 'rgba(0,0,0,0.5)' : 'rgba(0,0,0,0.5)';
}
/** Draw the feature into canvas
* @private
*/
drawFeaturePath_(e, out) {
var ctx = e.context;
var canvas = ctx.canvas;
var ratio = e.frameState.pixelRatio;
// Transform
var tr;
if (e.frameState.coordinateToPixelTransform) {
var m = e.frameState.coordinateToPixelTransform;
// ol > 6
if (e.inversePixelTransform) {
var ipt = e.inversePixelTransform;
tr = function (pt) {
pt = [
(pt[0] * m[0] + pt[1] * m[1] + m[4]),
(pt[0] * m[2] + pt[1] * m[3] + m[5])
];
return [
(pt[0] * ipt[0] - pt[1] * ipt[1] + ipt[4]),
(-pt[0] * ipt[2] + pt[1] * ipt[3] + ipt[5])
];
};
} else {
// ol 5
tr = function (pt) {
return [
(pt[0] * m[0] + pt[1] * m[1] + m[4]) * ratio,
(pt[0] * m[2] + pt[1] * m[3] + m[5]) * ratio
];
};
}
} else {
// Older version
m = e.frameState.coordinateToPixelMatrix;
tr = function (pt) {
return [
(pt[0] * m[0] + pt[1] * m[1] + m[12]) * ratio,
(pt[0] * m[4] + pt[1] * m[5] + m[13]) * ratio
];
};
}
// Geometry
var ll = this.feature_.getGeometry().getCoordinates();
if (this.feature_.getGeometry().getType() === 'Polygon')
ll = [ll];
// Draw feature at dx world
function drawll(dx) {
for (var l = 0; l < ll.length; l++) {
var c = ll[l];
for (var i = 0; i < c.length; i++) {
var pt = tr([c[i][0][0] + dx, c[i][0][1]]);
ctx.moveTo(pt[0], pt[1]);
for (var j = 1; j < c[i].length; j++) {
pt = tr([c[i][j][0] + dx, c[i][j][1]]);
ctx.lineTo(pt[0], pt[1]);
}
}
}
}
ctx.beginPath();
if (out) {
ctx.moveTo(-100, -100);
ctx.lineTo(canvas.width + 100, -100);
ctx.lineTo(canvas.width + 100, canvas.height + 100);
ctx.lineTo(-100, canvas.height + 100);
ctx.lineTo(-100, -100);
}
// Draw current world
if (this.get('wrapX')) {
var worldExtent = e.frameState.viewState.projection.getExtent();
var worldWidth = worldExtent[2] - worldExtent[0];
var extent = e.frameState.extent;
var fExtent = this.feature_.getGeometry().getExtent();
var fWidth = fExtent[2] - fExtent[1];
var start = Math.floor((extent[0] - fWidth - worldExtent[0]) / worldWidth);
var end = Math.floor((extent[2] + fWidth - worldExtent[2]) / worldWidth) + 1;
if (start > end) {
[start, end] = [end, start];
}
for (var i = start; i <= end; i++) {
drawll(i * worldWidth);
}
} else {
drawll(0);
}
}
/**
* @param {ol/Event} e
* @private
*/
postcompose(e) {
if (!this.feature_) return;
var ctx = e.context;
ctx.save();
this.drawFeaturePath_(e, !this.get('inner'));
ctx.fillStyle = this._fillColor;
ctx.fill('evenodd');
// Draw shadow
if (this.get('shadowWidth')) {
var width = this.get('shadowWidth') * e.frameState.pixelRatio
if (this.get('shadowMapUnits')) width /= e.frameState.viewState.resolution;
ctx.clip('evenodd');
ctx.filter = 'blur(' + width + 'px)';
ctx.strokeStyle = this._shadowColor;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.lineWidth = width;
ctx.stroke();
}
ctx.restore();
}
}
export default ol_filter_Mask