qwc2
Version:
QGIS Web Client
230 lines (224 loc) • 8.21 kB
JavaScript
/**
* Copyright 2015 GeoSolutions Sas
* Copyright 2016-2024 Sourcepole AG
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
import React from 'react';
import ol from 'openlayers';
var layersMap;
var rendererItem;
// internal state for visibility of all Google Maps layers in layer tree
var layerVisibilities = {};
var gmaps = {};
var isTouchSupported = 'ontouchstart' in window;
var startEvent = isTouchSupported ? 'touchstart' : 'mousedown';
var moveEvent = isTouchSupported ? 'touchmove' : 'mousemove';
var endEvent = isTouchSupported ? 'touchend' : 'mouseup';
// NOTE: For the GoogleLayer to work, you MUST use EPSG:3857 as map projection and the google mercator scales:
// [591658711,295829355,147914678,73957339,36978669,18489335,9244667,4622334,2311167,1155583,577792,288896,144448,72224,36112,18056,9028,4514,2257,1128,564,282,141,71,35,18,9,4,2]
export default {
create: function create(options, map) {
var google = window.google;
var mapId = map.get('id');
if (mapId !== 'map') {
// ignore if not main map, e.g. overview
return null;
}
if (!layersMap) {
layersMap = {
HYBRID: google.maps.MapTypeId.HYBRID,
SATELLITE: google.maps.MapTypeId.SATELLITE,
ROADMAP: google.maps.MapTypeId.ROADMAP,
TERRAIN: google.maps.MapTypeId.TERRAIN
};
}
if (!gmaps[mapId]) {
gmaps[mapId] = new google.maps.Map(document.getElementById(mapId + 'gmaps'), {
disableDefaultUI: true,
keyboardShortcuts: false,
draggable: false,
disableDoubleClickZoom: true,
scrollwheel: false,
streetViewControl: false,
tilt: 0
});
}
gmaps[mapId].setMapTypeId(layersMap[options.name]);
var mapContainer = document.getElementById(mapId + 'gmaps');
var setCenter = function setCenter() {
if (mapContainer.style.visibility !== 'hidden') {
var center = ol.proj.transform(map.getView().getCenter(), 'EPSG:3857', 'EPSG:4326');
gmaps[mapId].setCenter(new google.maps.LatLng(center[1], center[0]));
}
};
var setZoom = function setZoom() {
if (mapContainer.style.visibility !== 'hidden') {
gmaps[mapId].setZoom(Math.round(map.getView().getZoom()));
}
};
/**
* @param point {array}: [x, y]
* @param alpha {number}: rotation in degrees
*/
var rotatePoint = function rotatePoint(point, alpha) {
var radAlpha = alpha * Math.PI / 180;
var x = point[0];
var y = point[1];
var rx = x * Math.cos(radAlpha) - y * Math.sin(radAlpha);
var ry = x * Math.sin(radAlpha) + y * Math.cos(radAlpha);
return [rx, ry];
};
/**
* @param rotation {number}: rotation in degrees
* @param size {array}: map size [w, h]
*/
var calculateRotatedSize = function calculateRotatedSize(rotation, size) {
var w = size[0];
var h = size[1];
var vertices = [
// [ x , y ]
[w / 2, h / 2], [-w / 2, h / 2], [-w / 2, -h / 2], [w / 2, -h / 2]];
var rVertices = vertices.map(function (p) {
return rotatePoint(p, rotation);
});
var Xs = rVertices.map(function (p) {
return p[0];
});
var Ys = rVertices.map(function (p) {
return p[1];
});
var maxX = Math.max.apply(null, Xs);
var minX = Math.min.apply(null, Xs);
var maxY = Math.max.apply(null, Ys);
var minY = Math.min.apply(null, Ys);
var H = Math.abs(maxY) + Math.abs(minY);
var W = Math.abs(maxX) + Math.abs(minX);
return {
width: W,
height: H
};
};
var setRotation = function setRotation() {
if (mapContainer.style.visibility !== 'hidden') {
var rotation = map.getView().getRotation() * 180 / Math.PI;
mapContainer.style.transform = "rotate(" + rotation + "deg)";
google.maps.event.trigger(gmaps[mapId], "resize");
}
};
var setViewEventListeners = function setViewEventListeners() {
var view = map.getView();
view.on('change:center', setCenter);
view.on('change:resolution', setZoom);
view.on('change:rotation', setRotation);
};
map.on('change:view', setViewEventListeners);
setViewEventListeners();
setCenter();
setZoom();
var viewport = map.getViewport();
var oldTrans = document.getElementById(mapId + 'gmaps').style.transform;
var mousedown = false;
var mousemove = false;
var resizeGoogleLayerIfRotated = function resizeGoogleLayerIfRotated() {
var degrees = /[+-]?\d+\.?\d*/i;
var newTrans = document.getElementById(mapId + 'gmaps').style.transform;
if (newTrans !== oldTrans && newTrans.indexOf('rotate') !== -1) {
var rotation = parseFloat(newTrans.match(degrees)[0]);
var size = calculateRotatedSize(-rotation, map.getSize());
mapContainer.style.width = size.width + 'px';
mapContainer.style.height = size.height + 'px';
mapContainer.style.left = Math.round((map.getSize()[0] - size.width) / 2.0) + 'px';
mapContainer.style.top = Math.round((map.getSize()[1] - size.height) / 2.0) + 'px';
google.maps.event.trigger(gmaps[mapId], "resize");
setCenter();
}
};
viewport.addEventListener(startEvent, function () {
mousedown = true;
});
viewport.addEventListener(endEvent, function () {
if (mousemove && mousedown) {
resizeGoogleLayerIfRotated();
}
oldTrans = document.getElementById(mapId + 'gmaps').style.transform;
mousedown = false;
});
viewport.addEventListener(moveEvent, function () {
mousemove = mousedown;
});
return null;
},
render: function render(options, map) {
var mapId = map.get('id');
if (mapId !== 'map') {
// ignore if not main map, e.g. overview
return null;
}
// the first item that call render will take control
if (!rendererItem) {
rendererItem = options.name;
}
var wrapperStyle = {
zIndex: -1,
position: 'fixed',
left: 0,
right: 0,
top: 0,
bottom: 0
};
var gmapsStyle = {
height: '100%'
};
var visibilityChanged = layerVisibilities[options.id] !== options.visibility;
layerVisibilities[options.id] = options.visibility;
if (options.visibility === true) {
var div = document.getElementById(mapId + "gmaps");
if (div) {
// override div visibility
div.style.visibility = 'visible';
}
if (gmaps[mapId] && layersMap) {
gmaps[mapId].setMapTypeId(layersMap[options.name]);
gmaps[mapId].setTilt(0);
if (visibilityChanged) {
// update map extent when turning visibility on
var center = ol.proj.transform(map.getView().getCenter(), 'EPSG:3857', 'EPSG:4326');
gmaps[mapId].setCenter(new window.google.maps.LatLng(center[1], center[0]));
gmaps[mapId].setZoom(map.getView().getZoom());
}
}
} else {
gmapsStyle.visibility = 'hidden'; // used only for the renered div
}
// To hide the map when visibility is set to false for every
// instance of google layer
if (rendererItem === options.name) {
// assume the first render the div for gmaps
var _div = document.getElementById(mapId + "gmaps");
if (_div) {
_div.style.visibility = options.visibility ? 'visible' : 'hidden';
}
return /*#__PURE__*/React.createElement("div", {
style: wrapperStyle
}, /*#__PURE__*/React.createElement("div", {
className: "fill",
id: mapId + "gmaps",
style: gmapsStyle
}));
}
return null;
},
update: function update(layer, newOptions, oldOptions, map) {
var mapId = map.get('id');
var google = window.google;
if (!oldOptions.visibility && newOptions.visibility) {
var view = map.getView();
var center = ol.proj.transform(view.getCenter(), 'EPSG:3857', 'EPSG:4326');
gmaps[mapId].setCenter(new google.maps.LatLng(center[1], center[0]));
gmaps[mapId].setZoom(view.getZoom());
}
}
};