WME Mapraid Overlays

Mapraid overlays

当前为 2019-09-26 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name WME Mapraid Overlays
  3. // @namespace https://greasyfork.org/en/users/166843-wazedev
  4. // @version 2019.09.25.01
  5. // @description Mapraid overlays
  6. // @author JustinS83
  7. // @include https://www.waze.com/editor*
  8. // @include https://www.waze.com/*/editor*
  9. // @include https://beta.waze.com/editor*
  10. // @include https://beta.waze.com/*/editor*
  11. // @exclude https://www.waze.com/*user/editor*
  12. // @grant none
  13. // @require https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
  14. // @contributionURL https://github.com/WazeDev/Thank-The-Authors
  15. // ==/UserScript==
  16.  
  17. /* global W */
  18. /* global OL */
  19. /* ecmaVersion 2017 */
  20. /* global $ */
  21. /* global I18n */
  22. /* global _ */
  23. /* global WazeWrap */
  24. /* global require */
  25. /* eslint curly: ["warn", "multi-or-nest"] */
  26.  
  27. (function() {
  28. 'use strict';
  29.  
  30. var _settings;
  31. var _settingsStoreName = '_wme_mapraid_overlays';
  32. var _kml;
  33. var _layerName = 'Mapraid Overlay';
  34. var _layer = null;
  35. var countryAbbr;
  36. var _origOpacity;
  37. var _mapraidNameMap = {};
  38.  
  39. function bootstrap(tries = 1) {
  40. if (W &&
  41. W.map &&
  42. W.model &&
  43. W.loginManager.user &&
  44. W.model.countries.top &&
  45. $ && WazeWrap.Ready)
  46. init();
  47. else if (tries < 1000)
  48. setTimeout(function () {bootstrap(tries++);}, 200);
  49. }
  50.  
  51. bootstrap();
  52.  
  53. function isChecked(checkboxId) {
  54. return $('#' + checkboxId).is(':checked');
  55. }
  56.  
  57. function setChecked(checkboxId, checked) {
  58. $('#' + checkboxId).prop('checked', checked);
  59. }
  60.  
  61. function loadSettings() {
  62. _settings = $.parseJSON(localStorage.getItem(_settingsStoreName));
  63. let _defaultsettings = {
  64. layerVisible: true,
  65. EnabledOverlays: {},
  66. HideCurrentArea: false
  67. };
  68. _settings = $.extend({}, _defaultsettings, _settings);
  69. }
  70.  
  71. function saveSettings() {
  72. if (localStorage) {
  73. var settings = {
  74. layerVisible: _layer.visibility,
  75. EnabledOverlays: _settings.EnabledOverlays,
  76. HideCurrentArea: _settings.HideCurrentArea
  77. };
  78. localStorage.setItem(_settingsStoreName, JSON.stringify(settings));
  79. }
  80. }
  81.  
  82. async function getKML(url){
  83. return await $.get(url);
  84. }
  85.  
  86. function GetFeaturesFromKMLString(strKML) {
  87. var format = new OL.Format.KML({
  88. 'internalProjection': W.map.baseLayer.projection,
  89. 'externalProjection': new OL.Projection("EPSG:4326"),
  90. 'extractStyles': true
  91. });
  92. return format.read(strKML);
  93. }
  94.  
  95. async function init(){
  96. loadSettings();
  97.  
  98. var layerid = 'wme_mapraid_overlays';
  99.  
  100. _layer = new OL.Layer.Vector("Mapraid Overlays", {
  101. rendererOptions: { zIndexing: true },
  102. uniqueName: layerid,
  103. layerGroup: 'mapraid_overlays',
  104. zIndex: -9999,
  105. visibility: _settings.layerVisible
  106. });
  107. I18n.translations[I18n.locale].layers.name[layerid] = "Mapraid Overlays";
  108. W.map.addLayer(_layer);
  109.  
  110. var $section = $("<div>", {style:"padding:8px 16px", id:"WMEMapraidOverlays"});
  111. $section.html([
  112. `<h4 style="margin-bottom:0px;"><b>WME Mapraid Overlays</b></h4>`,
  113. `<h6 style="margin-top:0px;">${GM_info.script.version}</h6>`,
  114. `<div><input type="checkbox" id="_cbMROHideCurrentArea" class="wmemroSettingsCheckbox" /><label for="_cbMROHideCurrentArea">Hide fill for current area</label></div>`,
  115. `<div id="divWMEMROAvailableOverlays"><label>Available overlays</label> <select id="mroOverlaySelect" style="min-width:125px;"></select><i class="fa fa-plus fa-lg" id="mroAddOverlay" aria-hidden="true" style="color:green; cursor:pointer;"></i></div>`,
  116. '<div id="currOverlays"></div>',
  117. '<div style="position:absolute; bottom:0;">Generate new mapraid overlays at <a href="http://wazedev.com/mapraidgenerator.html" target="_blank">http://wazedev.com/mapraidgenerator.html</a></div>',
  118. '</div>'
  119. ].join(' '));
  120.  
  121. new WazeWrap.Interface.Tab('MRO', $section.html(), init2);
  122. }
  123.  
  124. async function getAvailableOverlays(){
  125. $('#mroOverlaySelect').innerHTML = "";
  126. countryAbbr = W.model.countries.top.abbr;
  127. let KMLinfoArr = await $.get(`https://api.github.com/repos/WazeDev/WME-Mapraid-Overlays/contents/KMLs/${countryAbbr}`);
  128. let overlaysSelect = $('<div>');
  129. overlaysSelect.html([
  130. '<option selected disabled hidden style="display: none" value=""></option>',
  131. `${KMLinfoArr.map(function(obj){
  132. let fileName = obj.name.replace(".kml", "");
  133. if(!_settings.EnabledOverlays[fileName])
  134. return `<option value="${fileName}">${fileName}</option>`;
  135. })}`,
  136. '</select>'
  137. ].join(''));
  138. $('#mroOverlaySelect')[0].innerHTML = overlaysSelect.html();
  139. }
  140.  
  141. function updatePolygons(newKML, mapraidName){
  142. var _features = GetFeaturesFromKMLString(newKML);
  143.  
  144. for(let i=0; i< _features.length; i++){
  145. _features[i].attributes.name = _features[i].attributes.name.replace('<at><openparen>', '').replace('<closeparen>','');
  146. _features[i].style.label = _features[i].attributes.name;
  147. _features[i].style.labelOutlineColor= '#000000';
  148. _features[i].style.labelOutlineWidth= 4;
  149. _features[i].style.labelAlign= 'cm';
  150. _features[i].style.fontSize= "16px";
  151. _features[i].style.fontColor= _features[i].style.fillColor;//"#ffffff";
  152. _features[i].attributes.mapraidName = mapraidName;
  153.  
  154. if(!_settings.EnabledOverlays[mapraidName].fillAreas){
  155. if(!_origOpacity)
  156. _origOpacity = _features[i].style.fillOpacity;
  157. _features[i].style.fillOpacity = 0;
  158. }
  159. }
  160.  
  161. _layer.addFeatures(_features);
  162. }
  163.  
  164. function hex_is_light(color) {
  165. const hex = color.replace('#', '');
  166. const c_r = parseInt(hex.substr(0, 2), 16);
  167. const c_g = parseInt(hex.substr(2, 2), 16);
  168. const c_b = parseInt(hex.substr(4, 2), 16);
  169. const brightness = ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000;
  170. return brightness > 70;
  171. }
  172.  
  173. async function BuildEnabledOverlays(mapraidName){
  174. let kml;
  175. try{
  176. kml = await getKML(encodeURI(`https://raw.githubusercontent.com/WazeDev/WME-Mapraid-Overlays/master/KMLs/${countryAbbr}/${mapraidName}.kml`));
  177. }
  178. catch(err){
  179. return;
  180. console.error(err);
  181. }
  182. let kmlObj = $($.parseXML(kml));
  183. let RaidAreas = $(kmlObj).find('Placemark');
  184.  
  185. let $newRaidSection = $('<div>');
  186. $newRaidSection.html([
  187. `<fieldset style="border:1px solid silver; padding:8px; border-radius:4px; position:relative;"><legend style="margin-bottom:0px; borer-bottom-style:none; width:auto;"><h4>${mapraidName}</h4></legend>`,
  188. `<i class="fa fa-minus fa-lg" id="mroRemoveOverlay${mapraidName.replace(/\s/g, "_")}" aria-hidden="true" style="color:red; position:absolute; cursor:pointer; top:10px; right:5px;"></i>`,
  189. `<div><input type="checkbox" id="_cbMROFillRaidArea${mapraidName.replace(/\s/g, "_")}" ${_settings.EnabledOverlays[mapraidName].fillAreas ? 'checked' : ''} /><label for="_cbMROFillRaidArea${mapraidName.replace(/\s/g, "_")}">Fill raid area</label></div>`,
  190. `Jump to <select id="${mapraidName.replace(/\s/g, "_")}_Areas">${
  191. function(){
  192. let names = $(RaidAreas).find('name');
  193. let options = "";
  194. for(let i=0; i<names.length; i++)
  195. options += `<option>${$(names[i]).text()}</option>`;
  196. return options;
  197. }()
  198. }</select>`,
  199. `<i class="fa fa-share" aria-hidden="true" style="color:green; cursor:pointer;" id="JumpTo${mapraidName.replace(/\s/g, "_")}"></i>`,
  200. '</fieldset>'
  201. ].join(''));
  202.  
  203. $(`#mroOverlaySelect option[value="${mapraidName}"]`).remove(); //remove this option from the list
  204. $('#currOverlays').append($newRaidSection.html()); //add the mapraid section
  205.  
  206. $('[id^="_cbMROFillRaidArea"]').change(function(){
  207. let mapraid = this.id.replace("_cbMROFillRaidArea", "");
  208. _settings.EnabledOverlays[_mapraidNameMap[mapraid]].fillAreas = isChecked(this.id);
  209. saveSettings();
  210. });
  211.  
  212. $('[id^="mroRemoveOverlay"]').click(function(){
  213. let mapraid = this.id.replace("mroRemoveOverlay", "");
  214. $(this).parent().remove();
  215.  
  216. delete _settings.EnabledOverlays[_mapraidNameMap[mapraid]];
  217. saveSettings();
  218.  
  219. let deleteFeatures = [];
  220. for(let i=0; i < _layer.features.length; i++){ //delete the features from the layer
  221. if(_layer.features[i].attributes.mapraidName === _mapraidNameMap[mapraid])
  222. deleteFeatures.push(_layer.features[i]);
  223. }
  224. _layer.removeFeatures(deleteFeatures);
  225. getAvailableOverlays();
  226. });
  227.  
  228. $('[id^=_cbMROFillRaidArea]').change(function(){
  229. let mapraid = this.id.replace("_cbMROFillRaidArea", "");
  230. for(let i=0; i<_layer.features.length; i++){
  231. if(_layer.features[i].attributes.mapraidName.replace(/\s/g, "_") === mapraid){
  232. if(!_origOpacity)
  233. _origOpacity = _layer.features[i].style.fillOpacity;
  234. _layer.features[i].style.fillOpacity = isChecked(this.id) ? _origOpacity : 0;
  235. _layer.redraw();
  236. }
  237. }
  238. });
  239.  
  240. $('[id^="JumpTo"]').click(function(){
  241. //jump to the appropriate area - look up the area in the layer features and jump to the centroid.
  242. let raidArea = this.id.replace("JumpTo", "");
  243. for(let i=0; i<_layer.features.length; i++){
  244. if(_layer.features[i].attributes.mapraidName.replace(/\s/g, "_") === raidArea){
  245. let selectedArea = $(`#${raidArea.replace(/\s/g, "_")}_Areas`).val();
  246. if(_layer.features[i].attributes.name === selectedArea){
  247. let centroid = _layer.features[i].geometry.getCentroid();
  248. W.map.setCenter([centroid.x, centroid.y], W.map.zoom)
  249. break;
  250. }
  251. }
  252. }
  253.  
  254. });
  255.  
  256. updatePolygons(kml, mapraidName);
  257. }
  258.  
  259. function HandleMoveZoom(){
  260. //display the current MR area in the title bar
  261. //hide the current MR area fill (if setting is enabled)
  262.  
  263. if($('#mrodivCurrMapraidArea').length === 0){
  264. var $section = $("<div>");
  265. $section.html([
  266. '<div id="mrodivCurrMapraidArea" style="font-size: 16px; font-weight:bold; margin-left:10px; float:left;">',
  267. '<span id="mroCurrAreaTopbar"></span>',
  268. '</div>'
  269. ].join(' '));
  270.  
  271. $('.topbar').append($section.html());
  272. }
  273.  
  274. let center = new OL.Geometry.Point(W.map.center.lon,W.map.center.lat);
  275. $('#mroCurrAreaTopbar').text("");
  276. for (var i=0;i<_layer.features.length;i++){
  277. var feature = _layer.features[i];
  278. if(_origOpacity && _settings.EnabledOverlays[feature.attributes.mapraidName].fillAreas)
  279. feature.style.fillOpacity = _origOpacity;
  280. if(feature.geometry.intersects(center)){
  281. $('#mroCurrAreaTopbar').text(feature.attributes.name);
  282. $('#mroCurrAreaTopbar').css('color', feature.style.fillColor);
  283.  
  284. if(!hex_is_light(feature.style.fillColor))
  285. $('#mroCurrAreaTopbar').css('text-shadow', '-1px 0 #efefef, 0 1px #efefef, 1px 0 #efefef, 0 -1px #efefef');
  286. else
  287. $('#mroCurrAreaTopbar').css('text-shadow', '-1px 0 black, 0 1px black, 1px 0 black, 0 -1px black');
  288.  
  289.  
  290. if(_settings.HideCurrentArea){
  291. if(!_origOpacity)
  292. _origOpacity = feature.style.fillOpacity;
  293. if(feature.style.fillOpacity > 0)
  294. feature.style.fillOpacity = 0;
  295. }
  296. }
  297. }
  298. _layer.redraw();
  299. }
  300.  
  301. function init2(){
  302. getAvailableOverlays();
  303.  
  304. $.each(_settings.EnabledOverlays, function(k, v){
  305. if(!_mapraidNameMap[k.replace(/\s/g, "_")])
  306. _mapraidNameMap[k.replace(/\s/g, "_")] = k;
  307. BuildEnabledOverlays(k);
  308.  
  309. });
  310.  
  311. $('#mroAddOverlay').click(async function(){
  312. if($('#mroOverlaySelect').val() !== null){
  313. let raid = $('#mroOverlaySelect').val();
  314. _settings.EnabledOverlays[raid] = {fillAreas: true};
  315.  
  316. BuildEnabledOverlays(raid);
  317. if(!_mapraidNameMap[raid.replace(/\s/g, "_")])
  318. _mapraidNameMap[raid.replace(/\s/g, "_")] = raid;
  319.  
  320. saveSettings();
  321. }
  322. });
  323.  
  324. $('.wmemroSettingsCheckbox').change(function(){
  325. var settingName = $(this)[0].id.substr(6);
  326. _settings[settingName] = this.checked;
  327. saveSettings();
  328. });
  329.  
  330. $('#_cbMROHideCurrentArea').change(function(){
  331. HandleMoveZoom();
  332. });
  333.  
  334. WazeWrap.Events.register("zoomend", null, HandleMoveZoom);
  335. WazeWrap.Events.register("moveend", null, HandleMoveZoom);
  336.  
  337. setChecked('_cbMROHideCurrentArea', _settings.HideCurrentArea);
  338. HandleMoveZoom();
  339. }
  340.  
  341. })();