如何在React Native中通过Ref设置选中Marker并实现动画?
为选中的Marker添加动画效果的问题
我想实现点击Marker选中它,点击按钮时触发该选中Marker的动画。但目前点击Marker时跳动的不是目标标记,也无法切换选中的标记。尝试过把当前Marker存入state、点击时设置Ref(收到只读错误)、把markerRef传入handlePress替换.current都没成功。
问题原因
- 多个Marker共用同一个
markerRef,导致最后渲染的Marker会覆盖之前的Ref引用,动画总是作用在最后一个Marker上 - 没有维护选中Marker的状态,无法追踪当前选中的目标
修正后的代码
import React, { useRef, useState } from 'react'; import { View, StyleSheet, TouchableOpacity, Text } from 'react-native'; import MapView, { Marker } from 'react-native-maps'; import * as Animatable from 'react-native-animatable'; const MapWithMarkerAnimation = () => { // 用对象存储所有Marker的Ref,key为Marker的唯一标识 const markerRefs = useRef({}); // 维护当前选中的Marker标识 const [selectedMarkerId, setSelectedMarkerId] = useState(null); // 点击Marker时设置选中状态 const handleMarkerPress = (markerId) => { setSelectedMarkerId(markerId); }; // 触发选中Marker的动画 const handleAnimateButtonPress = () => { if (selectedMarkerId && markerRefs.current[selectedMarkerId]) { markerRefs.current[selectedMarkerId].bounce(800); } }; // 生成Marker的唯一标识,用坐标拼接确保唯一性 const getMarkerId = (coordinate) => { return `${coordinate.latitude}-${coordinate.longitude}`; }; return ( <View style={styles.container}> <MapView style={styles.map} initialRegion={{ latitude: 52.4194975, longitude: -1.5101260, latitudeDelta: 0.2, longitudeDelta: 0.2 }} > {[ { latitude: 52.4194975, longitude: -1.5101260 }, { latitude: 52.514825, longitude: -1.5101260 } ].map(coordinate => { const markerId = getMarkerId(coordinate); return ( <Marker key={markerId} coordinate={coordinate} onPress={() => handleMarkerPress(markerId)} > <Animatable.View ref={ref => markerRefs.current[markerId] = ref} animation="zoomIn" duration={1000} easing="ease-out" > <View style={[styles.marker, selectedMarkerId === markerId && styles.selectedMarker]} /> </Animatable.View> </Marker> ); })} </MapView> <TouchableOpacity style={styles.button} onPress={handleAnimateButtonPress}> <Text style={styles.buttonText}>Animate Marker</Text> </TouchableOpacity> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, map: { ...StyleSheet.absoluteFillObject, }, marker: { width: 20, height: 20, borderRadius: 10, backgroundColor: 'red', }, selectedMarker: { borderWidth: 2, borderColor: 'white', }, button: { backgroundColor: 'blue', paddingVertical: 10, paddingHorizontal: 20, borderRadius: 5, marginTop: 10, }, buttonText: { color: 'white', fontSize: 16, fontWeight: 'bold', }, }); export default MapWithMarkerAnimation;
关键修改点
- 改用
markerRefs对象存储所有Marker的Ref,每个Marker对应唯一ID,避免引用覆盖 - 添加
selectedMarkerId状态,明确追踪当前选中的Marker - 点击Marker时更新选中状态,同时给选中的Marker添加白色边框样式,方便视觉区分
- 点击动画按钮时,根据选中的ID找到对应Ref并触发动画
- 将Marker数据改为数组循环渲染,提升代码可维护性
内容的提问来源于stack exchange,提问作者JulesUK
相关产品推荐
相关产品推荐

