几何计算示例
本示例展示如何使用 expo-gaode-map 提供的几何计算功能,包括距离计算、面积计算和点位关系判断。
基础用法
typescript
import React, { useState } from 'react';
import { View, Text, Button, ScrollView, StyleSheet } from 'react-native';
import {ExpoGaodeMapModule} from 'expo-gaode-map';
export default function GeometryUtilsExample() {
const [results, setResults] = useState<string[]>([]);
const runCalculations = async () => {
const newResults: string[] = [];
try {
// 1. 计算两点之间的距离
const distance = await ExpoGaodeMapModule.distanceBetweenCoordinates(
{ latitude: 39.90923, longitude: 116.397428 }, // 天安门
{ latitude: 39.916527, longitude: 116.397545 } // 故宫
);
newResults.push(`天安门到故宫的距离: ${distance.toFixed(2)} 米`);
// 2. 计算多边形面积
const polygon = [
{ latitude: 39.923, longitude: 116.391 },
{ latitude: 39.923, longitude: 116.424 },
{ latitude: 39.886, longitude: 116.424 },
{ latitude: 39.886, longitude: 116.391 },
];
const polygonArea = await ExpoGaodeMapModule.calculatePolygonArea(polygon);
newResults.push(`多边形面积: ${(polygonArea / 1000000).toFixed(2)} 平方公里`);
// 3. 计算矩形面积
const rectArea = await ExpoGaodeMapModule.calculateRectangleArea(
{ latitude: 39.886, longitude: 116.391 },
{ latitude: 39.923, longitude: 116.424 }
);
newResults.push(`矩形面积: ${(rectArea / 1000000).toFixed(2)} 平方公里`);
// 4. 判断点是否在多边形内
const testPoint = { latitude: 39.9, longitude: 116.4 };
const isInPolygon = await ExpoGaodeMapModule.isPointInPolygon(testPoint, polygon);
newResults.push(`点 (39.9, 116.4) 是否在多边形内: ${isInPolygon ? '是' : '否'}`);
// 5. 判断点是否在圆内
const center = { latitude: 39.90923, longitude: 116.397428 };
const isInCircle = await ExpoGaodeMapModule.isPointInCircle(
testPoint,
center,
10000 // 10公里
);
newResults.push(`点是否在10公里圆内: ${isInCircle ? '是' : '否'}`);
setResults(newResults);
} catch (error) {
console.error('计算失败:', error);
newResults.push(`错误: ${error.message}`);
setResults(newResults);
}
};
return (
<View style={styles.container}>
<Button title="运行几何计算" onPress={runCalculations} />
<ScrollView style={styles.resultsContainer}>
{results.map((result, index) => (
<Text key={index} style={styles.resultText}>
• {result}
</Text>
))}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
},
resultsContainer: {
marginTop: 20,
},
resultText: {
fontSize: 14,
marginVertical: 5,
lineHeight: 20,
},
});实际应用场景
1. 附近商家距离显示
typescript
async function calculateNearbyShops(userLocation: LatLng, shops: Shop[]) {
const shopsWithDistance = await Promise.all(
shops.map(async (shop) => {
const distance = await ExpoGaodeMapModule.distanceBetweenCoordinates(
userLocation,
shop.location
);
return {
...shop,
distance,
distanceText: distance < 1000
? `${Math.round(distance)}米`
: `${(distance / 1000).toFixed(1)}公里`
};
})
);
// 按距离排序
return shopsWithDistance.sort((a, b) => a.distance - b.distance);
}2. 地理围栏(进入/离开区域检测)
typescript
function useGeofencing(location: LatLng, area: LatLng[]) {
const [isInside, setIsInside] = useState(false);
useEffect(() => {
const checkLocation = async () => {
const inside = await ExpoGaodeMapModule.isPointInPolygon(
location,
area
);
if (inside !== isInside) {
setIsInside(inside);
// 触发进入或离开事件
if (inside) {
console.log('用户进入了区域');
} else {
console.log('用户离开了区域');
}
}
};
checkLocation();
}, [location]);
return isInside;
}3. 土地面积测量工具
typescript
function LandAreaCalculator() {
const [points, setPoints] = useState<LatLng[]>([]);
const [area, setArea] = useState<number>(0);
const addPoint = (point: LatLng) => {
setPoints([...points, point]);
};
const calculateArea = async () => {
if (points.length < 3) {
alert('至少需要3个点才能计算面积');
return;
}
const calculatedArea = await ExpoGaodeMapModule.calculatePolygonArea(points);
setArea(calculatedArea);
};
const clearPoints = () => {
setPoints([]);
setArea(0);
};
return (
<View>
<Text>已标记 {points.length} 个点</Text>
{area > 0 && (
<Text>
面积: {(area / 1000000).toFixed(2)} 平方公里
({(area / 10000).toFixed(2)} 公顷)
</Text>
)}
<Button title="计算面积" onPress={calculateArea} />
<Button title="清除" onPress={clearPoints} />
</View>
);
}4. 配送范围判断
typescript
async function isInDeliveryRange(
userLocation: LatLng,
shopLocation: LatLng,
maxDistance: number
): Promise<boolean> {
const isInRange = await ExpoGaodeMapModule.isPointInCircle(
userLocation,
shopLocation,
maxDistance
);
if (!isInRange) {
const distance = await ExpoGaodeMapModule.distanceBetweenCoordinates(
userLocation,
shopLocation
);
console.log(`超出配送范围 ${(distance / 1000).toFixed(1)}km,最大配送距离 ${(maxDistance / 1000).toFixed(1)}km`);
}
return isInRange;
}性能优化建议
- 批量计算: 对于多个点的距离计算,考虑使用 Promise.all 并行处理
- 结果缓存: 对于固定区域的判断结果可以缓存,避免重复计算
- 精度控制: 根据实际需求选择合适的精度,避免过度计算
typescript
// 批量距离计算示例
async function batchCalculateDistances(
origin: LatLng,
destinations: LatLng[]
) {
return Promise.all(
destinations.map(dest =>
ExpoGaodeMapModule.distanceBetweenCoordinates(origin, dest)
)
);
}
// 结果缓存示例
const areaCache = new Map<string, boolean>();
async function isInAreaCached(
point: LatLng,
polygon: LatLng[]
): Promise<boolean> {
const key = `${point.latitude},${point.longitude}`;
if (areaCache.has(key)) {
return areaCache.get(key)!;
}
const result = await ExpoGaodeMapModule.isPointInPolygon(point, polygon);
areaCache.set(key, result);
return result;
}