Reorganize maps configuration

This commit is contained in:
Kimmo Puputti 2018-08-16 16:31:08 +03:00 committed by Hannu Lyytikainen
parent 28078d0912
commit 669e1a7edb
13 changed files with 235 additions and 206 deletions

View file

@ -1,39 +1,21 @@
import React from 'react';
// import { types as sdkTypes } from '../../util/sdkLoader';
import classNames from 'classnames';
import { getPlacePredictions, getPlaceDetails, locationBounds } from '../../util/googleMaps';
import { userLocation } from '../../util/maps';
import config from '../../config';
import css from './LocationAutocompleteInput.css';
// const { LatLng: SDKLatLng, LatLngBounds: SDKLatLngBounds } = sdkTypes;
export const CURRENT_LOCATION_ID = 'current-location';
const CURRENT_LOCATION_BOUNDS_DISTANCE = 1000; // meters
// A list of default predictions that can be shown when the user
// focuses on the autocomplete input without typing a search. This can
// be used to reduce typing and Geocoding API calls for common
// searches.
export const defaultPredictions = [
// Examples:
// Current user location from the browser geolocation API
// {
// id: CURRENT_LOCATION_ID,
// predictionPlace: {},
// },
// Helsinki
// {
// id: 'default-helsinki',
// predictionPlace: {
// address: 'Helsinki, Finland',
// origin: new SDKLatLng(60.16985, 24.93837),
// bounds: new SDKLatLngBounds(
// new SDKLatLng(60.29783, 25.25448),
// new SDKLatLng(59.92248, 24.78287)
// ),
// },
// },
];
export const defaultPredictions = (config.maps.search.suggestCurrentLocation
? [{ id: CURRENT_LOCATION_ID, predictionPlace: {} }]
: []
).concat(config.maps.search.defaults);
// When displaying data from the Google Maps Places API, and
// attribution is required next to the results.
@ -117,7 +99,7 @@ class GeocoderGoogleMaps {
return {
address: '',
origin: latlng,
bounds: locationBounds(latlng, CURRENT_LOCATION_BOUNDS_DISTANCE),
bounds: locationBounds(latlng, config.maps.search.currentLocationBoundsDistance),
};
});
}

View file

@ -5,7 +5,6 @@ import config from '../../config';
const { LatLng: SDKLatLng, LatLngBounds: SDKLatLngBounds } = sdkTypes;
export const CURRENT_LOCATION_ID = 'current-location';
const CURRENT_LOCATION_BOUNDS_DISTANCE = 1000; // meters
const locationBounds = (latlng, distance) => {
const bounds = new window.mapboxgl.LngLat(latlng.lng, latlng.lat).toBounds(distance);
@ -38,26 +37,10 @@ const placeBounds = prediction => {
// focuses on the autocomplete input without typing a search. This can
// be used to reduce typing and Geocoding API calls for common
// searches.
export const defaultPredictions = [
// Examples:
// Current user location from the browser geolocation API
// {
// id: CURRENT_LOCATION_ID,
// predictionPlace: {},
// },
// Helsinki
// {
// id: 'default-helsinki',
// predictionPlace: {
// address: 'Helsinki, Finland',
// origin: new SDKLatLng(60.16985, 24.93837),
// bounds: new SDKLatLngBounds(
// new SDKLatLng(60.29783, 25.25448),
// new SDKLatLng(59.92248, 24.78287)
// ),
// },
// },
];
export const defaultPredictions = (config.maps.search.suggestCurrentLocation
? [{ id: CURRENT_LOCATION_ID, predictionPlace: {} }]
: []
).concat(config.maps.search.defaults);
export const GeocoderAttribution = () => null;
@ -140,7 +123,7 @@ class GeocoderMapbox {
return {
address: '',
origin: latlng,
bounds: locationBounds(latlng, CURRENT_LOCATION_BOUNDS_DISTANCE),
bounds: locationBounds(latlng, config.maps.search.currentLocationBoundsDistance),
};
});
}

View file

@ -8,13 +8,13 @@ import config from '../../config';
* It handles some of the google map initialization states.
*/
const DynamicGoogleMap = withGoogleMap(props => {
const { center, zoom, address, coordinatesConfig } = props;
const { center, zoom, address, mapsConfig } = props;
const { markerURI, anchorX, anchorY, width, height } = coordinatesConfig.customMarker || {};
const markerIcon = coordinatesConfig.customMarker
const { enabled, url, anchorX, anchorY, width, height } = mapsConfig.customMarker;
const markerIcon = enabled
? {
icon: {
url: markerURI,
url,
// The origin for this image is (0, 0).
origin: new window.google.maps.Point(0, 0),
@ -27,8 +27,15 @@ const DynamicGoogleMap = withGoogleMap(props => {
const marker = <Marker position={center} {...markerIcon} title={address} />;
const circleProps = {
options: coordinatesConfig.circleOptions,
radius: coordinatesConfig.coordinateOffset,
options: {
fillColor: mapsConfig.fuzzy.circleColor,
fillOpacity: 0.2,
strokeColor: mapsConfig.fuzzy.circleColor,
strokeOpacity: 0.5,
strokeWeight: 1,
clickable: false,
},
radius: mapsConfig.fuzzy.offset,
center,
};
@ -59,7 +66,7 @@ const DynamicGoogleMap = withGoogleMap(props => {
},
}}
>
{coordinatesConfig.fuzzy ? circle : marker}
{mapsConfig.fuzzy.enabled ? circle : marker}
</GoogleMap>
);
});
@ -67,8 +74,8 @@ const DynamicGoogleMap = withGoogleMap(props => {
DynamicGoogleMap.defaultProps = {
address: '',
center: null,
zoom: config.coordinates.fuzzy ? config.coordinates.fuzzyDefaultZoomLevel : 11,
coordinatesConfig: config.coordinates,
zoom: config.maps.fuzzy.enabled ? config.maps.fuzzy.defaultZoomLevel : 11,
mapsConfig: config.maps,
};
DynamicGoogleMap.propTypes = {
@ -78,7 +85,7 @@ DynamicGoogleMap.propTypes = {
lng: number.isRequired,
}).isRequired,
zoom: number,
coordinatesConfig: object,
mapsConfig: object,
};
export default DynamicGoogleMap;

View file

@ -4,25 +4,21 @@ import uniqueId from 'lodash/uniqueId';
import { circlePolyline } from '../../util/maps';
import config from '../../config';
const mapMarker = coordinatesConfig => {
const { customMarker } = coordinatesConfig;
if (customMarker) {
const mapMarker = mapsConfig => {
const { enabled, url, width, height } = mapsConfig.customMarker;
if (enabled) {
const element = document.createElement('div');
element.style.backgroundImage = `url(${customMarker.markerURI})`;
element.style.width = `${customMarker.width}px`;
element.style.height = `${customMarker.height}px`;
element.style.backgroundImage = `url(${url})`;
element.style.width = `${width}px`;
element.style.height = `${height}px`;
return new window.mapboxgl.Marker({ element });
} else {
return new window.mapboxgl.Marker();
}
};
const circleLayer = (center, coordinatesConfig, layerId) => {
const { fillColor, fillOpacity } = coordinatesConfig.circleOptions;
const path = circlePolyline(center, coordinatesConfig.coordinateOffset).map(([lat, lng]) => [
lng,
lat,
]);
const circleLayer = (center, mapsConfig, layerId) => {
const path = circlePolyline(center, mapsConfig.fuzzy.offset).map(([lat, lng]) => [lng, lat]);
return {
id: layerId,
type: 'fill',
@ -37,8 +33,8 @@ const circleLayer = (center, coordinatesConfig, layerId) => {
},
},
paint: {
'fill-color': fillColor,
'fill-opacity': fillOpacity,
'fill-color': mapsConfig.fuzzy.circleColor,
'fill-opacity': 0.2,
},
};
};
@ -59,7 +55,7 @@ class DynamicMapboxMap extends Component {
this.updateFuzzyCirclelayer = this.updateFuzzyCirclelayer.bind(this);
}
componentDidMount() {
const { center, zoom, coordinatesConfig } = this.props;
const { center, zoom, mapsConfig } = this.props;
const position = [center.lng, center.lat];
this.map = new window.mapboxgl.Map({
@ -71,12 +67,12 @@ class DynamicMapboxMap extends Component {
});
this.map.addControl(new window.mapboxgl.NavigationControl(), 'top-left');
if (coordinatesConfig.fuzzy) {
if (mapsConfig.fuzzy.enabled) {
this.map.on('load', () => {
this.map.addLayer(circleLayer(center, coordinatesConfig, this.fuzzyLayerId));
this.map.addLayer(circleLayer(center, mapsConfig, this.fuzzyLayerId));
});
} else {
this.centerMarker = mapMarker(coordinatesConfig);
this.centerMarker = mapMarker(mapsConfig);
this.centerMarker.setLngLat(position).addTo(this.map);
}
}
@ -92,7 +88,7 @@ class DynamicMapboxMap extends Component {
return;
}
const { center, zoom, coordinatesConfig } = this.props;
const { center, zoom, mapsConfig } = this.props;
const { lat, lng } = center;
const position = [lng, lat];
@ -110,7 +106,7 @@ class DynamicMapboxMap extends Component {
}
// fuzzy circle change
if (coordinatesConfig.fuzzy && centerChanged) {
if (mapsConfig.fuzzy.enabled && centerChanged) {
if (this.map.loaded()) {
this.updateFuzzyCirclelayer();
} else {
@ -118,14 +114,14 @@ class DynamicMapboxMap extends Component {
}
}
// NOTE: coordinatesConfig changes are not handled
// NOTE: mapsConfig changes are not handled
}
updateFuzzyCirclelayer() {
if (!this.map) {
// map already removed
return;
}
const { center, coordinatesConfig } = this.props;
const { center, mapsConfig } = this.props;
const { lat, lng } = center;
const position = [lng, lat];
@ -133,7 +129,7 @@ class DynamicMapboxMap extends Component {
// We have to use a different layer id to avoid Mapbox errors
this.fuzzyLayerId = generateFuzzyLayerId();
this.map.addLayer(circleLayer(center, coordinatesConfig, this.fuzzyLayerId));
this.map.addLayer(circleLayer(center, mapsConfig, this.fuzzyLayerId));
this.map.setCenter(position);
}
@ -150,8 +146,8 @@ class DynamicMapboxMap extends Component {
DynamicMapboxMap.defaultProps = {
address: '',
center: null,
zoom: config.coordinates.fuzzy ? config.coordinates.fuzzyDefaultZoomLevel : 11,
coordinatesConfig: config.coordinates,
zoom: config.maps.fuzzy.enabled ? config.maps.fuzzy.defaultZoomLevel : 11,
mapsConfig: config.maps,
};
DynamicMapboxMap.propTypes = {
@ -161,7 +157,7 @@ DynamicMapboxMap.propTypes = {
lng: number.isRequired,
}).isRequired,
zoom: number,
coordinatesConfig: object,
mapsConfig: object,
};
export default DynamicMapboxMap;

View file

@ -31,9 +31,12 @@ export const WithObfuscatedLocation = {
obfuscatedCenter: new LatLng(60.16502999999999, 24.940064399999983),
address: 'Sharetribe',
zoom: 14,
coordinatesConfig: {
...config.coordinates,
fuzzy: true,
mapsConfig: {
...config.maps,
fuzzy: {
...config.maps.fuzzy,
enabled: true,
},
},
},
};
@ -48,9 +51,12 @@ export const WithCircleLocation = {
center: new LatLng(60.16502999999999, 24.940064399999983),
obfuscatedCenter: obfuscatedCoordinates(new LatLng(60.16502999999999, 24.940064399999983)),
address: 'Sharetribe',
coordinatesConfig: {
...config.coordinates,
fuzzy: true,
mapsConfig: {
...config.maps,
fuzzy: {
...config.maps.fuzzy,
enabled: true,
},
},
},
};

View file

@ -18,32 +18,27 @@ export class Map extends Component {
center,
obfuscatedCenter,
zoom,
coordinatesConfig,
mapsConfig,
useStaticMap,
} = this.props;
const classes = classNames(rootClassName || css.root, className);
const mapClasses = mapRootClassName || css.mapRoot;
if (coordinatesConfig.fuzzy && !obfuscatedCenter) {
if (mapsConfig.fuzzy.enabled && !obfuscatedCenter) {
throw new Error(
'Map: obfuscatedCenter prop is required when config.coordinates.fuzzy === true'
'Map: obfuscatedCenter prop is required when config.maps.fuzzy.enabled === true'
);
}
if (!coordinatesConfig.fuzzy && !center) {
throw new Error('Map: center prop is required when config.coordinates.fuzzy === false');
if (!mapsConfig.fuzzy.enabled && !center) {
throw new Error('Map: center prop is required when config.maps.fuzzy.enabled === false');
}
const location = coordinatesConfig.fuzzy ? obfuscatedCenter : center;
const location = mapsConfig.fuzzy.enabled ? obfuscatedCenter : center;
return !isMapsLibLoaded() ? (
<div className={classes} />
) : useStaticMap ? (
<StaticMap
center={location}
zoom={zoom}
address={address}
coordinatesConfig={coordinatesConfig}
/>
<StaticMap center={location} zoom={zoom} address={address} mapsConfig={mapsConfig} />
) : (
<DynamicMap
containerElement={<div className={classes} />}
@ -53,7 +48,7 @@ export class Map extends Component {
center={location}
zoom={zoom}
address={address}
coordinatesConfig={coordinatesConfig}
mapsConfig={mapsConfig}
/>
);
}
@ -64,8 +59,8 @@ Map.defaultProps = {
rootClassName: null,
mapRootClassName: null,
address: '',
zoom: config.coordinates.fuzzy ? config.coordinates.fuzzyDefaultZoomLevel : 11,
coordinatesConfig: config.coordinates,
zoom: config.maps.fuzzy.enabled ? config.maps.fuzzy.defaultZoomLevel : 11,
mapsConfig: config.maps,
useStaticMap: false,
};
@ -77,7 +72,7 @@ Map.propTypes = {
center: propTypes.latlng,
obfuscatedCenter: propTypes.latlng,
zoom: number,
coordinatesConfig: object,
mapsConfig: object,
useStaticMap: bool,
};

View file

@ -34,21 +34,17 @@ const convertOpacity = opacity => {
};
// Draw a circle polyline for fuzzy location.
const drawFuzzyCircle = (coordinatesConfig, center) => {
if (
!(
coordinatesConfig &&
typeof coordinatesConfig === 'object' &&
center &&
typeof center === 'object'
)
) {
const drawFuzzyCircle = (mapsConfig, center) => {
if (!(mapsConfig && typeof mapsConfig === 'object' && center && typeof center === 'object')) {
return '';
}
const { fillColor, fillOpacity, strokeColor, strokeWeight } = coordinatesConfig.circleOptions;
const fillColor = mapsConfig.fuzzy.circleColor;
const fillOpacity = 0.2;
const strokeColor = mapsConfig.fuzzy.circleColor;
const strokeWeight = 1;
const circleRadius = coordinatesConfig.coordinateOffset || 500;
const circleRadius = mapsConfig.fuzzy.offset || 500;
const circleStrokeWeight = strokeWeight || 1;
const circleStrokeColor = formatColorFromString(strokeColor);
const circleStrokeOpacity = convertOpacity(DEFAULT_STROKE_OPACITY);
@ -70,8 +66,8 @@ const drawFuzzyCircle = (coordinatesConfig, center) => {
// Get custom marker data for static map URI
const customMarker = (options, lat, lng) => {
const { anchorX, anchorY, markerURI } = options;
return [`anchor:${anchorX},${anchorY}`, `icon:${markerURI}`, `${lat},${lng}`].join('|');
const { anchorX, anchorY, url } = options;
return [`anchor:${anchorX},${anchorY}`, `icon:${url}`, `${lat},${lng}`].join('|');
};
class StaticGoogleMap extends Component {
@ -84,7 +80,7 @@ class StaticGoogleMap extends Component {
}
render() {
const { center, zoom, address, coordinatesConfig, dimensions } = this.props;
const { center, zoom, address, mapsConfig, dimensions } = this.props;
const { lat, lng } = center || {};
const { width, height } = dimensions;
@ -92,10 +88,10 @@ class StaticGoogleMap extends Component {
// 1. if fuzzy coordinates are used, return circle path
// 2. if customMarker is defined in config.js, use that
// 3. else return default marker
const targetMaybe = coordinatesConfig.fuzzy
? { path: drawFuzzyCircle(coordinatesConfig, center) }
: coordinatesConfig.customMarker
? { markers: customMarker(coordinatesConfig.customMarker, lat, lng) }
const targetMaybe = mapsConfig.fuzzy.enabled
? { path: drawFuzzyCircle(mapsConfig, center) }
: mapsConfig.customMarker.enabled
? { markers: customMarker(mapsConfig.customMarker, lat, lng) }
: { markers: `${lat},${lng}` };
const srcParams = stringify({
@ -103,7 +99,7 @@ class StaticGoogleMap extends Component {
zoom,
size: `${width}x${height}`,
maptype: 'roadmap',
key: config.googleMapsAPIKey,
key: config.maps.googleMapsAPIKey,
...targetMaybe,
});
@ -118,8 +114,8 @@ StaticGoogleMap.defaultProps = {
rootClassName: null,
address: '',
center: null,
zoom: config.coordinates.fuzzy ? config.coordinates.fuzzyDefaultZoomLevel : 11,
coordinatesConfig: config.coordinates,
zoom: config.maps.fuzzy.enabled ? config.maps.fuzzy.defaultZoomLevel : 11,
mapsConfig: config.maps,
};
StaticGoogleMap.propTypes = {
@ -131,7 +127,7 @@ StaticGoogleMap.propTypes = {
lng: number.isRequired,
}).isRequired,
zoom: number,
coordinatesConfig: object,
mapsConfig: object,
// from withDimensions
dimensions: shape({

View file

@ -9,42 +9,41 @@ const formatColor = color => {
return color.replace(/^#/, '');
};
const fuzzyCircleOverlay = (center, coordinatesConfig) => {
const {
strokeWeight,
strokeColor,
strokeOpacity,
fillColor,
fillOpacity,
} = coordinatesConfig.circleOptions;
const path = circlePolyline(center, coordinatesConfig.coordinateOffset);
const fuzzyCircleOverlay = (center, mapsConfig) => {
const strokeWeight = 1;
const strokeColor = mapsConfig.fuzzy.circleColor;
const strokeOpacity = 0.5;
const fillColor = mapsConfig.fuzzy.circleColor;
const fillOpacity = 0.2;
const path = circlePolyline(center, mapsConfig.fuzzy.offset);
const styles = `-${strokeWeight}+${formatColor(strokeColor)}-${strokeOpacity}+${formatColor(
fillColor
)}-${fillOpacity}`;
return `path${styles}(${encodeURIComponent(polyline.encode(path))})`;
};
const customMarkerOverlay = (center, coordinatesConfig) => {
const { markerURI } = coordinatesConfig.customMarker;
return `url-${encodeURIComponent(markerURI)}(${center.lng},${center.lat})`;
const customMarkerOverlay = (center, mapsConfig) => {
const { url } = mapsConfig.customMarker;
return `url-${encodeURIComponent(url)}(${center.lng},${center.lat})`;
};
const markerOverlay = center => {
return `pin-s(${center.lng},${center.lat})`;
};
const mapOverlay = (center, coordinatesConfig) => {
if (coordinatesConfig.fuzzy) {
return fuzzyCircleOverlay(center, coordinatesConfig);
const mapOverlay = (center, mapsConfig) => {
if (mapsConfig.fuzzy.enabled) {
return fuzzyCircleOverlay(center, mapsConfig);
}
if (coordinatesConfig.customMarker) {
return customMarkerOverlay(center, coordinatesConfig);
if (mapsConfig.customMarker.enabled) {
return customMarkerOverlay(center, mapsConfig);
}
return markerOverlay(center);
};
const StaticMapboxMap = props => {
const { address, center, zoom, coordinatesConfig, dimensions } = props;
const { address, center, zoom, mapsConfig, dimensions } = props;
const { width, height } = dimensions;
const libLoaded = typeof window !== 'undefined' && window.mapboxgl;
@ -52,13 +51,13 @@ const StaticMapboxMap = props => {
return null;
}
const overlay = mapOverlay(center, coordinatesConfig);
const overlay = mapOverlay(center, mapsConfig);
const src =
'https://api.mapbox.com/styles/v1/mapbox/streets-v10/static' +
(overlay ? `/${overlay}` : '') +
`/${center.lng},${center.lat},${zoom}` +
`/${width}x${height}` +
`?access_token=${window.mapboxgl.accessToken}`;
`?access_token=${config.maps.mapboxAccessToken}`;
return <img src={src} alt={address} />;
};
@ -66,8 +65,8 @@ const StaticMapboxMap = props => {
StaticMapboxMap.defaultProps = {
address: '',
center: null,
zoom: config.coordinates.fuzzy ? config.coordinates.fuzzyDefaultZoomLevel : 11,
coordinatesConfig: config.coordinates,
zoom: config.maps.fuzzy.enabled ? config.maps.fuzzy.defaultZoomLevel : 11,
mapsConfig: config.maps,
};
StaticMapboxMap.propTypes = {
@ -77,7 +76,7 @@ StaticMapboxMap.propTypes = {
lng: number.isRequired,
}).isRequired,
zoom: number,
coordinatesConfig: object,
mapsConfig: object,
// from withDimensions
dimensions: shape({

View file

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { arrayOf, bool, func, number, string, shape } from 'prop-types';
import { arrayOf, bool, func, number, string, shape, object } from 'prop-types';
import { withRouter } from 'react-router-dom';
import { withGoogleMap, GoogleMap } from 'react-google-maps';
import classNames from 'classnames';
@ -279,14 +279,14 @@ export class SearchMapComponent extends Component {
onCloseAsModal,
onIdle,
zoom,
coordinatesConfig,
mapsConfig,
activeListingId,
} = this.props;
const classes = classNames(rootClassName || css.root, className);
const mapClasses = mapRootClassName || css.mapRoot;
const listingsWithLocation = originalListings.filter(l => !!l.attributes.geolocation);
const listings = coordinatesConfig.fuzzy
const listings = mapsConfig.fuzzy.enabled
? withCoordinatesObfuscated(listingsWithLocation)
: listingsWithLocation;
const infoCardOpen = this.state.infoCardOpen;
@ -345,7 +345,7 @@ SearchMapComponent.defaultProps = {
onCloseAsModal: null,
useLocationSearchBounds: true,
zoom: 11,
coordinatesConfig: config.coordinates,
mapsConfig: config.maps,
};
SearchMapComponent.propTypes = {
@ -361,9 +361,7 @@ SearchMapComponent.propTypes = {
onIdle: func.isRequired,
useLocationSearchBounds: bool, // eslint-disable-line react/no-unused-prop-types
zoom: number,
coordinatesConfig: shape({
fuzzy: bool.isRequired,
}),
mapsConfig: object,
// from withRouter
history: shape({

View file

@ -1,4 +1,5 @@
import * as custom from './marketplace-custom-config.js';
import defaultLocationSearches from './default-location-searches';
const env = process.env.REACT_APP_ENV;
const dev = process.env.REACT_APP_ENV === 'development';
@ -262,57 +263,74 @@ const siteFacebookPage = 'https://www.facebook.com/Sharetribe/';
// You should create one to track social sharing in Facebook
const facebookAppId = null;
// Google Maps API key is needed for static map images.
const googleMapsAPIKey = process.env.REACT_APP_GOOGLE_MAPS_API_KEY;
const maps = {
mapboxAccessToken: process.env.REACT_APP_MAPBOX_ACCESS_TOKEN,
googleMapsAPIKey: process.env.REACT_APP_GOOGLE_MAPS_API_KEY,
const coordinates = {
// If true, obfuscate the coordinates of the listings that are shown
// on a map.
fuzzy: false,
// The location search input can be configured to show default
// searches when the user focuses on the input and hasn't yet typed
// anything. This reduces typing and avoids too many Geolocation API
// calls for common searches.
search: {
// When enabled, the first suggestion is "Current location" that
// uses the browser Geolocation API to query the user's current
// location.
suggestCurrentLocation: process.env.REACT_APP_DEFAULT_SEARCHES_ENABLED === 'true',
// Default zoom level when showing a single circle on a Map. Should
// be small enough so the whole circle fits in.
fuzzyDefaultZoomLevel: 14,
// Distance in meters for calculating the bounding box around the
// current location.
currentLocationBoundsDistance: 1000,
// When fuzzy === true, the coordinates on the Map component are
// obfuscated and a circle is shown instead of a marker. To decide a
// proper value for the offset and the radius, see:
//
// https://gis.stackexchange.com/a/8674
// Amount of maximum offset in meters that is applied to obfuscate
// the original coordinates. The actual value is random, but the
// obfuscated coordinates are withing a circle that has the same
// radius as the offset.
coordinateOffset: 500,
// Options to style the circle appearance.
//
// See: https://developers.google.com/maps/documentation/javascript/reference#CircleOptions
circleOptions: {
fillColor: '#c0392b',
fillOpacity: 0.2,
strokeColor: '#c0392b',
strokeOpacity: 0.5,
strokeWeight: 1,
clickable: false,
// Example location can be edited in the
// `default-location-searches.js` file.
defaults: defaultLocationSearches,
},
// An option to use custom marker on static maps. Uncomment to enable it.
// https://developers.google.com/maps/documentation/maps-static/dev-guide#Markers
// When fuzzy locations are enabled, coordinates on maps are
// obfuscated randomly around the actual location.
//
// Note 1: fuzzy coordinate circle overwrites these custom marker settings)
// Note 2: markerURI needs to be a public URI accessible by Google Maps API servers.
// The easiest place is /public/static/icons/ folder, but then the marker image is not available
// while developing through localhost.
// NOTE: This only hides the locations in the UI level, the actual
// coordinates are still accessible in the HTTP requests and the
// Redux store.
fuzzy: {
enabled: false,
// customMarker: {
// markerURI: encodeURI(`${canonicalRootURL}/static/icons/map-marker-32x32.png`),
// anchorX: 16,
// anchorY: 32,
// width: 32,
// height: 32,
// },
// Amount of maximum offset in meters that is applied to obfuscate
// the original coordinates. The actual value is random, but the
// obfuscated coordinates are withing a circle that has the same
// radius as the offset.
offset: 500,
// Default zoom level when showing a single circle on a Map. Should
// be small enough so the whole circle fits in.
defaultZoomLevel: 13,
// Color of the circle on the Map component.
circleColor: '#c0392b',
},
// Custom marker image to use in the Map component.
//
// NOTE: Not used if fuzzy locations are enabled.
customMarker: {
enabled: false,
// Publicly accessible URL for the custom marker image.
//
// The easiest place is /public/static/icons/ folder, but then the
// marker image is not available while developing through
// localhost.
url: encodeURI(`${canonicalRootURL}/static/icons/map-marker-32x32.png`),
// Dimensions of the marker image.
width: 32,
height: 32,
// Position to anchor the image in relation to the coordinates,
// ignored when using Mapbox.
anchorX: 16,
anchorY: 32,
},
};
// NOTE: only expose configuration that should be visible in the
@ -350,8 +368,7 @@ const config = {
facebookAppId,
sentryDsn,
usingSSL,
googleMapsAPIKey,
coordinates,
maps,
custom,
};

View file

@ -25,7 +25,7 @@ class SectionMapMaybe extends Component {
const address = publicData.location ? publicData.location.address : '';
const classes = classNames(rootClassName || css.sectionMap, className);
const mapProps = config.coordinates.fuzzy
const mapProps = config.maps.fuzzy.enabled
? { obfuscatedCenter: obfuscatedCoordinates(geolocation, listingId ? listingId.uuid : null) }
: { address, center: geolocation };
const map = <Map {...mapProps} useStaticMap={this.state.isStatic} />;

View file

@ -0,0 +1,51 @@
import { types as sdkTypes } from './util/sdkLoader';
const { LatLng, LatLngBounds } = sdkTypes;
// An array of locations to show in the LocationAutocompleteInput when
// the input is in focus but the user hasn't typed in any search yet.
//
// Each item in the array should be an object with a unique `id` (String) and a
// `predictionPlace` (util.types.place) properties.
export default [
{
id: 'default-helsinki',
predictionPlace: {
address: 'Helsinki, Finland',
origin: new LatLng(60.16985, 24.93837),
bounds: new LatLngBounds(new LatLng(60.29783, 25.25448), new LatLng(59.92248, 24.78287)),
},
},
{
id: 'default-turku',
predictionPlace: {
address: 'Turku, Finland',
origin: new LatLng(60.45181, 22.26663),
bounds: new LatLngBounds(new LatLng(60.53045, 22.38197), new LatLng(60.33361, 22.06644)),
},
},
{
id: 'default-tampere',
predictionPlace: {
address: 'Tampere, Finland',
origin: new LatLng(61.49775, 23.76095),
bounds: new LatLngBounds(new LatLng(61.83657, 24.11838), new LatLng(61.42728, 23.5422)),
},
},
{
id: 'default-oulu',
predictionPlace: {
address: 'Oulu, Finland',
origin: new LatLng(65.01208, 25.46507),
bounds: new LatLngBounds(new LatLng(65.56434, 26.77069), new LatLng(64.8443, 24.11494)),
},
},
{
id: 'default-ruka',
predictionPlace: {
address: 'Ruka, Finland',
origin: new LatLng(66.16546, 29.15172),
bounds: new LatLngBounds(new LatLng(66.16997, 29.16773), new LatLng(66.16095, 29.13572)),
},
},
];

View file

@ -12,10 +12,9 @@ const { LatLng } = sdkTypes;
*/
const obfuscatedCoordinatesImpl = (latlng, cacheKey) => {
const { lat, lng } = latlng;
const offset = config.coordinates.coordinateOffset;
// https://gis.stackexchange.com/questions/25877/generating-random-locations-nearby
const r = offset / 111300;
const r = config.maps.fuzzy.offset / 111300;
const y0 = lat;
const x0 = lng;