Advertisement
Guest User

mapview directions

a guest
Apr 22nd, 2019
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.24 KB | None | 0 0
  1. import React, { Component } from 'react';
  2. import PropTypes from 'prop-types';
  3. import MapView from 'react-native-maps';
  4. import isEqual from 'lodash.isequal';
  5.  
  6. class MapViewDirections extends Component {
  7.  
  8. constructor(props) {
  9. super(props);
  10.  
  11. this.state = {
  12. coordinates: null,
  13. distance: null,
  14. duration: null,
  15. newWaypoints: []
  16. };
  17. }
  18.  
  19. componentDidMount() {
  20. this._mounted = true;
  21. this.fetchAndRenderRoute(this.props);
  22. }
  23.  
  24. componentWillUnmount() {
  25. this._mounted = false;
  26. }
  27.  
  28. componentWillReceiveProps(nextProps) {
  29. if (!isEqual(nextProps.origin, this.props.origin) || !isEqual(nextProps.destination, this.props.destination) || !isEqual(nextProps.waypoints, this.props.waypoints)) {
  30. if (nextProps.resetOnChange === false) {
  31. this.fetchAndRenderRoute(nextProps);
  32. } else {
  33. this.resetState(() => {
  34. this.fetchAndRenderRoute(nextProps);
  35. });
  36. }
  37. }
  38. }
  39.  
  40. resetState = (cb = null) => {
  41. this._mounted && this.setState({
  42. coordinates: null,
  43. distance: null,
  44. duration: null,
  45. }, cb);
  46. }
  47.  
  48. decode(t, e) {
  49. for (var n, o, u = 0, l = 0, r = 0, d = [], h = 0, i = 0, a = null, c = Math.pow(10, e || 5); u < t.length;) {
  50. a = null, h = 0, i = 0;
  51. do a = t.charCodeAt(u++) - 63, i |= (31 & a) << h, h += 5; while (a >= 32);
  52. n = 1 & i ? ~(i >> 1) : i >> 1, h = i = 0;
  53. do a = t.charCodeAt(u++) - 63, i |= (31 & a) << h, h += 5; while (a >= 32);
  54. o = 1 & i ? ~(i >> 1) : i >> 1, l += n, r += o, d.push([l / c, r / c]);
  55. }
  56.  
  57. return d = d.map(function (t) {
  58. return {
  59. latitude: t[0],
  60. longitude: t[1],
  61. };
  62. });
  63. }
  64.  
  65. fetchAndRenderRoute = (props) => {
  66.  
  67. let {
  68. origin,
  69. destination,
  70. waypoints,
  71. apikey,
  72. onStart,
  73. onReady,
  74. onError,
  75. mode = 'driving',
  76. language = 'en',
  77. tripCriteria,
  78. directionsServiceBaseUrl = 'https://maps.googleapis.com/maps/api/directions/json',
  79. } = props;
  80.  
  81. if (!origin || !destination) {
  82. return;
  83. }
  84.  
  85. if (origin.latitude == 0 || origin.longitude == 0 || destination.latitude == 0 || destination.longitude == 0) {
  86. return;
  87. }
  88.  
  89. if (origin.latitude && origin.longitude) {
  90. origin = `${origin.latitude},${origin.longitude}`;
  91. }
  92.  
  93. if (destination.latitude && destination.longitude) {
  94. destination = `${destination.latitude},${destination.longitude}`;
  95. }
  96.  
  97. if (!waypoints || !waypoints.length) {
  98. waypoints = '';
  99. } else {
  100. waypoints = waypoints
  101. .map(waypoint => (waypoint.latitude && waypoint.longitude) ? `${waypoint.latitude},${waypoint.longitude}` : waypoint)
  102. .join('|');
  103. }
  104.  
  105.  
  106. onStart && onStart({
  107. origin,
  108. destination,
  109. waypoints: waypoints ? waypoints.split('|') : [],
  110. });
  111.  
  112. this.fetchRoute(directionsServiceBaseUrl, origin, waypoints, destination, apikey, mode, language)
  113. .then(result => {
  114. let distanceTotal = 0;
  115. let durationTotal = 0;
  116. let criteriaCounter = 0;
  117.  
  118. var currentTime = new Date();
  119.  
  120. result.json.routes[0].legs[0].steps.map((step) => {
  121. if (criteriaCounter < tripCriteria.length) {
  122. durationTotal += Math.floor(step.duration.value / 60);
  123. let criteriaHours = tripCriteria[criteriaCounter].time.getHours(); //time hours
  124. let criteriaMinutes = tripCriteria[criteriaCounter].time.getMinutes(); // time minutes
  125. let estimatedTime = this.handleEstimatedStepTime(currentTime, durationTotal);
  126.  
  127. // console.log('EST: ' + estimatedTime);
  128. // console.log('MIN: ' + this.calculateMinTime(criteriaHours, criteriaMinutes));
  129. // console.log('MAX: ' + this.calculateMaxTime(criteriaHours, criteriaMinutes));
  130.  
  131. if (estimatedTime >= this.calculateMinTime(criteriaHours, criteriaMinutes) && estimatedTime <= this.calculateMaxTime(criteriaHours, criteriaMinutes)) {
  132. this.fetchWaypoint(apikey, tripCriteria[criteriaCounter].category + ' ' + tripCriteria[criteriaCounter].criteriaName, step.start_location)
  133. .then(waypointResult => {
  134. this.setState(prevState => ({ newWaypoints: [...prevState.newWaypoints, waypointResult.json.results[0]] }));
  135. // waypoints = newWaypoints.map(waypoint => `${waypoint.geometry.location.lat},${waypoint.geometry.location.lng}`).join('|');
  136. // console.log(waypoints);
  137. });
  138. if (criteriaCounter <= tripCriteria.length - 1) {
  139. criteriaCounter++;
  140. }
  141.  
  142. }
  143. }
  144.  
  145. });
  146.  
  147. result = this.fetchRoute(directionsServiceBaseUrl, origin, waypoints, destination, apikey, mode, language)
  148. .catch(errorMessage => {
  149. this.resetState();
  150. console.warn(`MapViewDirections Error: ${errorMessage}`); // eslint-disable-line no-console
  151. onError && onError(errorMessage);
  152. })
  153.  
  154. if (!this._mounted) return;
  155. this.setState(result);
  156. onReady && onReady(result);
  157. })
  158. //generate new route here maybe?
  159. .catch(errorMessage => {
  160. this.resetState();
  161. console.warn(`MapViewDirections Error: ${errorMessage}`); // eslint-disable-line no-console
  162. onError && onError(errorMessage);
  163. });
  164.  
  165. }
  166.  
  167. fetchWaypoint(apikey, searchInput, projectedLocation) {
  168. let url = 'https://maps.googleapis.com/maps/api/place/textsearch/json';
  169. url += `?input=${searchInput}&inputtype=textquery&location=${projectedLocation.lat},${projectedLocation.lng}&fields=name,types&key=${apikey}&radius=2000`;
  170.  
  171. return fetch(encodeURI(url))
  172. .then(response => response.json())
  173. .then(json => {
  174. if (json.status !== 'OK') {
  175. const errorMessage = json.error_message || 'Unkown error';
  176. return Promise.reject(errorMessage);
  177. }
  178.  
  179. if (json.results.length) {
  180. return Promise.resolve({ json });
  181. } else {
  182. return Promise.reject();
  183. }
  184.  
  185. })
  186. }
  187.  
  188. fetchRoute(directionsServiceBaseUrl, origin, waypoints, destination, apikey, mode, language) {
  189.  
  190. // Define the URL to call. Only add default parameters to the URL if it's a string.
  191. let url = directionsServiceBaseUrl;
  192. if (typeof (directionsServiceBaseUrl) === 'string') {
  193. url += `?origin=${origin}&waypoints=${waypoints}&destination=${destination}&key=${apikey}&mode=${mode}&language=${language}`;
  194. }
  195.  
  196. return fetch(url)
  197. .then(response => response.json())
  198. .then(json => {
  199.  
  200. if (json.status !== 'OK') {
  201. const errorMessage = json.error_message || 'Unknown error';
  202. return Promise.reject(errorMessage);
  203. }
  204.  
  205. if (json.routes.length) {
  206.  
  207. const route = json.routes[0];
  208.  
  209. return Promise.resolve({
  210. json,
  211. coordinates: this.decode(route.overview_polyline.points)
  212. });
  213.  
  214. } else {
  215. return Promise.reject();
  216. }
  217. });
  218. }
  219.  
  220. calculateMaxTime(criteriaHours, criteriaMinutes) {
  221. let criteriaMax = new Date();
  222.  
  223. if (criteriaMinutes % 60 > 30) {
  224. criteriaMax.setHours(criteriaHours + 1);
  225. criteriaMax.setMinutes(60 - criteriaMinutes);
  226. } else {
  227. criteriaMax.setHours(criteriaHours);
  228. criteriaMax.setMinutes(criteriaMinutes + 30);
  229. }
  230.  
  231. return criteriaMax;
  232. }
  233.  
  234. calculateMinTime(criteriaHours, criteriaMinutes) {
  235. let criteriaMin = new Date();
  236.  
  237. if (criteriaMinutes % 60 < 30) {
  238. criteriaMin.setHours(criteriaHours - 1);
  239. criteriaMin.setMinutes(60 - criteriaMinutes);
  240. } else {
  241. criteriaMin.setHours(criteriaHours);
  242. criteriaMin.setMinutes(criteriaMinutes - 30);
  243. }
  244.  
  245. return criteriaMin;
  246. }
  247.  
  248. handleEstimatedStepTime(currentTime, tripDuration) {
  249. var tripTime = new Date();
  250. let hours = Math.floor(tripDuration / 60);
  251. let minutes = tripDuration % 60;
  252.  
  253. tripTime.setHours(currentTime.getHours() + hours);
  254. if(currentTime.getMinutes() + minutes > 59){
  255. tripTime.setMinutes((currentTime.getMinutes() + minutes) % 60);
  256. tripTime.setHours(tripTime.getHours() + 1);
  257. }else{
  258. tripTime.setMinutes((currentTime.getMinutes() + minutes));
  259. }
  260.  
  261. return tripTime;
  262. }
  263.  
  264.  
  265. render() {
  266. if (!this.state.coordinates) {
  267. return null;
  268. }
  269.  
  270. const {
  271. origin, // eslint-disable-line no-unused-vars
  272. waypoints, // eslint-disable-line no-unused-vars
  273. destination, // eslint-disable-line no-unused-vars
  274. apikey, // eslint-disable-line no-unused-vars
  275. onReady, // eslint-disable-line no-unused-vars
  276. onError, // eslint-disable-line no-unused-vars
  277. mode, // eslint-disable-line no-unused-vars
  278. language, // eslint-disable-line no-unused-vars
  279. ...props
  280. } = this.props;
  281.  
  282. return (
  283. <MapView.Polyline coordinates={this.state.coordinates} {...props} />
  284. );
  285. }
  286.  
  287. }
  288.  
  289. MapViewDirections.propTypes = {
  290. origin: PropTypes.oneOfType([
  291. PropTypes.string,
  292. PropTypes.shape({
  293. latitude: PropTypes.number.isRequired,
  294. longitude: PropTypes.number.isRequired,
  295. }),
  296. ]),
  297. waypoints: PropTypes.arrayOf(
  298. PropTypes.oneOfType([
  299. PropTypes.string,
  300. PropTypes.shape({
  301. latitude: PropTypes.number.isRequired,
  302. longitude: PropTypes.number.isRequired,
  303. }),
  304. ]),
  305. ),
  306. destination: PropTypes.oneOfType([
  307. PropTypes.string,
  308. PropTypes.shape({
  309. latitude: PropTypes.number.isRequired,
  310. longitude: PropTypes.number.isRequired,
  311. }),
  312. ]),
  313. apikey: PropTypes.string.isRequired,
  314. onStart: PropTypes.func,
  315. onReady: PropTypes.func,
  316. onError: PropTypes.func,
  317. mode: PropTypes.oneOf(['driving', 'bicycling', 'transit', 'walking']),
  318. language: PropTypes.string,
  319. resetOnChange: PropTypes.bool,
  320. directionsServiceBaseUrl: PropTypes.string,
  321. };
  322.  
  323. export default MapViewDirections;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement