UNPKG

@goongmaps/goong-map-react-native

Version:

A Goong GL react native module for creating custom maps

212 lines (178 loc) 5.94 kB
import React from 'react'; import PropTypes from 'prop-types'; import {NativeModules, requireNativeComponent} from 'react-native'; import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'; import { toJSONString, cloneReactChildrenWithProps, viewPropTypes, isFunction, } from '../utils'; import AbstractSource from './AbstractSource'; const GoongSDK = NativeModules.MGLModule; export const NATIVE_MODULE_NAME = 'RCTMGLShapeSource'; /** * ShapeSource is a map content source that supplies vector shapes to be shown on the map. * The shape may be a url or a GeoJSON object */ class ShapeSource extends AbstractSource { static NATIVE_ASSETS_KEY = 'assets'; static imageSourcePrefix = '__shape_source_images__'; static propTypes = { ...viewPropTypes, /** * A string that uniquely identifies the source. */ id: PropTypes.string, /** * An HTTP(S) URL, absolute file URL, or local file URL relative to the current application’s resource bundle. */ url: PropTypes.string, /** * The contents of the source. A shape can represent a GeoJSON geometry, a feature, or a feature colllection. */ shape: PropTypes.object, /** * Enables clustering on the source for point shapes. */ cluster: PropTypes.bool, /** * Specifies the radius of each cluster if clustering is enabled. * A value of 512 produces a radius equal to the width of a tile. * The default value is 50. */ clusterRadius: PropTypes.number, /** * Specifies the maximum zoom level at which to cluster points if clustering is enabled. * Defaults to one zoom level less than the value of maxZoomLevel so that, at the maximum zoom level, * the shapes are not clustered. */ clusterMaxZoomLevel: PropTypes.number, /** * Specifies the maximum zoom level at which to create vector tiles. * A greater value produces greater detail at high zoom levels. * The default value is 18. */ maxZoomLevel: PropTypes.number, /** * Specifies the size of the tile buffer on each side. * A value of 0 produces no buffer. A value of 512 produces a buffer as wide as the tile itself. * Larger values produce fewer rendering artifacts near tile edges and slower performance. * The default value is 128. */ buffer: PropTypes.number, /** * Specifies the Douglas-Peucker simplification tolerance. * A greater value produces simpler geometries and improves performance. * The default value is 0.375. */ tolerance: PropTypes.number, /** * Specifies the external images in key-value pairs required for the shape source. * If you have an asset under Image.xcassets on iOS and the drawables directory on android * you can specify an array of string names with assets as the key `{ assets: ['pin'] }`. * * Deprecated, please use Images#images. */ images: PropTypes.object, /** * Source press listener, gets called when a user presses one of the children layers only * if that layer has a higher z-index than another source layers * * @param {NativeSyntheticEvent<GeoJSONFeatureEvent>} event - event with geojson feature as payload * @return void */ onPress: PropTypes.func, /** * Overrides the default touch hitbox(44x44 pixels) for the source layers */ hitbox: PropTypes.shape({ width: PropTypes.number.isRequired, height: PropTypes.number.isRequired, }), }; static defaultProps = { id: GoongSDK.StyleSource.DefaultSourceID, }; setNativeProps(props) { const shallowProps = Object.assign({}, props); // Adds support for Animated if (shallowProps.shape && typeof shallowProps !== 'string') { shallowProps.shape = JSON.stringify(shallowProps.shape); } super.setNativeProps(shallowProps); } _getShape() { if (!this.props.shape) { return; } return toJSONString(this.props.shape); } _getImages() { if (!this.props.images) { return; } if (!this.props.id.startsWith(ShapeSource.imageSourcePrefix)) { console.warn( 'ShapeSource#images is deprecated, please use Images#images', ); } const images = {}; let nativeImages = []; const imageNames = Object.keys(this.props.images); for (const imageName of imageNames) { if ( imageName === ShapeSource.NATIVE_ASSETS_KEY && Array.isArray(this.props.images[ShapeSource.NATIVE_ASSETS_KEY]) ) { nativeImages = this.props.images[ShapeSource.NATIVE_ASSETS_KEY]; continue; } const res = resolveAssetSource(this.props.images[imageName]); if (res && res.uri) { images[imageName] = res; } } return { images, nativeImages, }; } render() { const props = { id: this.props.id, url: this.props.url, shape: this._getShape(), hitbox: this.props.hitbox, hasPressListener: isFunction(this.props.onPress), onMapboxShapeSourcePress: this.props.onPress, cluster: this.props.cluster ? 1 : 0, clusterRadius: this.props.clusterRadius, clusterMaxZoomLevel: this.props.clusterMaxZoomLevel, maxZoomLevel: this.props.maxZoomLevel, buffer: this.props.buffer, tolerance: this.props.tolerance, ...this._getImages(), onPress: undefined, }; return ( <RCTMGLShapeSource ref="nativeSource" {...props}> {cloneReactChildrenWithProps(this.props.children, { sourceID: this.props.id, })} </RCTMGLShapeSource> ); } } const RCTMGLShapeSource = requireNativeComponent( NATIVE_MODULE_NAME, ShapeSource, { nativeOnly: { nativeImages: true, hasPressListener: true, onMapboxShapeSourcePress: true, }, }, ); export default ShapeSource;