ol-ext
Version:
A set of cool extensions for OpenLayers (ol) in node modules structure
176 lines (157 loc) • 5.14 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 {unByKey as ol_Observable_unByKey} from 'ol/Observable.js'
import ol_interaction_Pointer from 'ol/interaction/Pointer.js'
import ol_ext_getMapCanvas from '../util/getMapCanvas.js'
/** Interaction splitter: acts as a split feature agent while editing vector features (LineString).
* @constructor
* @extends {ol_interaction_Pointer}
* @param {Object} options
* @param {function|undefined} onDrag Function handling "drag" events. It provides a dpixel and a traction (in projection) vector form the center of the compas
* @param {Number} options.size size of the compass in px, default 80
* @param {Number} options.alpha opacity of the compass, default 0.5
*/
var ol_interaction_TouchCompass = class olinteractionTouchCompass extends ol_interaction_Pointer {
constructor(options) {
options = options || {};
var opt = {};
// Click on the compass
opt.handleDownEvent = function (e) {
var s = this.getCenter_();
var dx = e.pixel[0] - s[0];
var dy = e.pixel[1] - s[1];
this.start = e;
return (Math.sqrt(dx * dx + dy * dy) < this.size / 2);
};
// Pn drag
opt.handleDragEvent = function (e) {
if (!this.pos) {
this.pos = this.start;
try { this.getMap().renderSync(); } catch (e) { /* ok */ }
}
this.pos = e;
};
// Stop drag
opt.handleUpEvent = function () {
this.pos = false;
return true;
};
super(opt);
this.ondrag_ = options.onDrag;
this.size = options.size || 80;
this.alpha = options.alpha || 0.5;
if (!this.compass) {
var canvas = this.compass = document.createElement('canvas');
var ctx = canvas.getContext("2d");
var s = canvas.width = canvas.height = this.size;
var w = s / 10;
var r = s / 2;
var r2 = 0.22 * r;
ctx.translate(r, r);
ctx.fillStyle = "#999";
ctx.strokeStyle = "#ccc";
ctx.lineWidth = w;
ctx.beginPath();
ctx.arc(0, 0, s * 0.42, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.fillStyle = "#99f";
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(r, 0); ctx.lineTo(r2, r2); ctx.moveTo(0, 0);
ctx.lineTo(-r, 0); ctx.lineTo(-r2, -r2); ctx.moveTo(0, 0);
ctx.lineTo(0, r); ctx.lineTo(-r2, r2); ctx.moveTo(0, 0);
ctx.lineTo(0, -r); ctx.lineTo(r2, -r2); ctx.moveTo(0, 0);
ctx.fill();
ctx.fillStyle = "#eee";
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(r, 0); ctx.lineTo(r2, -r2); ctx.moveTo(0, 0);
ctx.lineTo(-r, 0); ctx.lineTo(-r2, r2); ctx.moveTo(0, 0);
ctx.lineTo(0, r); ctx.lineTo(r2, r2); ctx.moveTo(0, 0);
ctx.lineTo(0, -r); ctx.lineTo(-r2, -r2); ctx.moveTo(0, 0);
ctx.fill();
}
}
/**
* Remove the interaction from its current map, if any, and attach it to a new
* map, if any. Pass `null` to just remove the interaction from the current map.
* @param {_ol_Map_} map Map.
* @api stable
*/
setMap(map) {
if (this._listener) ol_Observable_unByKey(this._listener);
this._listener = null;
super.setMap(map);
if (map) {
this._listener = map.on('postcompose', this.drawCompass_.bind(this));
ol_ext_getMapCanvas(map);
}
}
/**
* Activate or deactivate the interaction.
* @param {boolean} active Active.
* @observable
* @api
*/
setActive(b) {
super.setActive(b);
if (this.getMap()) {
try { this.getMap().renderSync(); } catch (e) { /* ok */ }
}
}
/**
* Get the center of the compass
* @param {_ol_coordinate_}
* @private
*/
getCenter_() {
var margin = 10;
var s = this.size;
var c = this.getMap().getSize();
return [c[0] / 2, c[1] - margin - s / 2];
}
/**
* Draw the compass on post compose
* @private
*/
drawCompass_(e) {
if (!this.getActive())
return;
var ctx = e.context || ol_ext_getMapCanvas(this.getMap()).getContext('2d');
var ratio = e.frameState.pixelRatio;
ctx.save();
ctx.scale(ratio, ratio);
ctx.globalAlpha = this.alpha;
ctx.strokeStyle = "#fff";
ctx.lineWidth = 5;
var s = this.size;
var c = this.getCenter_();
ctx.drawImage(this.compass, 0, 0, this.compass.width, this.compass.height, c[0] - s / 2, c[1] - s / 2, s, s);
if (this.pos) {
var dx = this.pos.pixel[0] - this.start.pixel[0];
var dy = this.pos.pixel[1] - this.start.pixel[1];
for (var i = 1; i <= 4; i++) {
ctx.beginPath();
ctx.arc(c[0] + dx / 4 * i, c[1] + dy / 4 * i, s / 2 * (0.6 + 0.4 * i / 4), 0, 2 * Math.PI);
ctx.stroke();
}
}
ctx.restore();
if (this.pos) { // Get delta
if (this.ondrag_) {
var r = this.getMap().getView().getResolution();
var delta = {
dpixel: [this.pos.pixel[0] - this.start.pixel[0], this.pos.pixel[1] - this.start.pixel[1]]
};
delta.traction = [delta.dpixel[0] * r, -delta.dpixel[1] * r];
this.ondrag_(delta, this.pos);
}
// Continue animation
e.frameState.animate = true;
}
}
}
export default ol_interaction_TouchCompass