PropertyViewMap.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. define(["https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.0/mapbox-gl.js", "https://api.mapbox.com/mapbox.js/plugins/turf/v3.0.11/turf.min.js", "https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"], function(mapboxgl, turf) {
  2. map = '';
  3. mapboxgl_gbl = mapboxgl;
  4. turf_gbl = turf;
  5. dots = '';
  6. svg = '';
  7. curLon = '0';
  8. curLat = '0';
  9. bounds = '';
  10. geojsonFeature = {}
  11. geoBusFeature = {}
  12. function mapControl() {};
  13. //Initialize Control
  14. mapControl.prototype.initialize = function(oControlHost, fnDoneInitializing, oDataStore) {
  15. console.log('1.Initialize')
  16. // Add External StyleSheets
  17. $("head link[rel='stylesheet']").last().after("<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.0/mapbox-gl.css' rel='stylesheet' />");
  18. $("head link[rel='stylesheet']").last().after("<link href='https://endor-bsln.analytics-devlab-nonprod.w3cloud.ibm.com/samples/images/Team10_generic.css' rel='stylesheet' />");
  19. var mapContainer = oControlHost.container.id;
  20. //Default GeoJSON Setup an empty geoJson. Will populate it with data from Query
  21. geojsonFeature = {
  22. "type": "FeatureCollection",
  23. "features": []
  24. }
  25. //Initialize Mapbox and map
  26. mapboxgl.accessToken = 'pk.eyJ1IjoibWNpbnRvc2hkZXJlayIsImEiOiJjajh6M3h5eTMya3lkMzNtYmV2aWwycWZ2In0.jMqt3uXdINkigqeV8skBqA';
  27. map = new mapboxgl.Map({
  28. container: mapContainer, // container id
  29. style: 'mapbox://styles/mapbox/streets-v11', //stylesheet location
  30. center: [-96, 37.8],
  31. zoom: 3,
  32. interactive: true
  33. });
  34. bounds = new mapboxgl.LngLatBounds();
  35. fnDoneInitializing();
  36. };
  37. //Draw Control and add to screen:
  38. mapControl.prototype.draw = function(oControlHost) {
  39. console.log("3. Draw ---");
  40. console.log(geojsonFeature);
  41. var oPage = oControlHost.page;
  42. var box = oControlHost.container.id;
  43. $('#' + box).parent().prepend('<button id="reset" onclick ="reset()">Reset</button>');
  44. //Add Initial Layer to Map
  45. map.on("load", function() {
  46. //Add Cognos Source & Layer
  47. map.addSource("points", {
  48. "type": "geojson",
  49. "data": geojsonFeature
  50. });
  51. map.addLayer({
  52. "id": "points",
  53. "type": "circle",
  54. "source": "points",
  55. "paint": {
  56. 'circle-radius': {
  57. base: 10,
  58. stops: [
  59. [10, 10],
  60. [13, 10]
  61. ]
  62. },
  63. "circle-color": ["get", "color"]
  64. },
  65. "filter": ["==", "$type", "Point"],
  66. });
  67. //Add 3d Building Layer
  68. map.addLayer({
  69. 'id': '3d-buildings',
  70. 'source': 'composite',
  71. 'source-layer': 'building',
  72. 'filter': ['==', 'extrude', 'true'],
  73. 'type': 'fill-extrusion',
  74. 'minzoom': 15,
  75. 'paint': {
  76. 'fill-extrusion-color': '#aaa',
  77. // use an 'interpolate' expression to add a smooth transition effect to the
  78. // buildings as the user zooms in
  79. 'fill-extrusion-height': [
  80. "interpolate", ["linear"],
  81. ["zoom"],
  82. 15, 0,
  83. 15.05, ["get", "height"]
  84. ],
  85. 'fill-extrusion-base': [
  86. "interpolate", ["linear"],
  87. ["zoom"],
  88. 15, 0,
  89. 15.05, ["get", "min_height"]
  90. ],
  91. 'fill-extrusion-opacity': .6
  92. }
  93. });
  94. }); //End On Load
  95. //Zoom and Fit map to points
  96. geojsonFeature.features.forEach(function(feature) {
  97. bounds.extend(feature.geometry.coordinates);
  98. });
  99. map.fitBounds(bounds, {
  100. padding: 40
  101. });
  102. //SetUp Popup on Click*************************************
  103. map.on('click', 'points', function(e) {
  104. var coordinates = e.features[0].geometry.coordinates.slice();
  105. var description = e.features[0].properties.tooltip;
  106. var chart = e.features[0].properties.chart;
  107. var clr = e.features[0].properties.color;
  108. var id = e.features[0].properties.id;
  109. // zoom out a little to view popup
  110. while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
  111. coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
  112. }
  113. //Add Popup to map and add content
  114. new mapboxgl.Popup()
  115. .setLngLat(coordinates)
  116. .setHTML(description)
  117. .addTo(map);
  118. //Sample Code on how to use AJAX and Cognos Rest call to insert live item from another report
  119. /* Advance Option to use Ajax to pull live data from another Report
  120. if (clr == '#b2abd2') {
  121. $.ajax({
  122. url: chart,
  123. type: 'GET',
  124. dataType: "html",
  125. success: function(data) {
  126. new mapboxgl.Popup()
  127. .setLngLat(coordinates)
  128. .setHTML(data)
  129. .addTo(map);
  130. }
  131. });
  132. } else {
  133. new mapboxgl.Popup()
  134. .setLngLat(coordinates)
  135. .setHTML(description)
  136. .addTo(map);
  137. }
  138. */
  139. });
  140. // Change the cursor to a pointer when the mouse is over the places layer.
  141. map.on('mouseenter', 'points', function() {
  142. map.getCanvas().style.cursor = 'pointer';
  143. });
  144. // Change it back to a pointer when it leaves.
  145. map.on('mouseleave', 'points', function() {
  146. map.getCanvas().style.cursor = '';
  147. });
  148. //Update Table Functionality *************************************************
  149. //Add find and reset as a first column to list *******************************
  150. //this Expect Latitude and Longititude to be last 2 columns in the list ******
  151. $("[lid='List1']").css("background-color", "#ffffff");
  152. var numCols = $('[lid="List1"] tr:nth-child(1) td').length;
  153. $("[lid='List1'] tr").each(function(i) {
  154. var $tds = $(this).find('td'),
  155. msg = $tds.eq(2).text(),
  156. lon = $tds.eq(numCols - 1).text(),
  157. lat = $tds.eq(numCols - 2).text();
  158. $tds.eq(numCols - 1).hide();
  159. $tds.eq(numCols - 2).hide();
  160. //Add control icons to table
  161. var MapClickIcon = '<td class="lc" style="padding: 2px 5px 2px 5px; vertical-align: top; text-align:center; ">&nbsp <a class="flyMe" href="#" onclick ="flyToStore(' + parseFloat(lon) + ',' + parseFloat(lat) + ',' + parseFloat(lat) + ',\'' + msg + '\');"> <img height="20px" width="15px" src="https://dedicated-bsln.analytics-devlab-nonprod.w3cloud.ibm.com/bi/samples/images/Team10_map-pin-02.png"></img></a> </td>'
  162. var resetIcon = '<td bgcolor="#EEEEEE" style="padding: 2px 5px 2px 5px; vertical-align: middle; text-align:center; " ><a href="#" onclick ="reset()"> <img height="20px" width="20px" src="https://dedicated-bsln.analytics-devlab-nonprod.w3cloud.ibm.com/bi/samples/images/Team10_refresh.png"></img></a> </td>'
  163. if (i == 0) {
  164. $(this).prepend(resetIcon);
  165. } else {
  166. $(this).prepend(MapClickIcon);
  167. }
  168. });
  169. //Add hover effect to highlight row, can also be used to link to point on Map
  170. $("[lid='List1'] tr").not(':first').hover(
  171. function() {
  172. var $tds = $(this).find('td');
  173. if ($tds.eq(4).text().indexOf("-") >= 0) {
  174. var lat = $tds.eq(4).text().split('-')
  175. var did = $tds.eq(5).text() + ',' + lat[1];
  176. } else {
  177. var did = $tds.eq(5).text() + ',' + $tds.eq(4).text();
  178. }
  179. },
  180. function() {
  181. $(this).css("background", "");
  182. }
  183. );
  184. //Set up resizing of table container Commented out 248-257 Derek
  185. //$("[lid='resizeBlock']").css({ "resize": "horizontal", "height": "90%", "overflow": "scroll" })
  186. //$("[lid='resizeBlock']").click(function() {
  187. // var winWidth = $(window).width()
  188. // var tblWidth = $("[lid='resizeBlock']").width()
  189. // var mapWidth = (winWidth - tblWidth) - 100
  190. // $('[specname="customControl"]').css('width', mapWidth + 'px')
  191. // map.resize()
  192. //});
  193. }; //End Draw Function
  194. mapControl.prototype.setData = function(oControlHost, oDataStore) {
  195. this.m_oDataStore = oDataStore;
  196. // Loop Through Data
  197. // data is identified by column number:
  198. // col 0 = ID
  199. // col 1 - Longitutde of data Point
  200. // col 2 - Latitude of data Point
  201. // col 3 = Tool Tip Information *Requiered if no tool tip pass in an empty string
  202. // col 4 = Point Color (Color is defined in the Query to give report writer more control)
  203. var iRowCount = oDataStore.rowCount;
  204. for (var iRow = 0; iRow < iRowCount; iRow++) {
  205. var feature = {}
  206. feature['type'] = 'Feature'
  207. feature['geometry'] = {
  208. 'type': 'Point',
  209. 'coordinates': [parseFloat(oDataStore.getCellValue(iRow, 1)), parseFloat(oDataStore.getCellValue(iRow, 2)) * 1],
  210. }
  211. feature['properties'] = { 'id': oDataStore.getCellValue(iRow, 0), 'tooltip': oDataStore.getCellValue(iRow, 3), 'color': oDataStore.getCellValue(iRow, 4) }
  212. geojsonFeature['features'].push(feature)
  213. }
  214. };
  215. return mapControl;
  216. });
  217. //***********************************************************
  218. //Helper Functions ******************************************
  219. //***********************************************************
  220. // Function to move view to selected point
  221. function flyToStore(lng, lat, msg) {
  222. $('.proximityData').hide("fade", '', 500);
  223. $('.curLocation').text('View Center on: (' + lat + ',' + lng + ')');
  224. $('.reset').show();
  225. $('[lid="legendLive"]').hide()
  226. $('[lid="legendCognos"]').hide()
  227. curLon = lng;
  228. curLat = lat;
  229. if (lat < 0) {
  230. lat = -lat
  231. }
  232. map.flyTo({ center: [lng, lat], zoom: 14 });
  233. try {
  234. map.removeLayer("buff");
  235. map.removeSource("buffer");
  236. } catch (err) {
  237. console.log("Error!");
  238. }
  239. var nullIsland = {
  240. type: 'Feature',
  241. geometry: {
  242. type: 'Point',
  243. coordinates: [lng, lat]
  244. },
  245. properties: {
  246. name: 'Null Island'
  247. }
  248. };
  249. //Call function to create geojson for circle around point
  250. var oneMileOut = createGeoJSONCircle([lng, lat], .125).data
  251. //Add the geojon for circle
  252. map.addSource("buffer", {
  253. "type": "geojson",
  254. "data": oneMileOut
  255. });
  256. map.addLayer({
  257. "id": "buff",
  258. "type": "fill",
  259. "source": "buffer",
  260. "paint": {
  261. "fill-color": "#ffffff",
  262. "fill-opacity": 0.2
  263. },
  264. "filter": ["==", "$type", "Polygon"]
  265. }, "points");
  266. }
  267. //Reset Map to zoomor expand to show all the points
  268. function resetBounds() {
  269. map.fitBounds(bounds, {
  270. padding: 40
  271. });
  272. }
  273. //Function to create the Circle GeoJSON
  274. //Based on answer found here = http://stackoverflow.com/questions/37599561/drawing-a-circle-with-the-radius-in-miles-meters-with-mapbox-gl-js
  275. var createGeoJSONCircle = function(center, radiusInKm, points) {
  276. var geoFeatures = [];
  277. var counts = [];
  278. var statCounts = [];
  279. for (var k = 0; k < 4; k++) {
  280. if (!points) points = 64;
  281. var coords = {
  282. latitude: center[1],
  283. longitude: center[0]
  284. };
  285. var km = radiusInKm * (k + 1);
  286. var ret = [];
  287. var distanceX = km / (111.320 * Math.cos(coords.latitude * Math.PI / 180));
  288. var distanceY = km / 110.574;
  289. var theta, x, y;
  290. for (var i = 0; i < points; i++) {
  291. theta = (i / points) * (2 * Math.PI);
  292. x = distanceX * Math.cos(theta);
  293. y = distanceY * Math.sin(theta);
  294. ret.push([coords.longitude + x, coords.latitude + y]);
  295. }
  296. ret.push(ret[0]);
  297. var feature = {}
  298. feature['type'] = 'Feature'
  299. feature['geometry'] = {
  300. 'type': 'Polygon',
  301. 'coordinates': [ret],
  302. }
  303. feature['properties'] = { 'circle': k }
  304. geoFeatures.push(feature)
  305. }
  306. return {
  307. "type": "geojson",
  308. "data": {
  309. "type": "FeatureCollection",
  310. "features": geoFeatures
  311. }
  312. };
  313. };
  314. //Reset Map and UI items
  315. function reset() {
  316. resetBounds();
  317. curLat = 0;
  318. $('.curLocation').text('View: All');
  319. $('.proximityData').hide("fade", '', 500);
  320. $('.reset').hide();
  321. $('[lid="legendLive"]').show()
  322. $('[lid="legendCognos"]').show()
  323. //Reset Table
  324. $("[lid='List1'] tr").removeClass('trBlock');
  325. $("[lid='List1'] td").removeClass('tdBlock');
  326. $("[lid='List1'] tr").show();
  327. }
  328. //toggle layer view
  329. function layerToggle(clickedLayer) {
  330. var visibility = map.getLayoutProperty(clickedLayer, 'visibility');
  331. if (visibility === 'visible') {
  332. map.setLayoutProperty(clickedLayer, 'visibility', 'none');
  333. } else {
  334. map.setLayoutProperty(clickedLayer, 'visibility', 'visible');
  335. }
  336. };