React Native如何实现基于距离的用户筛选 类似Tinder半径过滤效果
距离筛选功能实现方案
核心原理
通过Haversine公式计算两个经纬度坐标点在地球球面上的实际距离,再和你设定的筛选半径对比,只保留符合距离要求的用户。
1. 先实现距离计算工具函数
你可以直接复用下面的方法,输入两个坐标的经纬度,返回两点之间的距离(单位:公里):
// 计算两点经纬度之间的距离,返回单位公里 const calculateDistance = (lat1, lon1, lat2, lon2) => { const R = 6371 // 地球半径,单位公里 const dLat = (lat2 - lat1) * Math.PI / 180 const dLon = (lon2 - lon1) * Math.PI / 180 const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon/2) * Math.sin(dLon/2) const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)) const distance = R * c return distance }
注意:请根据你实际的坐标字段名调整参数,比如你存储的坐标字段是user.lat/user.lng就对应修改取值逻辑
2. 调整你的业务代码
你可以直接在现有filter逻辑里新增距离判断规则,也可以把筛选半径放到state里支持用户自定义调整:
调整后完整示例代码:
// 先把上面的calculateDistance函数放在组件内或者工具文件里引入 // 可以在state里新增筛选半径,默认50公里,也可以做滑动条让用户自定义 state = { users: [], errorMessage: '', maxDistance: 50, // 最大筛选半径,单位公里 // 你已经拿到的当前用户坐标 currentPosition: { latitude: xxx, longitude: xxx } } getUsers = async() => { try{ const response = await api.get('/auth/list') const { users } = response.data console.log({users}) this.setState({ users }) }catch(response){ this.setState({ errorMessage: response.data.error }) console.log(response.data.error) } } async componentDidMount(){ this.getUsers() } render() { const { currentPosition, maxDistance } = this.state return( <View> {!!this.state.errorMessage && <Text>{ this.state.errorMessage }</Text>} {this.state.users.filter(user => { // 原有专业筛选条件 const isSpecialityMatch = user.speciality === 'Dermatologista' // 新增距离筛选条件 const distance = calculateDistance( currentPosition.latitude, currentPosition.longitude, user.latitude, // 替换成你用户数据里的纬度字段名 user.longitude // 替换成你用户数据里的经度字段名 ) const isDistanceMatch = distance <= maxDistance return isSpecialityMatch && isDistanceMatch }).map(user => ( <View key={user._id} style={{marginTop: 15, alignItems: 'center'}}> <Text style={{fontWeight: 'bold', fontSize:20}}>{user.title}</Text> <Text>{user.speciality}</Text> <Button title = 'View Profile' onPress ={() => this.props.navigation.navigate('Profile', { name: user._id })}/> </View> ))} </View> ) } }
优化建议
如果你的平台用户量较大,建议把距离筛选逻辑放到后端实现:
- 前端调用接口时把当前用户坐标、筛选半径作为参数传给后端
- 后端直接计算过滤后返回符合条件的用户列表
- 可以减少不必要的数据传输,也避免全量用户数据暴露到前端
内容的提问来源于stack exchange,提问作者Paulo Avila
相关产品推荐
相关产品推荐

