import * as React from 'react'; import * as PropTypes from 'prop-types'; import { Platform, requireNativeComponent, StyleSheet, ViewPropTypes, View } from 'react-native'; import type { LatLng, Point } from '../types'; import { LatLngPropType, PointPropType, mapEventsPropType } from '../prop-types'; import Component from './component'; const style = StyleSheet.create({ overlay: { position: 'absolute', }, }); export interface MarkerProps { /** * 坐标 */ coordinate: LatLng; /** * 标题,作为默认的选中弹出显示 */ title?: string; /** * 描述,显示在标题下方 */ description?: string; /** * 默认图标颜色 */ color?: string; /** * 自定义图标 */ icon?: () => React.ReactElement; /** * 自定义图片,对应原生图片名称 */ image?: string; /** * 透明度 [0, 1] */ opacity?: number; /** * 是否可拖拽 */ draggable?: boolean; /** * 是否平贴地图 */ flat?: boolean; /** * 层级 */ zIndex?: number; /** * 覆盖物锚点比例 * * @link http://a.amap.com/lbs/static/unzip/Android_Map_Doc/3D/com/amap/api/maps/model/Marker.html#setAnchor-float-float- * @platform android */ anchor?: Point; /** * 覆盖物偏移位置 * * @link http://a.amap.com/lbs/static/unzip/iOS_Map_Doc/AMap_iOS_API_Doc_3D/interface_m_a_annotation_view.html#a78f23c1e6a6d92faf12a00877ac278a7 * @platform ios */ centerOffset?: Point; /** * 是否选中,选中时将显示信息窗体,一个地图只能有一个正在选中的 marker */ active?: boolean; /** * 是否禁用点击,默认不禁用 */ clickDisabled?: boolean; /** * 是否禁用弹出窗口,默认不禁用 */ infoWindowDisabled?: boolean; /** * 自定义 InfoWindow */ children?: React.ReactChild; /** * 点击事件 */ onPress?: () => void; /** * 拖放开始事件 */ onDragStart?: () => void; /** * 拖放进行事件,类似于 mousemove,在结束之前会不断调用 */ onDrag?: () => void; /** * 拖放结束事件,最终坐标将传入参数 */ onDragEnd?: (coordinate: LatLng) => void; /** * 信息窗体点击事件 * * 注意,对于自定义信息窗体,该事件是无效的 */ onInfoWindowPress?: () => void; } const events = ['onInfoWindowPress', 'onPress', 'onDrag', 'onDragEnd', 'onDragStart']; /** * @ignore */ export default class Marker extends Component { static propTypes = { ...ViewPropTypes, ...mapEventsPropType(events), coordinate: LatLngPropType.isRequired, title: PropTypes.string, description: PropTypes.string, color: Platform.select({ android: PropTypes.oneOf(['azure', 'blue', 'cyan', 'green', 'magenta', 'orange', 'red', 'rose', 'violet', 'yellow']), ios: PropTypes.oneOf(['red', 'green', 'purple']), }), icon: PropTypes.func, image: PropTypes.string, opacity: PropTypes.number, draggable: PropTypes.bool, flat: PropTypes.bool, zIndex: PropTypes.number, anchor: PointPropType, centerOffset: PointPropType, active: PropTypes.bool, clickDisabled: PropTypes.bool, infoWindowDisabled: PropTypes.bool, }; nativeComponent = 'AMapMarker'; icon?: React.ReactElement; componentDidUpdate() { if (this.icon && Platform.OS === 'android') { setTimeout(() => this.call('update'), 0); } } active() { this.call('active'); } update() { this.call('update'); } lockToScreen(x: number, y: number) { this.call('lockToScreen', [x, y]); } renderCustomMarker(icon?: () => React.ReactElement) { if (icon) { this.icon = {icon()}; return this.icon; } return null; } /* eslint-disable class-methods-use-this */ renderInfoWindow(view?: React.ReactChild) { if (view) { // @ts-ignore return {view}; } return null; } render() { const props = { ...this.props, ...this.handlers(events), }; return ( {this.renderCustomMarker(this.props.icon)} {this.renderInfoWindow(this.props.children)} ); } } // @ts-ignore const AMapMarker = requireNativeComponent('AMapMarker', Marker); // @ts-ignore const InfoWindow = requireNativeComponent('AMapInfoWindow', { propTypes: { ...ViewPropTypes } });