diff options
Diffstat (limited to 'src/Components')
-rw-r--r-- | src/Components/Map.tsx | 29 | ||||
-rw-r--r-- | src/Components/MapObjects.tsx | 128 | ||||
-rw-r--r-- | src/Components/MapOverlay.tsx | 53 | ||||
-rw-r--r-- | src/Components/Settings.tsx | 32 |
4 files changed, 168 insertions, 74 deletions
diff --git a/src/Components/Map.tsx b/src/Components/Map.tsx index bb0b660..db0bed9 100644 --- a/src/Components/Map.tsx +++ b/src/Components/Map.tsx @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import { StyleSheet, View, Dimensions, ActivityIndicator } from 'react-native'; -import MapView, { Marker, Region, UrlTile } from 'react-native-maps'; +import MapView, { Marker, Region } from 'react-native-maps'; import { connect } from 'redux-su'; import { NavigationActions } from 'react-navigation'; @@ -10,6 +10,7 @@ import PortalPanel from './PortalPanel'; import { getBottomSpace } from '../helper'; import actions from '../Actions/actions'; import { LatLng } from '../Api/interfaces'; +import { getZoomByRegion, getDataZoomForMapZoom } from '../Api/api'; const { width, height } = Dimensions.get("screen") const draggableRange = { @@ -32,6 +33,7 @@ class Map extends Component<Props, State> { this.state = { user: undefined, region: null, + dataZoom: 15, } } componentDidMount() { @@ -63,7 +65,9 @@ class Map extends Component<Props, State> { ) } onRegionChange = (region: Region) => { - this.setState({ region }) + const zoom = getZoomByRegion(width, region) + const dataZoom = getDataZoomForMapZoom(zoom); + this.setState({ region, dataZoom }) setImmediate(() => this.load(false)) } @@ -79,7 +83,15 @@ class Map extends Component<Props, State> { } onPortalClick = (guid: string, coords: LatLng) => { - this.setState({ selectedPortal: { guid, coords } }) + if (this.state.selectedPortal && this.state.selectedPortal.guid == guid) { + this.setState({ selectedPortal: false }) + } else { + this.setState({ selectedPortal: { guid, coords } }) + } + } + + onPortalDismiss = () => { + this.setState({ selectedPortal: false }) } onOpenPortal = (guid: string, coords: LatLng) => { @@ -115,8 +127,13 @@ class Map extends Component<Props, State> { shouldRasterizeIOS renderToHardwareTextureAndroid > - <MapObjects onPortalClick={this.onPortalClick} region={this.state.region || initialRegion} /> - {this.state.selectedPortal && <Marker cluster={false} coordinate={this.state.selectedPortal.coords} />} + <MapObjects + onPortalClick={this.onPortalClick} + region={this.state.region || initialRegion} + levels={this.props.settings.filterLevel} + zoom={this.state.dataZoom} + /> + {this.state.selectedPortal && <Marker cluster={false} coordinate={this.state.selectedPortal.coords} onPress={this.onPortalDismiss} />} </MapView> <MapOverlay goToMe={this.goToMe} @@ -136,4 +153,4 @@ const styles = StyleSheet.create({ }, }); -export default connect({ 'entities': 'entities' }, actions)(Map)
\ No newline at end of file +export default connect({ 'entities': 'entities', 'settings': 'settings' }, actions)(Map)
\ No newline at end of file diff --git a/src/Components/MapObjects.tsx b/src/Components/MapObjects.tsx index 4b11225..2a5e1df 100644 --- a/src/Components/MapObjects.tsx +++ b/src/Components/MapObjects.tsx @@ -4,7 +4,27 @@ import { Polyline, Polygon, Marker, Region } from 'react-native-maps'; import Icon from 'react-native-vector-icons/FontAwesome'; import { Link, Portal, Field } from '../Api/types'; import { connect } from 'react-redux'; -import { COLORS, COLORS_LVL } from '../constants'; +import { COLORS, COLORS_LVL, DEFAULT_ZOOM_TO_LEVEL, DEFAULT_ZOOM_TO_LINK_LENGTH } from '../constants'; +import { calcCrow } from '../helper'; +const PORTALS = { + "N1": require('../../assets/N.png'), + "R1": require('../../assets/R1.png'), + "R2": require('../../assets/R2.png'), + "R3": require('../../assets/R3.png'), + "R4": require('../../assets/R4.png'), + "R5": require('../../assets/R5.png'), + "R6": require('../../assets/R6.png'), + "R7": require('../../assets/R7.png'), + "R8": require('../../assets/R8.png'), + "E1": require('../../assets/E1.png'), + "E2": require('../../assets/E2.png'), + "E3": require('../../assets/E3.png'), + "E4": require('../../assets/E4.png'), + "E5": require('../../assets/E5.png'), + "E6": require('../../assets/E6.png'), + "E7": require('../../assets/E7.png'), + "E8": require('../../assets/E8.png'), +} const fillPortalColor = { "R": "rgba(2, 140, 227, 0.5)", "E": "rgba(38, 205, 30, 0.5)", "N": "rgba(139, 0, 255, 0.5)" } // const fillPortalColor = { "R": COLORS[1], "E": COLORS[2], "N": COLORS[0] } @@ -13,11 +33,12 @@ const fractColor = { "R": "#028ce3", "E": "#26cd1e", "N": "#8b00ff" } const fieldColor = { "R": "rgba(2, 140, 227, 0.1)", "E": "rgba(38, 205, 30, 0.1)", "N": "rgba(139, 0, 255, 0.1)" } type Props = { - portals: { [guid: string]: Portal } - links: { [guid: string]: Link } - fields: { [guid: string]: Field } + portals: Portal[] + links: Link[] + fields: Field[] region: Region onPortalClick: Function + zoom: Number } class MapObjects extends PureComponent<Props> { @@ -31,60 +52,18 @@ class MapObjects extends PureComponent<Props> { const fields = this.props.fields const links = this.props.links const zoom = this.props.zoom - const renderPortal = Object.keys(portals) - .filter(guid => portals[guid].coords.latitude > lat1 && portals[guid].coords.latitude < lat2 && portals[guid].coords.longitude > lng1 && portals[guid].coords.longitude < lng2) - .map(guid => this.drawPortal(guid, portals[guid], this.props.onPortalClick)) - const renderLink = Object.keys(links) - .filter(guid => { - const l1 = links[guid].coords[0].latitude - const l2 = links[guid].coords[1].latitude - const n1 = links[guid].coords[0].longitude - const n2 = links[guid].coords[1].longitude - return !(l1 < lat1 && l2 < lat1 || l1 > lat2 && l2 > lat2 || n1 < lng1 && n2 < lng1 || n1 > lng2 && n2 > lng2) - }) - .map(guid => this.drawLink(guid, links[guid])) - const renderField = Object.keys(fields) - .filter(guid => { - const l1 = fields[guid].coords[0].latitude - const l2 = fields[guid].coords[1].latitude - const l3 = fields[guid].coords[2].latitude - const n1 = fields[guid].coords[0].longitude - const n2 = fields[guid].coords[1].longitude - const n3 = fields[guid].coords[2].longitude - return !( - l1 < lat1 && l2 < lat1 && l3 < lat1 || l1 > lat2 && l2 > lat2 && l3 > lat2 || - n1 < lng1 && n2 < lng1 && n3 < lng1 || n1 > lng2 && n2 > lng2 && n3 > lng2 - ) - }) - .map(guid => this.drawField(guid, fields[guid])) - - if (zoom <= 14) { - return [...renderField, ...renderLink] - } else { - return [...renderField, ...renderLink, ...renderPortal] - } + const renderPortal = this.props.renderPortal.map(guid => this.drawPortal(guid, portals[guid], this.props.onPortalClick)) + const renderLink = this.props.renderLink.map(guid => this.drawLink(guid, links[guid])) + const renderField = this.props.renderField.map(guid => this.drawField(guid, fields[guid])) + return [...renderField, ...renderLink, ...renderPortal] } drawPortal = (guid: string, entity: Portal, onPortalClick: Function) => { - const size = 20 return (<Marker key={guid} coordinate={entity.coords} onPress={() => onPortalClick(guid, entity.coords)} - > - {/* <Icon name={entity.fraction == "N" ? "circle-o" : "circle"} color={fillPortalColor[entity.fraction]} size={size} /> */} - <View style={{ - borderWidth: 2, - height: size, - width: size, - borderRadius: size / 2, - borderColor: COLORS_LVL[entity.level], - backgroundColor: fillPortalColor[entity.fraction], - justifyContent: 'center', - alignItems: 'center', - }}> - <Text style={{ fontWeight: 'bold' }}>{entity.level}</Text> - </View> - </Marker>); + image={PORTALS[entity.fraction + entity.level]} + />); } drawField = (guid: string, entity: Field) => { return <Polygon @@ -109,4 +88,47 @@ const styles = StyleSheet.create({ }); -export default connect((store, props: Props) => ({ portals: store.entities.portals, fields: store.entities.fields, links: store.entities.links }), {})(MapObjects)
\ No newline at end of file +export default connect((store, props: Props) => { + const region = props.region + const lat1 = region.latitude - region.latitudeDelta / 2 + const lat2 = region.latitude + region.latitudeDelta / 2 + const lng1 = region.longitude - region.longitudeDelta / 2 + const lng2 = region.longitude + region.longitudeDelta / 2 + const minlvl = DEFAULT_ZOOM_TO_LEVEL[Math.min(props.zoom - 1, DEFAULT_ZOOM_TO_LEVEL.length - 1)] + const minlen = DEFAULT_ZOOM_TO_LINK_LENGTH[Math.min(props.zoom - 1, DEFAULT_ZOOM_TO_LINK_LENGTH.length - 1)] / 1000 + const renderPortal = Object + .keys(store.entities.portals) + .filter(guid => store.entities.portals[guid].level >= props.levels[0] && store.entities.portals[guid].level <= props.levels[1]) + .filter(guid => store.entities.portals[guid].coords.latitude > lat1 && store.entities.portals[guid].coords.latitude < lat2 && store.entities.portals[guid].coords.longitude > lng1 && store.entities.portals[guid].coords.longitude < lng2) + + const renderLink = Object + .keys(store.entities.links) + .filter(guid => { + const l1 = store.entities.links[guid].coords[0].latitude + const l2 = store.entities.links[guid].coords[1].latitude + const n1 = store.entities.links[guid].coords[0].longitude + const n2 = store.entities.links[guid].coords[1].longitude + return !(l1 < lat1 && l2 < lat1 || l1 > lat2 && l2 > lat2 || n1 < lng1 && n2 < lng1 || n1 > lng2 && n2 > lng2) && calcCrow(l1, n1, l2, n2) >= minlen + }) + //.map(guid => this.drawLink(guid, links[guid])) + const renderField = Object + .keys(store.entities.fields) + .filter(guid => { + const l1 = store.entities.fields[guid].coords[0].guid + const l2 = store.entities.fields[guid].coords[1].guid + const l3 = store.entities.fields[guid].coords[2].guid + return store.entities.portals[l1] && store.entities.portals[l1].level >= minlvl || + store.entities.portals[l2] && store.entities.portals[l2].level >= minlvl || + store.entities.portals[l3] && store.entities.portals[l3].level >= minlvl + }) + return { + portals: store.entities.portals, + fields: store.entities.fields, + links: store.entities.links, + renderPortal, + renderField, + renderLink + } +}, {})( + MapObjects +);
\ No newline at end of file diff --git a/src/Components/MapOverlay.tsx b/src/Components/MapOverlay.tsx index faf484e..0e3624b 100644 --- a/src/Components/MapOverlay.tsx +++ b/src/Components/MapOverlay.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { StyleSheet, View, Text, GestureResponderEvent, ActivityIndicator, Linking } from 'react-native'; +import { StyleSheet, View, Text, GestureResponderEvent, ActivityIndicator, Linking, TextInput, Slider } from 'react-native'; import { FontAwesome } from '@expo/vector-icons'; import { getStatusBarHeight, getBottomSpace } from '../helper'; import { LatLng } from '../Api/interfaces'; @@ -15,11 +15,6 @@ type Props = { export default (props: Props) => ( <> <View style={styles.overlayLeft}> - {props.loading > 0 ? ( - <View style={styles.loader}> - <ActivityIndicator color={"#000"} /> - </View> - ) : null} {props.selectedPortal ? ( <> <View style={styles.buttonWrapper}> @@ -35,7 +30,7 @@ export default (props: Props) => ( backgroundColor={"#e3e3e3"} /> </View> - <View style={styles.buttonWrapper}> + {/* <View style={styles.buttonWrapper}> <FontAwesome.Button style={styles.button} name={'location-arrow'} @@ -45,9 +40,14 @@ export default (props: Props) => ( size={25} backgroundColor={"#e3e3e3"} /> - </View> + </View> */} </> ) : null} + {props.loading > 0 ? ( + <View style={styles.loader}> + <ActivityIndicator color={"#000"} /> + </View> + ) : null} </View> <View style={styles.overlayRight}> @@ -74,18 +74,23 @@ export default (props: Props) => ( /> </View> </View> + {props.selectedPortal ? ( + <View style={styles.panel}> + <Text>{JSON.stringify(props.selectedPortal)}</Text> + </View> + ) : null} </> ); const styles = StyleSheet.create({ overlayLeft: { position: 'absolute', - bottom: getBottomSpace(), + top: getStatusBarHeight() + 20, left: 8, }, overlayRight: { position: 'absolute', - bottom: getBottomSpace(), + top: getStatusBarHeight() + 20, right: 8, }, button: { @@ -93,9 +98,37 @@ const styles = StyleSheet.create({ alignItems: 'center', height: 48, width: 48, + }, buttonWrapper: { margin: 8, + //ios + shadowOpacity: 0.3, + shadowRadius: 3, + shadowOffset: { + height: 0, + width: 0 + }, + //android + elevation: 1 + }, + panel: { + position: 'absolute', + bottom: getBottomSpace(), + left: 8, + right: 8, + borderRadius: 8, + padding: 8, + backgroundColor: '#fff', + //ios + shadowOpacity: 0.3, + shadowRadius: 3, + shadowOffset: { + height: 0, + width: 0 + }, + //android + elevation: 1 }, icon: { marginRight: 0, diff --git a/src/Components/Settings.tsx b/src/Components/Settings.tsx index a99e46e..ca481a9 100644 --- a/src/Components/Settings.tsx +++ b/src/Components/Settings.tsx @@ -1,5 +1,5 @@ import React, { Component, PureComponent } from 'react'; -import { StyleSheet, View, Text, GestureResponderEvent, ActivityIndicator } from 'react-native'; +import { StyleSheet, View, Text, GestureResponderEvent, ActivityIndicator, Slider, SafeAreaView } from 'react-native'; // import { Button } from 'react-native-vector-icons/FontAwesome'; import { getStatusBarHeight } from '../helper'; import { connect } from 'react-redux'; @@ -20,15 +20,37 @@ class Settings extends PureComponent<Props> { }; render() { + const { filterLevel } = this.props.settings return ( - <View style={styles.overlay}> - {/* <Text>{JSON.stringify(this.props)}</Text> */} - </View> + <SafeAreaView style={styles.overlay}> + <Text>Мин. Ур.: {filterLevel[0]}</Text> + <Slider + style={{ width: 150, height: 40 }} + minimumValue={0} + maximumValue={filterLevel[1]} + value={filterLevel[0]} + step={1} + minimumTrackTintColor="#028ce3" + maximumTrackTintColor="#000000" + onSlidingComplete={this.props.setLevelFrom} + /> + <Text>Макс. Ур.: {filterLevel[1]}</Text> + <Slider + style={{ width: 150, height: 40 }} + minimumValue={filterLevel[0]} + maximumValue={8} + value={filterLevel[1]} + step={1} + minimumTrackTintColor="#028ce3" + maximumTrackTintColor="#000000" + onSlidingComplete={this.props.setLevelTo} + /> + </SafeAreaView> ); } } -export default connect((store) => ({}), (dispatch) => bindActionCreators(actions, dispatch))(Settings) +export default connect((store) => ({ settings: store.settings }), (dispatch) => bindActionCreators(actions, dispatch))(Settings) const styles = StyleSheet.create({ overlay: { |