272 lines
8.1 KiB
JavaScript
272 lines
8.1 KiB
JavaScript
/* Copyright (c) 2017 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_control_CanvasBase from './CanvasBase.js'
|
|
import ol_style_Style from 'ol/style/Style.js'
|
|
import ol_style_Stroke from 'ol/style/Stroke.js'
|
|
import ol_ext_element from '../util/element.js';
|
|
|
|
/**
|
|
* Draw a compass on the map. The position/size of the control is defined in the css.
|
|
*
|
|
* @constructor
|
|
* @extends {ol_control_CanvasBase}
|
|
* @param {Object=} options Control options. The style {_ol_style_Stroke_} option is usesd to draw the text.
|
|
* @param {string} options.className class name for the control
|
|
* @param {boolean} [options.visible=true]
|
|
* @param {Image} options.image an image, default use the src option or a default image
|
|
* @param {string} options.src image src or 'default' or 'compact', default use the image option or a default image
|
|
* @param {boolean} options.rotateVithView rotate vith view (false to show watermark), default true
|
|
* @param {ol_style_Stroke} options.style style to draw the lines, default draw no lines
|
|
*/
|
|
var ol_control_Compass = class olcontrolCompass extends ol_control_CanvasBase {
|
|
constructor(options) {
|
|
options = options || {};
|
|
|
|
// Initialize parent
|
|
var elt = document.createElement("div");
|
|
elt.className = "ol-control ol-compassctrl ol-unselectable ol-hidden" + (options.className ? " " + options.className : "");
|
|
elt.style.position = "absolute";
|
|
elt.style.visibility = "hidden";
|
|
|
|
var style = (options.style instanceof ol_style_Stroke) ? new ol_style_Style({ stroke: options.style }) : options.style;
|
|
if (!options.style) {
|
|
style = new ol_style_Style({ stroke: new ol_style_Stroke({ width: 0 }) });
|
|
}
|
|
super({
|
|
element: elt,
|
|
style: style
|
|
});
|
|
|
|
this.set('rotateVithView', options.rotateWithView !== false);
|
|
this.setVisible(options.visible !== false);
|
|
|
|
this.setImage(options.image || options.src);
|
|
}
|
|
/** Set compass image
|
|
* @param {Image|string} [img=default] the image or an url or 'compact' or 'default'
|
|
*/
|
|
setImage(img) {
|
|
// The image
|
|
if (img instanceof Image) {
|
|
this.img_ = img;
|
|
this.img_.onload = function () {
|
|
if (this.getMap()) {
|
|
try { this.getMap().renderSync(); } catch (e) { /* ok */ }
|
|
}
|
|
}.bind(this);
|
|
} else if (typeof (img) === 'string') {
|
|
// Load source
|
|
switch (img) {
|
|
case 'compact': {
|
|
this.img_ = this.compactCompass_(this.element.clientWidth, this.getStroke().getColor());
|
|
break;
|
|
}
|
|
case 'default': {
|
|
this.img_ = this.defaultCompass_(this.element.clientWidth, this.getStroke().getColor());
|
|
break;
|
|
}
|
|
default: {
|
|
this.img_ = new Image();
|
|
this.img_.onload = function () {
|
|
if (this.getMap()) {
|
|
try { this.getMap().renderSync(); } catch (e) { /* ok */ }
|
|
}
|
|
}.bind(this);
|
|
this.img_.src = img;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
this.img_ = this.defaultCompass_(this.element.clientWidth, this.getStroke().getColor());
|
|
}
|
|
}
|
|
/** Create a default image.
|
|
* @param {number} s the size of the compass
|
|
* @private
|
|
*/
|
|
compactCompass_(s, color) {
|
|
var canvas = document.createElement('canvas');
|
|
var ctx = canvas.getContext("2d");
|
|
s = canvas.width = canvas.height = s || 150;
|
|
var r = s / 2;
|
|
|
|
ctx.translate(r, r);
|
|
ctx.fillStyle = color || '#963';
|
|
ctx.lineWidth = 5;
|
|
ctx.lineJoin = ctx.lineCap = 'round';
|
|
|
|
ctx.font = 'bold ' + (r * 0.4) + 'px sans-serif';
|
|
ctx.textBaseline = 'bottom';
|
|
ctx.textAlign = 'center';
|
|
ctx.strokeStyle = '#fff';
|
|
ctx.globalAlpha = .75;
|
|
ctx.strokeText('N', 0, -r / 2);
|
|
ctx.globalAlpha = 1;
|
|
ctx.fillText('N', 0, -r / 2);
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, r / 4);
|
|
ctx.lineTo(r / 3, r / 2);
|
|
ctx.lineTo(0, -r / 2);
|
|
ctx.lineTo(-r / 3, r / 2);
|
|
ctx.lineTo(0, r / 4);
|
|
ctx.lineWidth = 12;
|
|
ctx.fillStyle = "#fff";
|
|
ctx.globalAlpha = .75;
|
|
ctx.fill();
|
|
ctx.stroke();
|
|
ctx.globalAlpha = 1;
|
|
|
|
ctx.fillStyle = ctx.strokeStyle = color || '#963';
|
|
ctx.lineWidth = 5;
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, r / 4);
|
|
ctx.lineTo(0, -r / 2);
|
|
ctx.lineTo(r / 3, r / 2);
|
|
ctx.lineTo(0, r / 4);
|
|
ctx.fill();
|
|
ctx.stroke();
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, r / 4);
|
|
ctx.lineTo(0, -r / 2);
|
|
ctx.lineTo(-r / 3, r / 2);
|
|
ctx.lineTo(0, r / 4);
|
|
ctx.stroke();
|
|
|
|
return canvas;
|
|
}
|
|
/** Create a default image.
|
|
* @param {number} s the size of the compass
|
|
* @private
|
|
*/
|
|
defaultCompass_(s, color) {
|
|
var canvas = document.createElement('canvas');
|
|
var ctx = canvas.getContext("2d");
|
|
s = canvas.width = canvas.height = s || 150;
|
|
var r = s / 2;
|
|
var r2 = 0.22 * r;
|
|
|
|
function draw(r, r2) {
|
|
ctx.fillStyle = color || "#963";
|
|
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.stroke();
|
|
}
|
|
|
|
function draw2(r, r2) {
|
|
ctx.globalCompositeOperation = "destination-out";
|
|
ctx.fillStyle = "#fff";
|
|
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.globalCompositeOperation = "source-over";
|
|
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.stroke();
|
|
}
|
|
|
|
ctx.translate(r, r);
|
|
ctx.strokeStyle = color || "#963";
|
|
ctx.lineWidth = 1.5;
|
|
ctx.beginPath();
|
|
ctx.arc(0, 0, s * 0.41, 0, 2 * Math.PI);
|
|
ctx.arc(0, 0, s * 0.44, 0, 2 * Math.PI);
|
|
ctx.stroke();
|
|
|
|
ctx.rotate(Math.PI / 4);
|
|
draw(r * 0.9, r2 * 0.8);
|
|
draw2(r * 0.9, r2 * 0.8);
|
|
|
|
ctx.rotate(-Math.PI / 4);
|
|
draw(r, r2);
|
|
draw2(r, r2);
|
|
|
|
return canvas;
|
|
}
|
|
/** Get control visibility
|
|
* @return {boolean}
|
|
*/
|
|
getVisible() {
|
|
return ol_ext_element.getStyle(this.element, 'display') === 'block';
|
|
}
|
|
/** Set visibility
|
|
* @param {boolean} b
|
|
*/
|
|
setVisible(b) {
|
|
if (b)
|
|
this.element.classList.add('ol-visible');
|
|
else
|
|
this.element.classList.remove('ol-visible');
|
|
if (this.getMap())
|
|
this.getMap().render();
|
|
}
|
|
/** Draw compass
|
|
* @param {ol.event} e postcompose event
|
|
* @private
|
|
*/
|
|
_draw(e) {
|
|
var ctx = this.getContext(e);
|
|
if (!ctx || !this.getVisible())
|
|
return;
|
|
var canvas = ctx.canvas;
|
|
|
|
// 8 angles
|
|
var i, da = [];
|
|
for (i = 0; i < 8; i++)
|
|
da[i] = [Math.cos(Math.PI * i / 8), Math.sin(Math.PI * i / 8)];
|
|
|
|
// Retina device
|
|
var ratio = e.frameState.pixelRatio;
|
|
ctx.save();
|
|
ctx.scale(ratio, ratio);
|
|
|
|
var w = this.element.clientWidth;
|
|
var h = this.element.clientHeight;
|
|
var pos = { left: this.element.offsetLeft, top: this.element.offsetTop };
|
|
|
|
var compass = this.img_;
|
|
var rot = e.frameState.viewState.rotation;
|
|
|
|
ctx.beginPath();
|
|
ctx.translate(pos.left + w / 2, pos.top + h / 2);
|
|
if (this.get('rotateVithView'))
|
|
ctx.rotate(rot);
|
|
if (this.getStroke().getWidth()) {
|
|
ctx.beginPath();
|
|
ctx.strokeStyle = this.getStroke().getColor();
|
|
ctx.lineWidth = this.getStroke().getWidth();
|
|
var m = Math.max(canvas.width, canvas.height);
|
|
for (i = 0; i < 8; i++) {
|
|
ctx.moveTo(-da[i][0] * m, -da[i][1] * m);
|
|
ctx.lineTo(da[i][0] * m, da[i][1] * m);
|
|
}
|
|
ctx.stroke();
|
|
}
|
|
|
|
if (compass.width) {
|
|
ctx.drawImage(compass, -w / 2, -h / 2, w, h);
|
|
}
|
|
|
|
ctx.closePath();
|
|
|
|
ctx.restore();
|
|
}
|
|
}
|
|
|
|
export default ol_control_Compass |