如何在ThreeJS球体上实现可交互自定义的国家区域映射?
解决ThreeJS地球国家区域绘制的经纬度转Canvas坐标问题
核心逻辑
你要实现的是把球面经纬度映射到Canvas平面坐标,用最基础的等矩形投影即可(和地球纹理的常用投影匹配),步骤如下:
1. 经纬度转Canvas坐标的公式
假设Canvas宽为canvasWidth、高为canvasHeight:
- 经度(范围-180~180)转Canvas X坐标:
const x = (lon + 180) / 360 * canvasWidth; - 纬度(范围-90~90)转Canvas Y坐标(Canvas Y轴从上到下,需反转纬度方向):
const y = (90 - lat) / 180 * canvasHeight;
2. 处理GeoJSON并绘制Canvas
以下是完整可运行的代码示例,包含加载数据、遍历国家多边形、自定义颜色绘制:
// 1. 创建Canvas(建议用2的幂次尺寸,ThreeJS纹理优化友好) const canvasWidth = 2048; const canvasHeight = 1024; const canvas = document.createElement('canvas'); canvas.width = canvasWidth; canvas.height = canvasHeight; const ctx = canvas.getContext('2d'); // 2. 遍历GeoJSON中的国家要素(假设已获取到geoJson对象) geoJson.features.forEach(feature => { // 过滤非国家要素 if (feature.properties.type !== 'country') return; // 自定义颜色:给德国设红色,其他国家设深灰 ctx.fillStyle = feature.properties.name === 'Germany' ? '#ff4444' : '#555555'; ctx.strokeStyle = '#333333'; ctx.lineWidth = 1; // 兼容Polygon和MultiPolygon类型(带岛屿的国家是MultiPolygon) const polygons = feature.geometry.type === 'MultiPolygon' ? feature.geometry.coordinates : [feature.geometry.coordinates]; // 绘制每个多边形的外环和内环 polygons.forEach(polygon => { polygon.forEach(ring => { ctx.beginPath(); ring.forEach(([lon, lat], idx) => { const x = (lon + 180) / 360 * canvasWidth; const y = (90 - lat) / 180 * canvasHeight; idx === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y); }); ctx.closePath(); ctx.fill(); ctx.stroke(); }); }); });
3. 将Canvas纹理贴到ThreeJS球体上
把生成的Canvas转换成ThreeJS纹理,替换现有球体的材质:
// 创建Canvas纹理并标记更新 const canvasTexture = new THREE.CanvasTexture(canvas); canvasTexture.needsUpdate = true; // 绑定到球体材质(假设你的球体实例是sphereMesh) sphereMesh.material.map = canvasTexture; sphereMesh.material.needsUpdate = true;
重要细节提示
- Canvas尺寸必须用2的幂次(如512、1024、2048),避免ThreeJS自动拉伸导致模糊。
- GeoJSON坐标顺序是
[经度, 纬度],不要搞反。 - 部分国家是MultiPolygon结构(包含主岛和小岛),必须遍历所有子多边形才能完整绘制。
内容的提问来源于stack exchange,提问作者Linus Grosser
相关产品推荐
相关产品推荐

