From d515804f6d0f0704b14013f76417115b73e650af Mon Sep 17 00:00:00 2001 From: dadiorchen Date: Tue, 23 Mar 2021 07:05:35 +0000 Subject: [PATCH] feat: can display map with leaflet, (new code) --- .env | 1 + package-lock.json | 44 ++- package.json | 13 +- src/App.js | 29 +- src/MapModel.js | 88 ++++- src/map.js | 853 +++++++++++++++++++++++-------------------- src/mapTools.js | 37 +- src/mapTools.test.js | 19 - src/style.css | 95 +++++ 9 files changed, 688 insertions(+), 491 deletions(-) diff --git a/.env b/.env index a1c6122ec..03df8f425 100644 --- a/.env +++ b/.env @@ -1 +1,2 @@ REACT_APP_API=https://dev-k8s.treetracker.org/webmap/ +REACT_APP_TILE_SERVER_URL=https://dev-k8s.treetracker.org/tiles/ diff --git a/package-lock.json b/package-lock.json index 12cc7921b..d2a15fcfb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "client", - "version": "1.0.0", + "version": "0.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -7488,6 +7488,11 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "corslite": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/corslite/-/corslite-0.0.7.tgz", + "integrity": "sha1-jkUdtTIKdVbeHveNm9NWY0MHdyE=" + }, "cosmiconfig": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", @@ -8958,23 +8963,23 @@ "dev": true }, "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" } } }, @@ -12886,6 +12891,19 @@ "invert-kv": "^2.0.0" } }, + "leaflet": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.7.1.tgz", + "integrity": "sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw==" + }, + "leaflet-utfgrid": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/leaflet-utfgrid/-/leaflet-utfgrid-0.3.0.tgz", + "integrity": "sha1-a4e+3hmOgFCpiJchhShWMwI0Btk=", + "requires": { + "corslite": "0.0.7" + } + }, "left-pad": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", diff --git a/package.json b/package.json index 5d4dcae4a..461948906 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,7 @@ { "name": "client", - "version": "1.0.0", + "version": "0.1.1", "private": true, - "repository": { - "type": "git", - "url": "git+https://github.com/Greenstand/treetracker-web-map-client.git" - }, - "author": "", - "license": "GNU", - "bugs": { - "url": "https://github.com/Greenstand/treetracker-web-map-client/issues" - }, "dependencies": { "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -19,6 +10,8 @@ "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", "expect-runtime": "^0.4.0", + "leaflet": "^1.7.1", + "leaflet-utfgrid": "^0.3.0", "loglevel": "^1.7.0", "moment": "^2.29.1", "react": "^16.13.1", diff --git a/src/App.js b/src/App.js index dce1f0d82..50247f01f 100644 --- a/src/App.js +++ b/src/App.js @@ -265,7 +265,11 @@ function App() { const marker = map.getMarkerByPointId()[tree.id] if(marker){ expect(marker).defined(); - const {top, left} = mapTools.getPixelCoordinateByLatLng(marker.getPosition().lat(), marker.getPosition().lng(), map.getMap()); + const mapLeaflet = map.getMap(); + log.log("map leaflet:", mapLeaflet); +// const {top, left} = mapTools.getPixelCoordinateByLatLng(marker.getLatLng().lat, marker.getLatLng().lng, map.getMap()); + const {x:left, y:top} = mapLeaflet.latLngToContainerPoint(marker.getLatLng()); + log.log("top:", top, "left:", left); expect(top).number(); expect(left).number(); log.log("the point at:", top, left); @@ -303,7 +307,7 @@ function App() { const x = left - leftCenter; const y = top - topCenter; log.log("pant by x,y:", x, y); - map.getMap().panBy(x,y); + map.getMap().panBy(window.L.point(x,y)); } setHasNext(map.hasNextPoint()); setHasPrev(map.hasPrevPoint()); @@ -417,20 +421,13 @@ function App() { React.useEffect(() => { log.debug("useEffect 1"); - const script = document.createElement('script'); - script.src = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyDUGv1-FFd7NFUS6HWNlivbKwETzuIPdKE&libraries=geometry'; - script.id = 'googleMaps'; - document.body.appendChild(script); - - script.onload = () => { - //map.initialize(); - const map = load(); - mapRef.current.map = map; - expect(mapRef) - .property("current").defined(); - expect(map).property("rerender").defined(); - injectApp(); - }; + //map.initialize(); + injectApp(); + const map = load(); + mapRef.current.map = map; + expect(mapRef) + .property("current").defined(); + expect(map).property("rerender").defined(); }, []); /* diff --git a/src/MapModel.js b/src/MapModel.js index 105b44630..795a6a7e0 100644 --- a/src/MapModel.js +++ b/src/MapModel.js @@ -4,6 +4,7 @@ import expect from "expect-runtime"; import axios from "axios"; import log from "loglevel"; +import "leaflet"; class MapModel { constructor(options){ @@ -39,11 +40,66 @@ class MapModel { */ async checkArrow(){ log.log("check arrow"); + const mymap = this._map; + var utfGridLayer = Object.values(mymap._layers).reduce((a,c) => c._url && c._url.match(/grid.json$/)?c:a,undefined); + const {x,y} = mymap.getSize(); + + let found = false; + + //check zoom level + log.warn("zoom level:", mymap.getZoom()); + expect(utfGridLayer).property("options").property("minZoom").defined(); + if( + mymap.getZoom() > utfGridLayer.options.maxZoom || + mymap.getZoom() < utfGridLayer.options.minZoom + ){ + log.warn("out of utf layer range, use old way"); + if( + //no markers + this._markers.length === 0 || + //all markers out of bounds + this._markers.every(marker => !this._map.getBounds().contains(marker.getLatLng())) + ){ + found = false; + }else{ + found = true; + } + }else{ + log.warn("utf calculating"); + + //waiting layer is ready + let isLoading = utfGridLayer.isLoading(); + log.warn("utf layer is loading:", isLoading); + if(isLoading){ + log.error("can not handle the grid utif check, cancel!") + return; + } + + const begin = Date.now(); + let count = 0; + let countNoChar = 0; + me: for(let y1 = 0; y1 < y; y1 += 10){ + for(let x1 = 0; x1 < x; x1 +=10){ + count++; + const tileChar = utfGridLayer._objectForEvent({latlng:mymap.containerPointToLatLng([x1,y1])})._tileCharCode; + if(!tileChar){ + countNoChar++; + //log.warn("can not fond char on!:", x1, y1); + continue; + } + const m = tileChar.match(/\d+:\d+:\d+:(\d+)/); + if(!m) throw new Error("Wrong char:" + tileChar); + if(m[1] !== "32"){ + log.log("find:", tileChar, "at:", x1,y1); + found = true; + break me; + } + } + } + log.warn("Take time:%d, count:%d,%d,found:%s", Date.now() - begin, count, countNoChar, found); + } if( - //no markers - this._markers.length === 0 || - //all markers out of bounds - this._markers.every(marker => !this._map.getBounds().contains(marker.getPosition())) + !found ){ //no markers, need to find nearest const center = this._map.getCenter(); @@ -62,33 +118,33 @@ class MapModel { lat: nearest.lat, lng: nearest.lng, }; - const distanceLat = window.google.maps.geometry.spherical.computeDistanceBetween( + const distanceLat = window.L.CRS.EPSG3857.distance( center, - new window.google.maps.LatLng( + window.L.latLng( dist.lat, - center.lng() + center.lng ), ); log.log("distanceLat:", distanceLat); expect(distanceLat).number(); - const distanceLng = window.google.maps.geometry.spherical.computeDistanceBetween( + const distanceLng = window.L.CRS.EPSG3857.distance( center, - new window.google.maps.LatLng( - center.lat(), + window.L.latLng( + center.lat, dist.lng, ), ); log.log("distanceLng:", distanceLng); expect(distanceLng).number(); log.log("dist:", dist); - log.log("center:", center, center.lat()); - if(dist.lat > center.lat()){ + log.log("center:", center, center.lat); + if(dist.lat > center.lat){ log.log("On the north"); if(distanceLat > distanceLng){ log.log("On the north"); this.showArrow("north"); }else{ - if(dist.lng > center.lng()){ + if(dist.lng > center.lng){ log.log("On the east"); this.showArrow("east"); }else{ @@ -102,7 +158,7 @@ class MapModel { log.log("On the south"); this.showArrow("south"); }else{ - if(dist.lng > center.lng()){ + if(dist.lng > center.lng){ log.log("On the east"); this.showArrow("east"); }else{ @@ -168,9 +224,9 @@ class MapModel { this._cancelAxios("cancel previous nearest request"); } const center = this._map.getCenter(); - log.log("current center:", center.toJSON()); + log.log("current center:", center); const zoom_level = this._map.getZoom(); - const res = await axios.get(this.apiUrl + `nearest?zoom_level=${zoom_level}&lat=${center.lat()}&lng=${center.lng()}`, { + const res = await axios.get(this.apiUrl + `nearest?zoom_level=${zoom_level}&lat=${center.lat}&lng=${center.lng}`, { cancelToken: new axios.CancelToken((c) => { this._cancelAxios = c; }), diff --git a/src/map.js b/src/map.js index b169503f2..57910c6b9 100644 --- a/src/map.js +++ b/src/map.js @@ -7,6 +7,9 @@ import {theme} from "./App"; import {parseMapName} from "./utils"; import log from "loglevel"; import {mapConfig} from "./mapConfig"; +import 'leaflet'; +import 'leaflet/dist/leaflet.css'; +import "leaflet-utfgrid/L.UTFGrid-min.js"; const CancelToken = axios.CancelToken; let source; @@ -29,7 +32,7 @@ function load( const YES = "YES"; const NO = "NO"; -var map = undefined; //Google Map object +var map = undefined; //Leaflet Map object var mc = undefined; //Marker Clusterer var markers = []; //All the markers var mapModel = undefined; @@ -44,9 +47,8 @@ var clusterRadius; var firstQuery = true; var firstRender = true; var firstInteraction = false; -var initialBounds = new window.google.maps.LatLngBounds(); +var initialBounds = new window.L.latLngBounds([]); var loader; -var panelLoader; var currentZoom; var req = null; @@ -70,6 +72,11 @@ var loadingTimer = undefined; */ let timeline = undefined; +/* + * When mouse over the icon in tile pic, create the markerHighlight + */ +let markerHighlight = undefined; + if(process.env.REACT_APP_API){ treetrackerApiUrl = process.env.REACT_APP_API; }else{ @@ -194,6 +201,19 @@ var initMarkers = function(viewportBounds, zoomLevel) { log.log("request:", queryUrl); source = CancelToken.source(); + //for tile server version, if zoom level > 15, and it isn't cases like + //map_name, wallet, then do not request for points, just let the tile + //server works. + if( + queryUrl.match(/zoom_level=(16|17|18|19|20|21|22)/) && + !queryUrl.match(/(wallet|map_name|timeline|userid|token)/) + ){ + log.warn("quit, use tile server instead"); + clearOverlays(markers); + return; + } + + //loading getApp().loadingB(false); if(!firstRender){ @@ -231,7 +251,7 @@ var initMarkers = function(viewportBounds, zoomLevel) { data.data.forEach(function(item,i) { if (item.type == "cluster") { var centroid = JSON.parse(item.centroid); - var latLng = new window.google.maps.LatLng( + var latLng = new window.L.latLng( centroid.coordinates[1], centroid.coordinates[0] ); @@ -242,27 +262,32 @@ var initMarkers = function(viewportBounds, zoomLevel) { anchor = null; if (item.count <= 300) { iconUrl = require("./images/cluster_46px.png"); - labelOrigin = new window.google.maps.Point(23, 23); - anchor = new window.google.maps.Point(23, 23); + labelOrigin = new window.L.point(23, 23); + anchor = new window.L.point(23, 23); } else { iconUrl = require("./images/cluster_63px.png"); - labelOrigin = new window.google.maps.Point(32, 32); - anchor = new window.google.maps.Point(32, 32); + labelOrigin = new window.L.point(32, 32); + anchor = new window.L.point(32, 32); } - var marker = new window.google.maps.Marker({ - position: latLng, - map: map, - label: { - text: shortenLargeNumber(item.count).toString(), - color: "#000" - }, - icon: { - url: iconUrl, - labelOrigin: labelOrigin, - anchor: anchor - } - }); + if (item.count <= 300) { + iconUrl = require("./images/cluster_46px.png"); + } else { + iconUrl = require("./images/cluster_63px.png"); + } + var marker = new window.L.marker( + latLng, + { + icon: new window.L.DivIcon({ + className: "greenstand-cluster", + html: ` +
+
${shortenLargeNumber(item.count).toString()}
+
+ `, + }), + }); + marker.addTo(map); //add zoomTarget to cluster marker marker.zoomTarget = data.zoomTargets? @@ -280,91 +305,105 @@ var initMarkers = function(viewportBounds, zoomLevel) { : undefined; - window.google.maps.event.addListener(marker, "click", function() { - window.google.maps.event.clearListeners(marker, "mouseover"); - window.google.maps.event.clearListeners(marker, "mouseout"); - if (item.count <= 300) { - marker.setIcon({ - ...marker.getIcon(), - url: require("./images/cluster_46px_clicked.png"), - }); - } else { - marker.setIcon({ - ...marker.getIcon(), - url: require("./images/cluster_63px_clicked.png"), - }); - } + marker.on("click", function() { + log.debug("marker click"); + log.debug("click marker:", marker); +// window.google.maps.event.clearListeners(marker, "mouseover"); +// window.google.maps.event.clearListeners(marker, "mouseout"); +// if (item.count <= 300) { +// marker.setIcon({ +// ...marker.getIcon(), +// url: require("./images/cluster_46px_clicked.png"), +// }); +// } else { +// marker.setIcon({ +// ...marker.getIcon(), +// url: require("./images/cluster_63px_clicked.png"), +// }); +// } + //icon + window.L.DomUtil.addClass(marker._icon, "clicked"); if(marker.zoomTarget){ fetchMarkers = false; var zoomLevel = map.getZoom(); - map.setZoom(zoomLevel + 2); const centroid = JSON.parse(marker.zoomTarget.centroid); const position = { lat: centroid.coordinates[1], lng: centroid.coordinates[0], } log.log("zoom target:", position); - map.panTo(position); + map.flyTo( + window.L.latLng( + centroid.coordinates[1], + centroid.coordinates[0] + ), + zoomLevel + 2, + ); }else{ fetchMarkers = false; var zoomLevel = map.getZoom(); - map.setZoom(zoomLevel + 2); - map.panTo(marker.position); + map.flyTo(marker.getLatLng(), zoomLevel+2); } }); - //the hover - window.google.maps.event.addListener(marker, "mouseover", function(){ - if (item.count <= 300) { - marker.setIcon({ - ...marker.getIcon(), - url: require("./images/cluster_46px_highlight.png"), - }); - } else { - marker.setIcon({ - ...marker.getIcon(), - url: require("./images/cluster_63px_highlight.png"), - }); - } - }); - - window.google.maps.event.addListener(marker, "mouseout", function(){ - if (item.count <= 300) { - marker.setIcon({ - ...marker.getIcon(), - url: require("./images/cluster_46px.png"), - }); - } else { - marker.setIcon({ - ...marker.getIcon(), - url: require("./images/cluster_63px.png"), - }); - } - }); +// //the hover +// window.google.maps.event.addListener(marker, "mouseover", function(){ +// if (item.count <= 300) { +// marker.setIcon({ +// ...marker.getIcon(), +// url: require("./images/cluster_46px_highlight.png"), +// }); +// } else { +// marker.setIcon({ +// ...marker.getIcon(), +// url: require("./images/cluster_63px_highlight.png"), +// }); +// } +// }); +// +// window.google.maps.event.addListener(marker, "mouseout", function(){ +// if (item.count <= 300) { +// marker.setIcon({ +// ...marker.getIcon(), +// url: require("./images/cluster_46px.png"), +// }); +// } else { +// marker.setIcon({ +// ...marker.getIcon(), +// url: require("./images/cluster_63px.png"), +// }); +// } +// }); - marker.triggerClick = () => { - window.google.maps.event.trigger(marker, "click"); - }; markers.push(marker); } else if (item.type == "point") { - var latLng = new window.google.maps.LatLng(item.lat, item.lon); + var latLng = new window.L.latLng(item.lat, item.lon); determineInitialSize(latLng); - var infowindow = new window.google.maps.InfoWindow({ - content: "/img/loading.gif" - }); - - var marker = new window.google.maps.Marker({ - position: latLng, - map: map, - title: "Tree", - icon: { - url: require("./images/pin_29px.png"), - }, - zIndex: undefined, - payload: { - id: item["id"] - } - }); +// var infowindow = new window.google.maps.InfoWindow({ +// content: "/img/loading.gif" +// }); + + var marker = new window.L.marker( + latLng, + { + icon: new window.L.DivIcon({ + className: "greenstand-point", + html: ` +
+
+
+ `, + }), + zIndex: undefined, +// payload: { +// id: item["id"] +// } + }); + marker.payload = { + id: item["id"] + }; + //NOTE close, use tile server to render points. + //marker.addTo(map); if ( selectedTreeMarker && @@ -374,44 +413,44 @@ var initMarkers = function(viewportBounds, zoomLevel) { changeTreeMarkSelected(); } - window.google.maps.event.addListener(marker, "mouseover", function(){ - const icon = marker.getIcon(); - selectedTreeMarker && expect(selectedTreeMarker) - .defined() - .property("payload") - .property("id") - .number(); - expect(marker) - .property("payload") - .property("id") - .number(); - marker.setIcon({ - ...icon, - url: selectedTreeMarker && (selectedTreeMarker.payload.id === marker.payload.id)? - require("./images/pin_32px_highlight.png") - : - require("./images/pin_29px_highlight.png"), - }); - }); - window.google.maps.event.addListener(marker, "mouseout", function(){ - const icon = marker.getIcon(); - selectedTreeMarker && expect(selectedTreeMarker) - .defined() - .property("payload") - .property("id") - .number(); - expect(marker) - .property("payload") - .property("id") - .number(); - marker.setIcon({ - ...icon, - url: selectedTreeMarker && (selectedTreeMarker.payload.id === marker.payload.id)? - require("./images/pin_32px.png") - : - require("./images/pin_29px.png"), - }); - }); +// window.google.maps.event.addListener(marker, "mouseover", function(){ +// const icon = marker.getIcon(); +// selectedTreeMarker && expect(selectedTreeMarker) +// .defined() +// .property("payload") +// .property("id") +// .number(); +// expect(marker) +// .property("payload") +// .property("id") +// .number(); +// marker.setIcon({ +// ...icon, +// url: selectedTreeMarker && (selectedTreeMarker.payload.id === marker.payload.id)? +// require("./images/pin_32px_highlight.png") +// : +// require("./images/pin_29px_highlight.png"), +// }); +// }); +// window.google.maps.event.addListener(marker, "mouseout", function(){ +// const icon = marker.getIcon(); +// selectedTreeMarker && expect(selectedTreeMarker) +// .defined() +// .property("payload") +// .property("id") +// .number(); +// expect(marker) +// .property("payload") +// .property("id") +// .number(); +// marker.setIcon({ +// ...icon, +// url: selectedTreeMarker && (selectedTreeMarker.payload.id === marker.payload.id)? +// require("./images/pin_32px.png") +// : +// require("./images/pin_29px.png"), +// }); +// }); // set the field for sorting item._sort_field = new Date(item.time_created); @@ -427,17 +466,6 @@ var initMarkers = function(viewportBounds, zoomLevel) { setPointMarkerListeners(); if (firstRender) { - // create infowindow object - var infowindow = new window.google.maps.InfoWindow({ - content: "
Click on the cluster to zoom into trees
" - }); - // - if (!checkSession()) { //only if the user is new - // add the infowindow to a random starting marker to be visible by default when the user first loads the screen - // Close it temporarily - //infowindow.open(map, markers[Math.floor(Math.random() * markers.length)]); - } - //loader.classList.remove("active"); getApp().loaded(); firstRender = false; @@ -448,6 +476,7 @@ var initMarkers = function(viewportBounds, zoomLevel) { log.log("init marker finished, loaded:", markers.length); isLoadingMarkers = false; //debugger; + log.warn("checkArrow"); mapModel.checkArrow(); }).catch(function(thrown){ if(axios.isCancel(thrown)){ @@ -467,12 +496,11 @@ function setPointMarkerListeners() { // return a._sort_field - b._sort_field; // }); - panelLoader = document.getElementById("tree-info-loader"); - points.forEach(function(point, i) { var marker = markerByPointId[point.id]; expect(marker).defined(); - window.google.maps.event.addListener(marker, "click", function() { + marker.on("click", function() { + log.debug("marker click"); // window.google.maps.event.clearListeners(marker, "mouseover"); // window.google.maps.event.clearListeners(marker, "mouseout"); //toggle tree mark @@ -486,15 +514,7 @@ function setPointMarkerListeners() { } getApp().showPanel(point); return; -// panelLoader.classList.add("active"); -// showMarkerInfo(point, marker, i); -// $("#tree-image").on("load", function() { -// panelLoader.classList.remove("active"); -// }); }); - marker.triggerClick4Test = () => { - window.google.maps.event.trigger(marker, "click"); - }; }); } @@ -514,121 +534,19 @@ function showAlert() { } } -// set up and show the marker info -function showMarkerInfo(point, marker, index) { - panelLoader = document.getElementById("tree-info-loader"); - - $("#tree_info_div").show("slide", "swing", 600); - if (treeInfoDivShowing == false) { - treeInfoDivShowing = true; - if ( - typeof window.orientation !== "undefined" || - navigator.userAgent.indexOf("IEMobile") !== -1 - ) { - $("#map-canvas").animate( - { - margin: "0 0 0 20vw" - }, - 700, - function() { - //Animation Complete - } - ); - } else { - $("#map-canvas").animate( - { - margin: "0 0 0 354px" - }, - 700, - function() { - //Animation Complete - } - ); - } - } - - //toggle tree mark - selectedOldTreeMarker = selectedTreeMarker; - selectedTreeMarker = marker; - changeTreeMarkSelected(); - - // always center this one - map.panTo(marker.getPosition()); - - $("#create-data").html( - moment(point["time_created"]).format("MM/DD/YYYY hh:mm A") - ); - if (wallet != null) { - $("#created_on").hide(); - $("#tree_id_holder").hide(); - $("#impact-owner-data").html("@" + wallet); - $("#status-data").html("Token issued"); - $("#token-id-data").html(point["token_uuid"]); - } else { - $("#sponsor").hide(); - $("#token_holder").hide(); - } - $("#updated-data").html(point["time_updated"]); - $("#gps-accuracy-data").html(point["gps_accuracy"]); - $("#latitude-data").html(point["lat"]); - $("#longitude-data").html(point["lon"]); - if (point["missing"]) { - $("#missing-data").html(YES); - } else { - $("#missing-data").html(NO); - } - if (point["dead"]) { - $("#dead-data").html(YES); - } else { - $("#dead-data").html(NO); - } - $("#tree-image").attr("src", point["image_url"]); - $("#tree-id").html(point["id"]); - $("#planter_name").html( - point["first_name"] + " " + point["last_name"].slice(0, 1) - ); - if (point["user_image_url"]) { - $("#planter_image").attr("src", point["user_image_url"]); - } else { - $("#planter_image").attr("src", "/img/LogoOnly_Bright_Green100x100.png"); - } - $("#tree_next").val(getCircularPointIndex(index + 1)); - $("#tree_prev").val(getCircularPointIndex(index - 1)); - - $("#tree_next") - .off("click") - .on("click", function() { - fetchMarkers = false; - var index = parseInt($(this).val(), 10); - panelLoader.classList.add("active"); - showMarkerInfoByIndex(index); - $("#tree-image").on("load", function() { - panelLoader.classList.remove("active"); - }); - }); - - $("#tree_prev") - .off("click") - .on("click", function() { - fetchMarkers = false; - var index = parseInt($(this).val(), 10); - panelLoader.classList.add("active"); - showMarkerInfoByIndex(index); - $("#tree-image").on("load", function() { - panelLoader.classList.remove("active"); - }); - }); -} function changeTreeMarkSelected() { if (selectedOldTreeMarker) { - selectedOldTreeMarker.setIcon(require("./images/pin_29px.png")); - selectedOldTreeMarker.setZIndex(0); +//TODO to highlight icon +// selectedOldTreeMarker.setIcon(require("./images/pin_29px.png")); +// selectedOldTreeMarker.setZIndex(0); + window.L.DomUtil.removeClass(selectedOldTreeMarker._icon, "clicked"); } if (selectedTreeMarker) { - selectedTreeMarker.setIcon(require("./images/pin_32px.png")); - selectedTreeMarker.setZIndex(window.google.maps.Marker.MAX_ZINDEX); +// selectedTreeMarker.setIcon(require("./images/pin_32px.png")); +// selectedTreeMarker.setZIndex(99999); + window.L.DomUtil.addClass(selectedTreeMarker._icon, "clicked"); } } @@ -636,7 +554,6 @@ function changeTreeMarkSelected() { function showMarkerInfoByIndex(index) { var point = points[index]; var marker = markerByPointId[point["id"]]; - showMarkerInfo(point, marker, index); } // handle the index for a circular list @@ -651,12 +568,12 @@ function getCircularPointIndex(index) { // clear the markers from the map and then clear our the array of markers function clearOverlays(overlays) { - //log.log(overlays); - for (var i = 0; i < overlays.length; i++) { - //log.log(i); - overlays[i].setMap(null); - } - overlays.length = 0; + log.debug("clear overlays"); + //remove + overlays.forEach(m => { + map.removeLayer(m); + }); + overlays = []; } // Gets the value of a given querystring in the provided url @@ -702,32 +619,32 @@ function getViewportBounds(offset) { var bounds = map.getBounds(); if (offset) { offset -= 1; - var east = bounds.getNorthEast().lng(); - var west = bounds.getSouthWest().lng(); - var north = bounds.getNorthEast().lat(); - var south = bounds.getSouthWest().lat(); + var east = bounds.getNorthEast().lng; + var west = bounds.getSouthWest().lng; + var north = bounds.getNorthEast().lat; + var south = bounds.getSouthWest().lat; // Get the longitude and latitude differences var longitudeDifference = (east - west) * offset; var latitudeDifference = (north - south) * offset; // Move each point farther outside the rectangle // To west - bounds.extend(new window.google.maps.LatLng(south, west - longitudeDifference)); + bounds.extend(window.L.latLng(south, west - longitudeDifference)); // To east - bounds.extend(new window.google.maps.LatLng(north, east + longitudeDifference)); + bounds.extend(window.L.latLng(north, east + longitudeDifference)); // To south - bounds.extend(new window.google.maps.LatLng(south - latitudeDifference, west)); + bounds.extend(window.L.latLng(south - latitudeDifference, west)); // To north - bounds.extend(new window.google.maps.LatLng(north + latitudeDifference, east)); + bounds.extend(window.L.latLng(north + latitudeDifference, east)); } return bounds; } function toUrlValueLonLat(bounds) { - var east = bounds.getNorthEast().lng(); - var west = bounds.getSouthWest().lng(); - var north = bounds.getNorthEast().lat(); - var south = bounds.getSouthWest().lat(); + var east = bounds.getNorthEast().lng; + var west = bounds.getSouthWest().lng; + var north = bounds.getNorthEast().lat; + var south = bounds.getSouthWest().lat; return [east, north, west, south].join(); } @@ -819,8 +736,13 @@ function fitMapToBoundsForSet(data){ window.innerWidth, window.innerHeight, ); - map.panTo(bounds.center); - map.setZoom(bounds.zoomLevel); + const {lat, lng} = bounds.center; + expect(lat).a(expect.any(Number)); + expect(lng).a(expect.any(Number)); + const latLng = window.L.latLng(lat, lng); +// map.panTo(latLng); +// map.setZoom(bounds.zoomLevel); + map.flyTo(latLng, bounds.zoomLevel); } @@ -848,103 +770,228 @@ var initialize = function() { initialZoom = linkZoom; } -//Fri Jul 17 14:26:03 CST 2020 do not set initial zoom when there is some parameters -// if ( -// token != null || -// organization != null || -// treeid != null || -// userid !== null || -// donor != null -// ) { -// initialZoom = 10; -// minZoom = null; // use the minimum zoom from the current map type -// } - -class freetownOverlay { - constructor(tileSize) { - this.tileSize = tileSize; - } - getTile(coord, zoom, ownerDocument) { - const div = ownerDocument.createElement("div"); - const y = (Math.pow(2, zoom) - coord.y - 1) - div.style.backgroundPosition = 'center center'; - div.style.backgroundRepeat = 'no-repeat'; - div.style.height = this.tileSize.height + 'px'; - div.style.width = this.tileSize.width + 'px'; - div.tileId = 'x_' + coord.x + '_y_' + coord.y + '_zoom_' + zoom; - div.style.backgroundImage = 'url(' + "https://treetracker-map-tiles.nyc3.digitaloceanspaces.com/freetown/" + zoom + "/" + coord.x + "/" + y + ".png" + ')'; - //check if coord is in tile range - if (zoom == 10 && coord.x == 474 && y < 537 && y > 534) { - return div; - } else if (zoom == 11 && coord.x > 947 && coord.x < 950 && y > 1070 && y < 1073) { - return div; - } else if (zoom == 12 && coord.x > 1895 && coord.x < 1899 && y > 2142 && y < 2146) { - return div; - } else if (zoom == 13 && coord.x > 3792 && coord.x < 3798 && y > 4286 && y < 4291) { - return div; - } else if (zoom == 14 && coord.x > 7585 && coord.x < 7595 && y > 8574 && y < 8581) { - return div; - } else if (zoom == 15 && coord.x > 15172 && coord.x < 15190 && y > 17149 && y < 17161) { - return div; - } else if (zoom == 16 && coord.x > 30345 && coord.x < 30379 && y > 34300 && y < 34322) { - return div; - } else if (zoom == 17 && coord.x > 60692 && coord.x < 60758 && y > 68602 && y < 68643) { - return div; - } else if (zoom == 18 && coord.x > 121385 && coord.x < 121516 && y > 137206 && y < 137286) { - return div; - } - } - releaseTile(tile) {} -} + //Fri Jul 17 14:26:03 CST 2020 do not set initial zoom when there is some parameters + // if ( + // token != null || + // organization != null || + // treeid != null || + // userid !== null || + // donor != null + // ) { + // initialZoom = 10; + // minZoom = null; // use the minimum zoom from the current map type + // } + + //class freetownOverlay { + // constructor(tileSize) { + // this.tileSize = tileSize; + // } + // getTile(coord, zoom, ownerDocument) { + // const div = ownerDocument.createElement("div"); + // const y = (Math.pow(2, zoom) - coord.y - 1) + // div.style.backgroundPosition = 'center center'; + // div.style.backgroundRepeat = 'no-repeat'; + // div.style.height = this.tileSize.height + 'px'; + // div.style.width = this.tileSize.width + 'px'; + // div.tileId = 'x_' + coord.x + '_y_' + coord.y + '_zoom_' + zoom; + // div.style.backgroundImage = 'url(' + "https://treetracker-map-tiles.nyc3.cdn.digitaloceanspaces.com/freetown/" + zoom + "/" + coord.x + "/" + y + ".png" + ')'; + // //check if coord is in tile range + // if (zoom == 10 && coord.x == 474 && y < 537 && y > 534) { + // return div; + // } else if (zoom == 11 && coord.x > 947 && coord.x < 950 && y > 1070 && y < 1073) { + // return div; + // } else if (zoom == 12 && coord.x > 1895 && coord.x < 1899 && y > 2142 && y < 2146) { + // return div; + // } else if (zoom == 13 && coord.x > 3792 && coord.x < 3798 && y > 4286 && y < 4291) { + // return div; + // } else if (zoom == 14 && coord.x > 7585 && coord.x < 7595 && y > 8574 && y < 8581) { + // return div; + // } else if (zoom == 15 && coord.x > 15172 && coord.x < 15190 && y > 17149 && y < 17161) { + // return div; + // } else if (zoom == 16 && coord.x > 30345 && coord.x < 30379 && y > 34300 && y < 34322) { + // return div; + // } else if (zoom == 17 && coord.x > 60692 && coord.x < 60758 && y > 68602 && y < 68643) { + // return div; + // } else if (zoom == 18 && coord.x > 121385 && coord.x < 121516 && y > 137206 && y < 137286) { + // return div; + // } + // } + // releaseTile(tile) {} + //} var mapOptions = { zoom: initialZoom, - center: { lat: 20, lng: 0 }, + center: window.L.latLng( 20, 0 ), minZoom: minZoom, - mapTypeId: "hybrid", - mapTypeControl: false, - streetViewControl: false, - fullscreenControl: false, -// backgroundColor: theme.palette.primary.main, - backgroundColor: theme.palette.grey.A200, + // mapTypeId: "hybrid", + // mapTypeControl: false, + // streetViewControl: false, + // fullscreenControl: false, + // backgroundColor: theme.palette.grey.A200, + zoomControl: false, }; - if(mapName != null && !!mapConfig[mapName]) { + if(mapName != null && !!mapConfig[mapName]) { mapOptions.zoom = mapConfig[mapName].zoom; mapOptions.center = mapConfig[mapName].center; } - map = new window.google.maps.Map(document.getElementById("map-canvas"), mapOptions); -// insert freetown overlay - map.overlayMapTypes.insertAt( - 0, - new freetownOverlay(new window.google.maps.Size(256, 256)) - ); - map.data.loadGeoJson( - "https://treetracker-map-features.fra1.digitaloceanspaces.com/freetown_catchments.geojson" - ); - map.data.setStyle({ - strokeWeight: 1, - strokeOpacity: 1, - strokeColor: 'green' - }); + map = window.L.map('map-canvas', mapOptions); + + //control + window.L.control.zoom({ + position: 'bottomright' + }).addTo(map); + + //google satillite map + const googleSat = window.L.tileLayer( + 'http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}',{ + maxZoom: 20, +// attribution: 'Map data © OpenStreetMap contributors, ' + +// 'Imagery © Mapbox', + subdomains:['mt0','mt1','mt2','mt3'] + }); + googleSat.addTo(map); + + //if isn't cases like wallet, org, then use tile + if(!token && !mapName && !treeid && !userid && !wallet){ + log.info("use tile server"); + var baseURL_def = process.env.REACT_APP_TILE_SERVER_URL; + if(!baseURL_def){ + throw new Error("Tile server url isn't set"); + } + new window.L.tileLayer( + baseURL_def + '{z}/{x}/{y}.png', + { + minZoom: 16, + maxZoom: 20, + } + ).addTo(map); + var utfGridLayer = new window.L.utfGrid( + baseURL_def + '{z}/{x}/{y}.grid.json', + { + minZoom: 15, + maxZoom: 20, + } + ); + + utfGridLayer.on('click', function (e) { + console.log("e:", e); + if (e.data) { + console.log('click', e.data); + // map.panTo(e.latlng); + // map.setView(e.latlng, map.getZoom() + 2); + // points.forEach(function(point, i) { + // var marker = markerByPointId[point.id]; + // expect(marker).defined(); + // marker.on("click", function() { + // log.debug("marker click"); + // // window.google.maps.event.clearListeners(marker, "mouseover"); + // // window.google.maps.event.clearListeners(marker, "mouseout"); + // //toggle tree mark + // selectedOldTreeMarker = selectedTreeMarker; + // selectedTreeMarker = marker; + // changeTreeMarkSelected(); + // + // //attache wallet + // if(wallet != null){ + // point.attachedWallet = wallet; + // } + // getApp().showPanel(point); + // return; + // }); + // }); + //expect(e.data).property("id").a("number"); + const point = points.reduce((a,c) => { + //expect(c).property("id").a("number"); + if(c.id === e.data.id){ + return c; + }else{ + return a; + } + }, undefined); + expect(point).defined(); + selectedTreeMarker = { + payload: e.data, + } + getApp().showPanel(point); + } else { + console.log('click nothing'); + } + }); + console.warn("utf:", utfGridLayer); + utfGridLayer.on('mouseover', function (e) { + console.log("e:", e); + expect(e.data).match({ + lat: expect.any(Number), + lon: expect.any(Number), + }); + markerHighlight = new window.L.marker( + [e.data.lat, e.data.lon], + { + icon: new window.L.DivIcon({ + className: "greenstand-point-highlight", + html: ` +
+
+
+ `, + iconSize: [32, 32], + }), + } + ); + markerHighlight.payload = { + id: e.data.id + }; + markerHighlight.addTo(map); + }); + utfGridLayer.on('mouseout', function (e) { + console.log("e:", e); + expect(e.data).match({ + lat: expect.any(Number), + lon: expect.any(Number), + }); + map.removeLayer(markerHighlight); + }); + utfGridLayer.addTo(map); + }else{ + log.info("do not use tile server"); + } + // insert freetown overlay + // map.overlayMapTypes.insertAt( + // 0, + // new freetownOverlay(new window.google.maps.Size(256, 256)) + // ); + +//TODO need to restore this in the future +// map.data.loadGeoJson( +// "https://treetracker-map-features.fra1.digitaloceanspaces.com/freetown_catchments.geojson" +// ); +// map.data.setStyle({ +// strokeWeight: 1, +// strokeOpacity: 1, +// strokeColor: 'green' +// }); // only fetch when the user has made some sort of action - window.google.maps.event.addListener(map, "dragstart", function() { - fetchMarkers = true; - firstInteraction = true; - }); + //TODO closed + // window.google.maps.event.addListener(map, "dragstart", function() { + // fetchMarkers = true; + // firstInteraction = true; + // }); function registerFirstInteraction() { + log.trace("registerFirstInteraction"); firstInteraction = true; } - window.google.maps.event.addListener(map, "click", registerFirstInteraction); + map.on("click", registerFirstInteraction); - window.google.maps.event.addListener(map, "mousemove", registerFirstInteraction); + map.on("mousemove", registerFirstInteraction); - window.google.maps.event.addListener(map, "zoom_changed", function() { + map.on("zoomend", function() { + log.debug("zoomend"); fetchMarkers = true; }); @@ -958,25 +1005,25 @@ class freetownOverlay { }); */ -//Fri Jul 17 14:26:56 CST 2020 do not use titlesloaded to set initial bounds -//use the firstRender in initMarkers fn to load initial bounds -// // Adjust map bounds after it’s fully loaded, but only before first interaction -// window.google.maps.event.addListener(map, "tilesloaded", function() { -// if ( -// !firstInteraction && -// (token != null || -// organization != null || -// treeid != null || -// userid !== null || -// donor != null) -// ) { -// log.log("before first interaction, fit the map", initialBounds.toJSON()); -// map.fitBounds(initialBounds); -// } -// }); - - - window.google.maps.event.addListener(map, "idle", function() { + //Fri Jul 17 14:26:56 CST 2020 do not use titlesloaded to set initial bounds + //use the firstRender in initMarkers fn to load initial bounds + // // Adjust map bounds after it’s fully loaded, but only before first interaction + // window.google.maps.event.addListener(map, "tilesloaded", function() { + // if ( + // !firstInteraction && + // (token != null || + // organization != null || + // treeid != null || + // userid !== null || + // donor != null) + // ) { + // log.log("before first interaction, fit the map", initialBounds.toJSON()); + // map.fitBounds(initialBounds); + // } + // }); + + + map.on("moveend load", function() { log.log('IDLE'); if(firstQuery){ firstQuery = false @@ -998,10 +1045,10 @@ class freetownOverlay { var clusterRadius = getQueryStringValue("clusterRadius") || getClusterRadius(queryZoomLevel); log.log("Cluster radius: " + clusterRadius); -// if (req != null) { -// log.log("initMarkers abort"); -// req.abort(); -// } + // if (req != null) { + // log.log("initMarkers abort"); + // req.abort(); + // } source && source.cancel("clean previous request"); var queryUrl = treetrackerApiUrl + "trees?clusterRadius=" + clusterRadius; queryUrl = queryUrl + "&zoom_level=" + queryZoomLevel; @@ -1020,13 +1067,13 @@ class freetownOverlay { const data = response.data.data; const app = getApp() if (userid && data.length === 0) { -// showAlert(); + // showAlert(); app.loaded(); app.showMessage(`Could not find any trees associated with userid ${userid}`); return; } if (data.length === 0) { -// showAlert(); + // showAlert(); app.loaded(); app.showMessage(`Could not find any data `); return; @@ -1075,15 +1122,16 @@ class freetownOverlay { currentZoom = zoomLevel; initMarkers(toUrlValueLonLat(getViewportBounds(1.1)), zoomLevel); } + mapModel.checkArrow(); }); currentZoom = initialZoom; -// $("#close-button").click(function() { -// $("#tree_info_div").hide("slide", "swing", 600); -// treeInfoDivShowing = false; -// $("#map-canvas").css("margin-left", "0px"); -// }); + // $("#close-button").click(function() { + // $("#tree_info_div").hide("slide", "swing", 600); + // treeInfoDivShowing = false; + // $("#map-canvas").css("margin-left", "0px"); + // }); //initialize MapModel log.log("MAKING MAP MODEL"); @@ -1094,9 +1142,13 @@ class freetownOverlay { }); mapModel.map = map; mapModel.markers = markers; + + //not sure should use it in this way + map.setView(mapOptions.center, mapOptions.zoom); }; -window.google.maps.event.addDomListener(window, "load", initialize); +//window.google.maps.event.addDomListener(window, "load", initialize); +initialize(); function getNextPoint(point) { expect(point).property("id").number(); @@ -1136,18 +1188,20 @@ function getPrevPoint(point){ } function addMarker(LatLng, tree){ - var marker = new window.google.maps.Marker({ - position: LatLng, - map: map, - title: "Tree", - icon: { - url: require("./images/pin_29px.png"), - }, - zIndex: undefined, - payload: { - id: tree.id, - } - }); + var marker = new window.L.marker( + LatLng, + { + map: map, + title: "Tree", +// icon: { +// url: require("./images/pin_29px.png"), +// }, + zIndex: undefined, + payload: { + id: tree.id, + } + }); + marker.addTo(map); markers.push(marker); expect(tree).property("id").number(); markerByPointId[tree.id] = marker; @@ -1180,13 +1234,14 @@ function getCurrentIndex(){ } function goNextPoint(){ + log.debug("go to next"); const index = getCurrentIndex(); const nextIndex = (index + 1) % points.length; expect(nextIndex).within(0, points.length); const nextPoint = points[nextIndex]; const marker = markerByPointId[nextPoint.id]; expect(marker).defined(); - marker.triggerClick4Test(); + marker.fire("click"); } function goPrevPoint(){ @@ -1199,7 +1254,7 @@ function goPrevPoint(){ const prevPoint = points[prevIndex]; const marker = markerByPointId[prevPoint.id]; expect(marker).defined(); - marker.triggerClick4Test(); + marker.fire("click"); } function hasNextPoint(){ diff --git a/src/mapTools.js b/src/mapTools.js index 81fbe9791..6a09d380a 100644 --- a/src/mapTools.js +++ b/src/mapTools.js @@ -3,6 +3,7 @@ */ import expect from "expect-runtime"; import log from "loglevel"; +import "leaflet"; function go(direction, location, degree){ expect(direction).oneOf(["east", "west", "north", "south"]); @@ -113,29 +114,29 @@ function getInitialBounds (locations, width, height){ locations.push(cornerEastSouth); } - const bounds = new window.google.maps.LatLngBounds(); + const bounds = new window.L.latLngBounds(); for(let location of locations){ bounds.extend(location); } log.log("bounds:", bounds); const center = { - lat: bounds.getCenter().lat(), - lng: bounds.getCenter().lng(), + lat: bounds.getCenter().lat, + lng: bounds.getCenter().lng, } //cal zoom let zoom; var GLOBE_WIDTH = 256; // a constant in Google's map projection { - const west = bounds.getSouthWest().lng(); - const east = bounds.getNorthEast().lng(); + const west = bounds.getSouthWest().lng; + const east = bounds.getNorthEast().lng; const angle = getAngleLng(east, west); zoom = Math.round(Math.log(width * 360 / angle / GLOBE_WIDTH) / Math.LN2); log.log("zoom1:", zoom); } let zoom2; { - const south = bounds.getSouthWest().lat(); - const north = bounds.getNorthEast().lat(); + const south = bounds.getSouthWest().lat; + const north = bounds.getNorthEast().lat; const angle = getAngleLat(north, south); log.log("angle:", angle); zoom2 = Math.round(Math.log(height * 360 / angle / GLOBE_WIDTH) / Math.LN2); @@ -156,14 +157,14 @@ const TILE_SIZE = 256; // The mapping between latitude, longitude and pixels is defined by the web // mercator projection. function project(latLng: google.maps.LatLng) { - let siny = Math.sin((latLng.lat() * Math.PI) / 180); + let siny = Math.sin((latLng.lat * Math.PI) / 180); // Truncating to 0.9999 effectively limits latitude to 89.189. This is // about a third of a tile past the edge of the world tile. siny = Math.min(Math.max(siny, -0.9999), 0.9999); - return new google.maps.Point( - TILE_SIZE * (0.5 + latLng.lng() / 360), + return window.L.point( + TILE_SIZE * (0.5 + latLng.lng / 360), TILE_SIZE * (0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI)) ); } @@ -172,12 +173,12 @@ function getLatLngCoordinateByPixel(top, left, map){ expect(top).number(); expect(left).number(); expect(map).defined(); - const northWest = new window.google.maps.LatLng( - map.getBounds().getNorthEast().lat(), - map.getBounds().getSouthWest().lng()); + const northWest = window.L.latLng( + map.getBounds().getNorthEast().lat, + map.getBounds().getSouthWest().lng); const northWestPixel = map.getProjection().fromLatLngToPoint(northWest); const pixelSize = Math.pow(2, -map.getZoom()); - const result = new window.google.maps.Point( + const result = window.L.point( northWestPixel.x + left*pixelSize, northWestPixel.y + top*pixelSize ); @@ -190,11 +191,11 @@ function getPixelCoordinateByLatLng(lat, lng, map){ expect(lat).number(); expect(lng).number(); expect(map).defined(); - const northWest = new window.google.maps.LatLng( - map.getBounds().getNorthEast().lat(), - map.getBounds().getSouthWest().lng()); + const northWest = window.L.latLng( + map.getBounds().getNorthEast().lat, + map.getBounds().getSouthWest().lng); const northWestPixel = map.getProjection().fromLatLngToPoint(northWest); - const target = new window.google.maps.LatLng( + const target = window.L.latLng( lat, lng ) diff --git a/src/mapTools.test.js b/src/mapTools.test.js index 53ae85164..f5e86f33e 100644 --- a/src/mapTools.test.js +++ b/src/mapTools.test.js @@ -82,25 +82,6 @@ describe("getInitialBounds", () => { it("getInitialBounds(0,0)", () => { - global.google = { - maps: { - LatLngBounds: jest.fn().mockImplementation(() => ({ - extend: jest.fn(), - getCenter: () => ({ - lat: () => 0, - lng: () => 0, - }), - getSouthWest: () => ({ - lat: () => 0, - lng: () => 0, - }), - getNorthEast: () => ({ - lat: () => 0, - lng: () => 0, - }), - })), - }, - }; const result = mapTools.getInitialBounds([{lat:0, lng:0}], 500, 500); expect(result).toMatchObject({ center: { diff --git a/src/style.css b/src/style.css index 7a71adaa9..27183efd3 100644 --- a/src/style.css +++ b/src/style.css @@ -138,3 +138,98 @@ body { animation-iteration-count:infinite; animation-timing-function:linear; } + +.greenstand-cluster:hover { + z-index: 999 !important; +} + +.greenstand-cluster.clicked { + z-index: 999 !important; +} + +.greenstand-cluster-box-small { + background: url(./images/cluster_46px.png); + width: 46px; + height: 46px; + display: flex; + justify-content: center; + align-items: center; + transform: translate(-50%, -50%); + font-family: Roboto, Arial, sans-serif; + font-size: 14px; +} + +.greenstand-cluster-box-small:hover { + background: url(./images/cluster_46px_highlight.png); + z-index: 9; +} + +.greenstand-cluster.clicked .greenstand-cluster-box-small{ + background: url(./images/cluster_46px_clicked.png); +} + +.greenstand-cluster-box-large { + background: url(./images/cluster_63px.png); + width: 63px; + height: 63px; + display: flex; + justify-content: center; + align-items: center; + transform: translate(-50%, -50%); + font-family: Roboto, Arial, sans-serif; + font-size: 14px; +} + +.greenstand-cluster-box-large:hover { + background: url(./images/cluster_63px_highlight.png); + z-index: 9; +} + +.greenstand-cluster.clicked .greenstand-cluster-box-large { + background: url(./images/cluster_63px_clicked.png); +} + + +.greenstand-point:hover { + z-index: 999 !important; +} + +.greenstand-point.clicked { + z-index: 999 !important; +} + +.greenstand-point-box { + background: url(./images/pin_29px.png); + width: 29px; + height: 32px; + display: flex; + justify-content: center; + align-items: center; + transform: translate(-50%, -50%); + font-family: Roboto, Arial, sans-serif; + font-size: 14px; +} + +.greenstand-point-box:hover { + background: url(./images/pin_29px_highlight.png); +} + +.greenstand-point.clicked .greenstand-point-box { + background: url(./images/pin_32px.png); +} + +.greenstand-point-highlight{ + z-index: 999 !important; +} + +.greenstand-point-highlight-box { + background: url(./images/pin_29px_highlight.png); + width: 29px; + height: 32px; + display: flex; + justify-content: center; + align-items: center; + /*transform: translate(-50%, -50%);*/ + font-family: Roboto, Arial, sans-serif; + font-size: 14px; +}