尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

react-native-maps 的 `<Marker />` 组件完全指南:属性、事件、方法与自定义标记实战

react-native-maps 的 `<Marker />` 组件完全指南:属性、事件、方法与自定义标记实战 移动开发UI组件前端【免费下载链接】react-native-mapsReact Native Mapview component for iOS Android项目地址https://gitcode.com/gh_mirrors/re/react-native-maps点击查看免费下载Marker /是 react-native-maps 中最核心、使用频率最高的地图标注组件用于在地图经纬度坐标上放置大头针、自定义图标或任意 React Native 视图并支持拖拽、旋转、浮层Callout、动画等交互能力。本文以仓库官方文档 docs/marker.md 为主体骨架结合仓库内组件源码与 example 示例工程系统讲解 Marker 的全部 Props、事件回调、命令式方法、自定义标记方案与性能优化实践读完即可在 iOSApple Maps / Google Maps与 Android 双端正确使用并调优 Marker。一、组件概览与基本用法Marker 由仓库 src/MapMarker.tsx 实现通过decorateMapComponent装饰后对外导出google.ios为SUPPORTEDgoogle.android使用默认实现因此同一个 JSX 写法可以同时运行在 Apple Maps、Google Maps 与 Android 上。最基础的用法只需提供coordinateimport MapView, {Marker} from react-native-maps; MapView initialRegion{{latitude: 37.78825, longitude: -122.4324, latitudeDelta: 0.0922, longitudeDelta: 0.0421}} Marker coordinate{{latitude: 37.78825, longitude: -122.4324}} / /MapView在 example 工程的 DefaultMarkers.tsx 中可以看到一个典型场景监听地图onPress事件把点击坐标加入数组动态渲染任意数量的 Marker并给每个 Marker 随机分配pinColor。这说明 Marker 完全可以作为受控组件批量渲染配合key使用即可。二、Props 详解下表完整列出Marker /支持的全部属性、类型、默认值及说明其中ImageSource即 React Native 官方Image组件定义的ImageSource类型可为ImageURISource | ImageRequireSource见 src/MapMarker.tsx 的类型声明Prop类型默认值说明titleString标记的标题。仅当Marker /没有Callout /子组件时使用此时走默认 Callout 行为会同时展示title与description若提供descriptionString标记的描述。仅当 Marker 没有Callout /子组件时使用与title一同在默认 Callout 中展示imageImageSource*用作标记图标的自定义图片仅允许使用本地图片资源iOS 与 Android 均支持iconImageSource*标记图标等价于 GMSMarker 类的icon属性。仅允许本地图片资源。注意仅 Google Maps 支持pinColorColor未提供自定义标记视图或自定义图片时使用平台默认大头针可通过该颜色自定义。使用自定义标记时被忽略。Android 可用颜色有限不支持的颜色会回退为红色详见 issue #887coordinateLatLng标记的经纬度坐标必填centerOffsetPoint(0, 0)标注视图的显示偏移单位 points。默认标注视图中心点位于坐标点处正值向右下移动负值向左上移动。Google Maps 请改用anchorcalloutOffsetPoint(0, 0)Callout 气泡的放置偏移单位 points。为 (0, 0) 时气泡锚点位于标记视图 frame 的顶部中心正值向右下移动负值向左上移动。Google Maps 请改用calloutAnchoranchorPoint(0.5, 1)标记的锚点指定图标中锚定到地表坐标的点。锚点位于连续空间 [0.0, 1.0] × [0.0, 1.0](0, 0) 为图片左上角(1, 1) 为右下角。对于 W×H 图片锚点会被缩放并取整到 (W1)×(H1) 网格上最近的离散格点例如 4×2 图片中锚点 (0.7, 0.6) 解析为格点 (3, 1)。iOS Apple Maps 请改用centerOffsetcalloutAnchorPoint(0.5, 0)显示 Callout 时在标记图片上的锚点坐标系与anchor相同默认位于图片顶部中间。iOS Apple Maps 请改用calloutOffsetflatBooleanfalse设置标记是贴在地图平面上的true还是始终面向相机的广告牌billboardfalseidentifierString用于日后引用该标记的标识符rotationFloat0标记的旋转角度单位为度。仅 Google MapsiOS与 Android 支持draggablenull非取值型属性只要加上该属性例如draggable即可让标记可拖拽重新定位tappableBooleantrue标记是否可点击。设为 false 后标记不再触发onPress。注意仅 iOS Google Maps 支持tracksViewChangesBooleantrue标记是否追踪子视图变化。使用子视图做自定义标记时决定首次渲染后内容变化是否被追踪。该选项有性能开销建议尽量关闭内容变化时显式调用redraw方法tracksInfoWindowChangesBooleanfalse标记是否追踪信息窗口InfoWindow的视图变化。开启后可让标记在首次渲染后更新信息窗口内容但会降低性能不需要时应关闭。注意仅 iOS Google Maps 支持stopPropagationBooleanfalse是否阻止onPress事件冒泡。开启后父级MapView的onPress将不再被调用。注意仅 iOS 支持Android 本身不冒泡onPress事件详见 issue #1132opacityFloat1.0标记的不透明度取值 0.01.0isPreselectedBooleanfalse为 true 时标记被预选中用户无需先点击聚焦即可直接拖拽。注意仅 iOS Apple Maps 支持keyString若未指定key或key不唯一Marker /将被复用位置变化时会产生动画想禁用动画可传入唯一key如key_${item.longitude}_${item.latitude}。注意仅 iOS 支持titleVisibilityvisible \| hidden \| adaptivehidden标记气泡下方标题文字的可见性。注意仅 iOS Apple Maps 支持subtitleVisibilityvisible \| hidden \| adaptivehidden标记气泡下方副标题文字的可见性。注意仅 iOS Apple Maps 支持useLegacyPinViewBooleanfalse决定使用旧版MKPinAnnotationViewtrue还是新版MKMarkerAnnotationViewfalse。自定义标记不受影响。注意仅 iOS Apple Maps 支持*ImageSourceReact Native 官方Image组件的ImageSource类型。2.1 源码视角平台差异与图片处理上述 Props 在 src/MapMarker.tsx 中均有 TypeScript 声明每个属性的 JSDoc 标注了platform支持范围与文档表格一致可作为开发时的权威参考。值得关注的是image/icon的底层处理逻辑src/MapMarker.tsx在 Fabric 架构下两者都会先经过fixImageProp见 src/fixImageProp.ts统一处理本地资源在旧架构iOS Google Maps 的非 Fabric 路径下还会把uri进一步提取为字符串传给原生层。因此文档强调「仅允许本地图片资源」是有实现依据的——远程 URL 图片不会被解析为预期的图标。stopPropagation的实现在渲染层src/MapMarker.tsx当该属性为 true 时内部包裹的onPress会先调用event.stopPropagation()再转发用户回调从而阻止事件冒泡到父级 MapView。2.2 默认大头针与 pinColor 实战DefaultMarkers.tsx 展示了「不传自定义视图/图片仅用平台大头针 随机颜色」的写法{this.state.markers.map((marker: any) ( Marker key{marker.key} coordinate{marker.coordinate} pinColor{marker.color} / ))}需要注意在 Android 上pinColor可用颜色受限于平台实现不支持的色值会回退为红色这是平台行为而非库的 bug。2.3 自定义图标 image / iconCustomMarkers.tsx 展示了用本地图片资源做标记图标的完整示例图片来自 example/src/examples/assets/flag-pink.png 与 example/src/examples/assets/flag-blue.pngMarker title{marker.key} image{marker.pink ? flagPinkImg : flagBlueImg} key{marker.key} coordinate{marker.coordinate} /image与icon语义接近主要区别在于icon对应 Google Maps 原生GMSMarker.icon因此icon标注为「仅 Google Maps」在 Apple Maps 与 Android 上请使用image。三、事件Events事件回调的数据需要通过e.nativeEvent访问。例如onPress{e console.log(e.nativeEvent)}会把完整事件对象打印到控制台。事件名返回数据说明onPress{ coordinate: LatLng, position: Point }用户按下标记时触发onSelect{ coordinate: LatLng, position: Point }用户选中标记时触发发生在 Callout 显示之前onDeselect{ coordinate: LatLng, position: Point }标记被取消选中时触发发生在 Callout 隐藏之前onCalloutPress用户点击 Callout 视图时触发onDragStart{ coordinate: LatLng, position: Point }用户开始拖拽标记时触发需标记可拖拽onDrag{ coordinate: LatLng, position: Point }标记拖拽过程中持续触发onDragEnd{ coordinate: LatLng, position: Point }拖拽结束时触发通常是重新setState标记坐标的时机3.1 事件数据与拖拽实战DraggableMarkers.tsx 演示了统一打印事件数据的辅助函数function log(eventName: any, e: any) { console.log(eventName, e.nativeEvent); }随后在 Marker 上挂载onSelect、onDrag、onDragStart、onDragEnd、onPress并加上draggable属性即可见 DraggableMarkers.tsx。关于onDragEnd有一个重要实践拖拽完成后原生层已经移动了标记React 状态并不会自动同步因此通常应在onDragEnd里把e.nativeEvent.coordinate通过setState写回标记的coordinate保证后续渲染与状态一致。四、方法MethodsMarker 的方法需要通过组件ref调用是命令式控制标记行为的主要手段方法名参数说明showCallout显示该标记的 CallouthideCallout隐藏该标记的 CalloutredrawCallout触发标记 Callout 的重绘。对 iOS 上的 Google Maps 很有用。注意仅 iOS 支持animateMarkerToCoordinatecoordinate: LatLng, duration: number动画移动标记。注意仅 Android 支持redraw触发标记重绘。当标记内容有更新、且tracksViewChanges开销过大时使用4.1 源码视角命令的派发这些方法在 src/MapMarker.tsx 中实现内部会根据是否启用 Fabric 选择不同命令通道Fabric 走specs/NativeComponentMarker生成的FabricCommands旧架构走 MapMarkerNativeComponent.ts 中codegenNativeCommands定义的Commands支持showCallout、hideCallout、animateMarkerToCoordinate、setCoordinates、redraw。4.2 showCallout / hideCallout 实战Callouts.tsx 中通过 ref 调用方法控制 Callout 显隐show() { this.marker1.showCallout(); } hide() { this.marker1.hideCallout(); }ref 的挂载方式为ref{ref { this.marker1 ref; }}见 Callouts.tsx。4.3 animateMarkerToCoordinate 与 AnimatedRegionAnimatedMarkers.tsx 给出了双端动画的完整对比Android 上调用animateMarkerToCoordinate(newCoordinate, 500)其中 500 为毫秒时长源码默认值为 500见 src/MapMarker.tsxiOS 上则使用AnimatedRegion配合coordinate.timing({...newCoordinate, useNativeDriver: true}).start()if (Platform.OS android) { if (this.marker) { this.marker._component.animateMarkerToCoordinate(newCoordinate, 500); } } else { // useNativeDriver defaults to false if not passed explicitly coordinate.timing({...newCoordinate, useNativeDriver: true}).start(); }其中coordinate来自new AnimatedRegion({latitude: LATITUDE, longitude: LONGITUDE})见 AnimatedMarkers.tsxAnimatedRegion的实现位于 src/AnimatedRegion.ts。在 iOS 原生侧AIRMapMarker提供了animateToCoordinate:duration:接口见 ios/AirMaps/AIRMapMarker.mAndroid 侧则由MapMarker的 command 处理。该示例同时提示当前 Fabric Map 尚未支持该动画能力示例会先检测supported状态再决定是否展示。五、类型TypesMarker 相关回调与属性使用两个核心结构类型type LatLng { latitude: Number, longitude: Number, }type Point { x: Number, y: Number, }LatLng用于coordinate及所有事件返回的坐标Point用于anchor、calloutAnchor、centerOffset、calloutOffset等偏移/锚点属性以及事件返回的position。二者的 TypeScript 定义可在 src/sharedTypes.ts 中查看。六、自定义标记Children Components子组件在Marker /内部添加子组件后渲染出的内容会替换掉标记符号本身这是创建自定义标记、复用原生 SVG 的标准方式。示例Marker ... View style{{backgroundColor: red, padding: 10}} TextSF/Text /View /Marker更贴近真实场景的案例见 PriceMarker.tsx在 DraggableMarkers.tsx 中被作为子视图使用以及 ViewsAsMarkers.tsx大量视图型自定义标记。6.1 与 Callout 组合自定义气泡Marker 的子组件也可以是Callout /。当 Marker 存在Callout /子组件时title/description将不再用于默认气泡Callout 组件自身支持tooltip为 true 时完全由子视图自定义气泡外观默认 false 会绘制默认 tooltip 气泡窗口、alphaHitTest与onPress等属性详见 src/MapCallout.tsx。Callouts.tsx 展示了完整组合Marker 上设置calloutOffset{{x: -8, y: 28}}与calloutAnchor{{x: 0.5, y: 0.4}}微调气泡位置内部嵌套自定义CustomCallout气泡视图CustomCallout.tsx并在 iOS 上通过CalloutSubview实现气泡内可点击子视图点击后setState并调用redrawCallout()刷新内容。七、性能最佳实践tracksViewChanges 与 redraw文档特别强调大量渲染自定义标记时追踪子视图变化会带来明显的性能开销。因此展示大量自定义标记时考虑关闭tracksViewChanges标记内容需要更新时手动调用redraw方法。该建议在原生层有明确实现依据。Android 侧 MapMarker.java 中setTracksViewChanges的逻辑是shouldTrack tracksViewChanges hasCustomMarkerView marker ! null即只有在「开启了追踪 使用自定义标记视图 原生 marker 已就绪」时才进入追踪状态追踪期间会通过ViewChangesTracker见 android/src/main/java/com/rnmaps/maps/ViewChangesTracker.java持续监听子视图的 layout/draw 变化并刷新标记快照。这也解释了为什么纯图片/默认大头针标记不受该开关影响——hasCustomMarkerView为 false 时追踪不会激活。据此可给出量化建议// 大量自定义标记时 Marker coordinate{item.coordinate} tracksViewChanges{false} // 关闭追踪避免逐帧性能损耗 ref{ref (this.markerRefs[item.id] ref)} MyCustomView / /Marker // 内容变化时按需重绘 this.markerRefs[id].redraw();对于 iOS 上 Google Maps 的信息窗口同理建议在不需要动态更新时保持tracksInfoWindowChanges为 false。八、常见问题与平台差异速查pinColor在 Android 上不生效/变红Android 可用色板有限不支持的颜色会回退为红色issue #887需精确颜色请使用自定义图片或自定义视图。onPress冒泡差异Android 上 Marker 的onPress不会冒泡到 MapViewstopPropagation仅对 iOS 有意义issue #1132。anchorvscenterOffsetGoogle Maps 与 Android 使用归一化anchor[0,1]×[0,1]Apple Maps 使用 points 单位的centerOffset两者不可混用。calloutAnchorvscalloutOffset同上Google Maps / Android 用calloutAnchorApple Maps 用calloutOffset。动画能力差异animateMarkerToCoordinate仅 Android 支持iOS 需借助AnimatedRegion且 Fabric Map 下动画能力仍在演进参考 AnimatedMarkers.tsx 的 supported 检测。标记复用与keyiOS 上省略key或key不唯一会导致 Marker 被复用从而产生移动动画需要无动画的精确控制时请为每个 Marker 提供唯一key。更多可运行示例可查阅仓库 example/src/examples 目录下的DefaultMarkers.tsx、CustomMarkers.tsx、DraggableMarkers.tsx、Callouts.tsx、AnimatedMarkers.tsx、ViewsAsMarkers.tsx等文件Callout 的独立 API 文档见 docs/callout.md。赞分享移动开发UI组件前端【免费下载链接】react-native-mapsReact Native Mapview component for iOS Android项目地址https://gitcode.com/gh_mirrors/re/react-native-maps点击查看免费下载相关推荐Umi-OCR 实战指南免费离线 OCR 的三个落地路径与调参对照Umi OCR 实战指南免费离线 OCR 的三个落地路径与调参对照 Umi OCR 是一款免费、离线的 OCR 工具解压即用不联网、不注册截屏识别、批量OCR桌面应用如何用react-native-maps打造引人注目的Marker标记从基础到高级动画全攻略如何用react native maps打造引人注目的Marker标记从基础到高级动画全攻略 react native maps是React Native生态移动开发UI组件前端React Native Maps拖拽标记Draggable Marker实现与事件处理指南React Native Maps拖拽标记Draggable Marker实现与事件处理指南 想要在React Native应用中实现可拖拽的地图标记吗re移动开发UI组件前端上一篇should.js与Mocha完美结合构建专业的Node.js测试套件下一篇Electrode Subapp实战3个步骤实现大型应用的微前端拆分创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表