UNPKG

qwc2

Version:
230 lines (224 loc) 8.21 kB
/** * 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()); } } };