GeoGuessr Custom Maps

using modified maps in geoguessr games

当前为 2024-09-08 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name GeoGuessr Custom Maps
  3. // @namespace https://gf.qytechs.cn/users/1179204
  4. // @description using modified maps in geoguessr games
  5. // @version 1.0.7
  6. // @author KaKa
  7. // @license BSD
  8. // @match *://www.geoguessr.com/*
  9. // @require https://update.gf.qytechs.cn/scripts/502813/1423193/Geoguessr%20Tag.js
  10. // @icon https://www.svgrepo.com/show/392367/interaction-interface-layer-layers-location-map.svg
  11.  
  12. // ==/UserScript==
  13.  
  14. (function() {
  15.  
  16. /*=========================================================================Modifiy your guess map here==================================================================================*/
  17.  
  18. let customOptions={
  19.  
  20. Language:'en', //en,zh,ja,fr,de,es
  21.  
  22. Google_StreetView_Layer_Lines_Style:'Orange', // More styles see below
  23.  
  24. Google_StreetView_Layer_Shortcut:'V',
  25.  
  26. Google_Labels_Layer_Shortcut:'G',
  27.  
  28. Google_Terrain_Layer_Shortcut:'T',
  29.  
  30. Google_Satellite_Layer_Shortcut:'B',
  31.  
  32. Apple_StreetView_Layer_Shortcut:'P',
  33.  
  34. Yandex_StreetView_Layer_Shortcut:'Y',
  35.  
  36. OpenWeather_Shortcut:'Q',
  37.  
  38. OpenWeather_Style:'radar', //'radar': Global Precipitation; 'CL':Cloud; 'APM':Pressure; 'TA2'Temperature; 'WS10':Wind Speed;
  39.  
  40. OpenWeather_Date:'now', // foramt:yyyy-mm-dd, less than one week ago
  41.  
  42. Bing_Maps_Style:'r', // 'a':satellite(without labels); 'h':hybrid; 'r':roadmap,'sre':terrain
  43.  
  44. Map_Tiler_Style:'basic', //basic,satellite,bright,landscape,ocean,outdoor,topo,streets,dataviz
  45.  
  46. Carto_Style:'light_all', //light_all,dark_all
  47.  
  48. Thunderforest_Style:'spinal-map'} //spinal-map,landscape,outdoors,atlas,transport,
  49.  
  50. let tileServices=["Google_Maps","OpenStreetMap","Bing_Maps","Map_Tiler","Thunderforest","Yandex_Maps","Carto","Petal_Maps"]
  51.  
  52. let colorOptions={
  53.  
  54. Default:['1098ad','99e9f2'],
  55.  
  56. Crimson:['f03e3e','ffc9c9'],
  57.  
  58. Deep_Pink:['d6336c','fcc2d7'],
  59.  
  60. Blue_Violet:['ae3ec9','eebefa'],
  61.  
  62. Slate_Blue:['7048e8','d0bfff'],
  63.  
  64. Royal_Blue:['4263eb','bac8ff'],
  65.  
  66. Dodger_Blue: ['1c7ed6','a5d8ff'],
  67.  
  68. Sea_Green:['0ca678','96f2d7'],
  69.  
  70. Lime_Green:['37b24d','b2f2bb'],
  71.  
  72. OliveDrab:['74b816','d8f5a2'],
  73.  
  74. Orange:['f59f00','ffec99'],
  75.  
  76. Dark_Orange:['f76707','ffd8a8'],
  77.  
  78. Brown:['bd5f1b','f7ca9e'],
  79. }
  80.  
  81. /*======================================================================================================================================================================================*/
  82.  
  83.  
  84. let currentMapType='roadmap',currentLayers=[],isGoogleDisplay=true,isSV=false,opacityControl
  85.  
  86. const openWeatherBaseURL = "https://g.sat.owm.io/vane/2.0/weather";
  87. const radarURL = `https://b.sat.owm.io/maps/2.0/radar/{z}/{x}/{y}?appid=9de243494c0b295cca9337e1e96b00e2&day=${getNow(customOptions.OpenWeather_Date)}`;
  88.  
  89. const openWeatherURL = (customOptions.OpenWeather_Style === 'radar')
  90. ? radarURL
  91. : `${openWeatherBaseURL}/${customOptions.OpenWeather_Style}/{z}/{x}/{y}?appid=9de243494c0b295cca9337e1e96b00e2&&date=${getTimestamp(customOptions.OpenWeather_Date)}&fill_bound=true`;
  92.  
  93. let tileUrls = {
  94. Petal_Maps: `https://maprastertile-dra.dbankcdn.com/display-service/v1/online-render/getTile/24.07.06.10/{z}/{x}/{y}/?language=${customOptions.Language}&p=46&scale=1&mapType=ROADMAP&presetStyleId=standard&key=CgB6e3x91JxUZ4Ow3JZYVG6r9c9U7rH4ameNQdauHVaVBYGWwy8ueadAtqjs6Yl2z3OwymAEx3JR83vpgPzv4nuC`,
  95. OpenStreetMap: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
  96. Map_Tiler:`https://api.maptiler.com/maps/${customOptions.Map_Tiler_Style}-v2/256/{z}/{x}/{y}.png?key=0epLOAjD7fw17tghcyee`,
  97. Thunderforest:`https://b.tile.thunderforest.com/${customOptions.Thunderforest_Style}/{z}/{x}/{y}@2x.png?apikey=6a53e8b25d114a5e9216df5bf9b5e9c8`,
  98. Carto:`https://cartodb-basemaps-3.global.ssl.fastly.net/${customOptions.Carto_Style}/{z}/{x}/{y}.png`,
  99. Google_StreetView:`https://maps.googleapis.com/maps/vt?pb=%211m5%211m4%211i{z}%212i{x}%213i{y}%214i256%212m8%211e2%212ssvv%214m2%211scc%212s*211m3*211e2*212b1*213e2*212b1*214b1%214m2%211ssvl%212s*212b1%213m17%212sen%213sUS%215e18%2112m4%211e68%212m2%211sset%212sRoadmap%2112m3%211e37%212m1%211ssmartmaps%2112m4%211e26%212m2%211sstyles%212ss.e%3Ag.f%7Cp.c%3A%23${colorOptions[customOptions.Google_StreetView_Layer_Lines_Style][0]}%7Cp.w%3A1%2Cs.e%3Ag.s%7Cp.c%3A%23${colorOptions[customOptions.Google_StreetView_Layer_Lines_Style][1]}%7Cp.w%3A3%215m1%215f1.35`,
  100. Google_Labels:`https://maps.googleapis.com/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m1!2sm!3m17!2s${customOptions.Language}!3sUS!5e18!12m4!1e68!2m2!1sset!2sRoadmap!12m3!1e37!2m1!1ssmartmaps!12m4!1e26!2m2!1sstyles!2ss.e:g|p.v:off,s.t:1|s.e:g.s|p.v:off,s.e:l|p.v:on!5m1!5f2`,
  101. Apple_StreetView:`https://lookmap.eu.pythonanywhere.com/bluelines_raster_2x/{z}/{x}/{y}.png`,
  102. Yandex_StreetView:`https://core-stv-renderer.maps.yandex.net/2.x/tiles?l=stv&x={x}&y={y}&z={z}&scale=1&v=2024.09.06.19.22-1_24.09.08-0-21241`,
  103. Yandex_Maps:`https://core-renderer-tiles.maps.yandex.net/tiles?l=map&v=24.09.06-3-b240906182700&x={x}&y={y}&z={z}&scale=1`,
  104. OpenWeather: openWeatherURL,
  105. }
  106.  
  107. let map,google,gsvLayer,initLayer=tag
  108. const intervalId = setInterval(() => {
  109. getMap();
  110. if (map) {
  111. clearInterval(intervalId)
  112. initCustomizer()}
  113. }, 500);
  114.  
  115.  
  116. function createOpacityControl(controlDiv, layer) {
  117. controlDiv.style.margin='20px'
  118. controlDiv.style.backgroundColor = '#fff';
  119. controlDiv.style.height = '30px';
  120. controlDiv.style.boxShadow = 'rgba(0, 0, 0, 0.3) 0px 1px 4px -1px';
  121. controlDiv.style.borderRadius = '5px';
  122.  
  123. var opacitySlider = document.createElement('input');
  124.  
  125. opacitySlider.setAttribute('type', 'range');
  126. opacitySlider.setAttribute('id', 'timeRange');
  127. opacitySlider.setAttribute('min', '0');
  128. opacitySlider.setAttribute('max', '100');
  129. opacitySlider.setAttribute('value', '100');
  130. opacitySlider.setAttribute('step', '1');
  131. opacitySlider.style.width = '80px';
  132. opacitySlider.style.height='20px'
  133. opacitySlider.style.marginTop='5px'
  134. opacitySlider.addEventListener('input', function() {
  135. var opacity = opacitySlider.value / 100
  136. layer.setOpacity(opacity);
  137.  
  138. });
  139.  
  140. controlDiv.appendChild(opacitySlider);
  141. }
  142.  
  143. function addOpacityControl(m, layer) {
  144. var opacityControlDiv = document.createElement('div');
  145. new createOpacityControl(opacityControlDiv, layer);
  146. opacityControl =true
  147. opacityControlDiv.index = 1;
  148. m.controls[google.maps.ControlPosition.TOP_RIGHT].push(opacityControlDiv);
  149. }
  150.  
  151. function removeOpacityControl(){
  152. if(opacityControl){
  153. map.controls[google.maps.ControlPosition.TOP_RIGHT].removeAt(map.controls[google.maps.ControlPosition.TOP_RIGHT].getLength() - 1)
  154. opacityControl=false
  155. }
  156. }
  157.  
  158. function getNow(date) {
  159. if(date!='now'){
  160. return date
  161. }
  162. const now = new Date();
  163. now.setHours(now.getHours() - 1);
  164. return now.toISOString().slice(0, 14)+'00';
  165. }
  166.  
  167. function getTimestamp(date){
  168. var parsedDate
  169. if (date=== 'now') {
  170. parsedDate= new Date()
  171. return Math.floor(parsedDate.getTime() / 1000)
  172. }
  173. parsedDate = new Date(date);
  174.  
  175. if (isNaN(parsedDate.getTime())) {
  176. throw new Error('Invalid date format');
  177. }
  178. return Math.floor(parsedDate.getTime() / 1000);
  179.  
  180. }
  181.  
  182. function extractTileCoordinates(url) {
  183. const regex = /!1i(\d+)!2i(\d+)!3i(\d+)!4i(\d+)/;
  184. const matches = url.match(regex);
  185.  
  186. if (matches && matches.length === 5) {
  187. const z = matches[1];
  188. const x = matches[2];
  189. const y = matches[3];
  190. return { z, x, y };
  191. } else {
  192. return null;
  193. }
  194. }
  195. function getBingTiles(tileX, tileY, zoom,type) {
  196. var quadKey = tileXYToQuadKey(tileX, tileY, zoom);
  197. var baseUrl = 'https://ecn.t0.tiles.virtualearth.net/tiles/';
  198.  
  199. return baseUrl + type + quadKey + '.jpeg?g=14519';
  200. }
  201. function tileXYToQuadKey(tileX, tileY, zoom) {
  202. var quadKey = '';
  203. for (var i = zoom; i > 0; i--) {
  204. var digit = 0;
  205. var mask = 1 << (i - 1);
  206. if ((tileX & mask) !== 0) {
  207. digit += 1;
  208. }
  209. if ((tileY & mask) !== 0) {
  210. digit += 2;
  211. }
  212. quadKey += digit.toString();
  213. }
  214. return quadKey;
  215. }
  216.  
  217.  
  218. function setMapLayer(layerName) {
  219. var tileLayerUrl = tileUrls[layerName];
  220. var tileLayer
  221. if (layerName==='Bing_Maps') {
  222. tileLayer = new google.maps.ImageMapType({
  223. getTileUrl: function(coord, zoom) {
  224. return getBingTiles(coord.x,coord.y,zoom,customOptions.Bing_Maps_Style)
  225. .replace('{z}', zoom)
  226. .replace('{x}', coord.x)
  227. .replace('{y}', coord.y);
  228. },
  229. tileSize: new google.maps.Size(256, 256),
  230. name: layerName,
  231.  
  232. });
  233. }
  234. else if (tileServices.includes(layerName)){
  235. tileLayer = new google.maps.ImageMapType({
  236. getTileUrl: function(coord, zoom) {
  237. return tileLayerUrl
  238. .replace('{z}', zoom)
  239. .replace('{x}', coord.x)
  240. .replace('{y}', coord.y);
  241. },
  242. tileSize: new google.maps.Size(256, 256),
  243. name: layerName,
  244. maxZoom:20
  245. });
  246. map.mapTypes.set(layerName, tileLayer);
  247. map.setMapTypeId(layerName);
  248. }
  249. else{
  250. tileLayer = new google.maps.ImageMapType({
  251. getTileUrl: function(coord, zoom) {
  252. return tileLayerUrl
  253. .replace('{z}', zoom)
  254. .replace('{x}', coord.x)
  255. .replace('{y}', coord.y);
  256. },
  257. tileSize: new google.maps.Size(256, 256),
  258. name: layerName,
  259.  
  260. });
  261. }
  262.  
  263. if(!layerName.includes('Google')&&layerName!='Apple_StreetView'&&layerName!='Yandex_StreetView'){
  264. isGoogleDisplay=false
  265. }
  266. if(currentLayers.includes(layerName)){
  267. removeMapLayer(layerName)
  268. const index = currentLayers.indexOf(layerName);
  269. if (index !== -1) {
  270. currentLayers.splice(index, 1);
  271. }
  272. if(!layerName.includes('Google')&&!layerName.includes('Weather')&&!layerName.includes('StreetView')){
  273. setMapType('roadmap')
  274. map.overlayMapTypes.clear();
  275. currentLayers=[]
  276. isGoogleDisplay=true
  277. }
  278. }
  279. else {
  280. if (!tileServices.includes(layerName)||layerName==='Bing_Maps')map.overlayMapTypes.push(tileLayer)
  281. currentLayers.push(layerName)};
  282.  
  283. if(layerName.includes('StreetView')){
  284.  
  285. if (!opacityControl){
  286. addOpacityControl(map,tileLayer)}
  287. else if (currentLayers.includes(layerName)){
  288. addOpacityControl(map,tileLayer)
  289. }
  290. else removeOpacityControl()
  291. }
  292. }
  293.  
  294.  
  295. function removeMapLayer(layerName) {
  296. for (let i = 0; i < map.overlayMapTypes.getLength(); i++) {
  297. const currentLayer = map.overlayMapTypes.getAt(i);
  298. if (currentLayer && currentLayer.name === layerName) {
  299. map.overlayMapTypes.removeAt(i);
  300. break;
  301. }
  302. }
  303. }
  304.  
  305. function getMap(){
  306. let element = document.getElementsByClassName("guess-map_canvas__cvpqv")[0]
  307. //if (!element) element=document.getElementsByClassName("coordinate-result-map_map__Yh2Il")[0]
  308. const keys = Object.keys(element)
  309. const key = keys.find(key => key.startsWith("__reactFiber$"))
  310. const props = element[key]
  311. map=props.return.return.memoizedProps.map
  312. google=unsafeWindow.google
  313. }
  314.  
  315. function setMapType(customType){
  316. if (currentMapType!=customType){
  317. currentMapType=customType
  318. }
  319. else{
  320. currentMapType='roadmap'
  321. }
  322. map.setMapTypeId(currentMapType);
  323. }
  324.  
  325.  
  326. function initCustomizer(){
  327. let onKeyDown = (e) => {
  328. if (e.key >= '1' && e.key <= '7') {
  329. initLayer(`layer:${tileServices[tileIndex]}`)
  330. if(!map) getMap()
  331. const tileIndex=parseInt(e.key)
  332. map.overlayMapTypes.clear();
  333. removeOpacityControl()
  334. setMapLayer(tileServices[tileIndex])
  335. const index = currentLayers.indexOf("Google_Labels");
  336. if (index !== -1) {
  337. currentLayers.splice(index, 1);
  338. }
  339. }
  340. else if (e.key === '0') {
  341. e.stopImmediatePropagation();
  342. if(!map) getMap()
  343. initLayer('layer:Google_Labels')
  344. map.overlayMapTypes.clear();
  345. currentLayers=[]
  346. isGoogleDisplay=true
  347. removeOpacityControl()
  348. map.set('styles', [
  349. {
  350. featureType: 'all',
  351. elementType: 'labels',
  352. stylers: [{ visibility: 'on' }]
  353. }
  354. ])
  355. isSV=false
  356. }
  357. else if (e.key === customOptions.Google_StreetView_Layer_Shortcut.toLowerCase()|| e.key === customOptions.Google_StreetView_Layer_Shortcut) {
  358. e.stopImmediatePropagation();
  359. if(!map) getMap()
  360. initLayer('layer:Google_StreetView')
  361. if(!isSV){
  362. map.set('styles', [
  363. {
  364. featureType: 'all',
  365. elementType: 'labels',
  366. stylers: [{ visibility: 'off' }]
  367. }
  368. ])
  369. isSV=true}
  370. else{
  371. map.set('styles', [
  372. {
  373. featureType: 'all',
  374. elementType: 'labels',
  375. stylers: [{ visibility: 'on' }]
  376. }
  377. ])
  378. isSV=false
  379. }
  380. setMapLayer('Google_StreetView')
  381. if (isGoogleDisplay)setMapLayer('Google_Labels')
  382. }
  383. else if (e.key === customOptions.Apple_StreetView_Layer_Shortcut.toLowerCase()|| e.key === customOptions.Apple_StreetView_Layer_Shortcut) {
  384. e.stopImmediatePropagation();
  385. initLayer('layer:Apple_StreetView')
  386. if(!map) getMap()
  387. if(!isSV){
  388. map.set('styles', [
  389. {
  390. featureType: 'all',
  391. elementType: 'labels',
  392. stylers: [{ visibility: 'off' }]
  393. }
  394. ])
  395. isSV=true}
  396. else{
  397. map.set('styles', [
  398. {
  399. featureType: 'all',
  400. elementType: 'labels',
  401. stylers: [{ visibility: 'on' }]
  402. }
  403. ])
  404. isSV=false
  405. }
  406. setMapLayer('Apple_StreetView')
  407. if (isGoogleDisplay)setMapLayer('Google_Labels')
  408. }
  409.  
  410. else if (e.key === customOptions.Yandex_StreetView_Layer_Shortcut.toLowerCase()|| e.key === customOptions.Yandex_StreetView_Layer_Shortcut) {
  411. e.stopImmediatePropagation();
  412. initLayer('layer:Yandex_StreetView')
  413. if(!map) getMap()
  414. if(!isSV){
  415. map.set('styles', [
  416. {
  417. featureType: 'all',
  418. elementType: 'labels',
  419. stylers: [{ visibility: 'off' }]
  420. }
  421. ])
  422. isSV=true}
  423. else{
  424. map.set('styles', [
  425. {
  426. featureType: 'all',
  427. elementType: 'labels',
  428. stylers: [{ visibility: 'on' }]
  429. }
  430. ])
  431. isSV=false
  432. }
  433. setMapLayer('Yandex_StreetView')
  434. if (isGoogleDisplay)setMapLayer('Google_Labels')
  435. }
  436. else if (e.key === customOptions.Google_Labels_Layer_Shortcut.toLowerCase()|| e.key === customOptions.Google_Labels_Layer_Shortcut) {
  437. e.stopImmediatePropagation();
  438. if(!map) getMap()
  439. initLayer('layer:Google_Labels')
  440. setMapLayer('Google_Labels')
  441. }
  442. else if (e.key === customOptions.Google_Terrain_Layer_Shortcut.toLowerCase()|| e.key === customOptions.Google_Terrain_Layer_Shortcut) {
  443. e.stopImmediatePropagation();
  444. if(!map) getMap()
  445. initLayer('layer:terrain')
  446. setMapType('terrain')
  447. }
  448. else if (e.key === customOptions.Google_Satellite_Layer_Shortcut.toLowerCase()|| e.key === customOptions.Google_Satellite_Layer_Shortcut) {
  449. e.stopImmediatePropagation();
  450. if(!map) getMap()
  451. initLayer('layer:satellite')
  452. setMapType('satellite')
  453. }
  454. else if (e.key === customOptions.OpenWeather_Shortcut.toLowerCase()|| e.key === customOptions.OpenWeather_Shortcut) {
  455. e.stopImmediatePropagation();
  456. if(!map) getMap()
  457. initLayer('layer:weather')
  458. setMapLayer('OpenWeather')
  459. }
  460. }
  461.  
  462. document.addEventListener("keydown", onKeyDown);
  463. }
  464.  
  465. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址