作为一个刚开始学习 mapvthree 的小白,今天要学习地图投影了!听说这个系统可以控制地图的坐标系统,不同的投影方式有不同的效果!想想就好奇!
今天在文档里看到了"投影"这个词,一开始我还以为是投影仪那种投影,结果查了一下才知道,原来这是地图学里的概念!
文档说地图投影是:
我的理解:简单说就是把地球这个球面"展开"成平面的方法!就像把橘子皮剥下来摊平一样,不同的剥法会有不同的效果!
作为一个初学者,我一开始很困惑:为什么需要投影?直接用经纬度不行吗?
我的疑问:经纬度不是已经很准确了吗?为什么还要转换?
看了文档才知道:
我的理解:就像拍照一样,不同的角度拍出来的效果不一样,投影就是选择"拍照角度"!
文档说 mapvthree 支持多种投影方式,我数了数,主要有这几种:
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:3857', // Web 墨卡托投影(默认)
},
});我的理解:这是最常用的网络地图投影,也是引擎的默认投影。
我的发现:
我的想法:如果做普通的网络地图,用这个投影就够了!
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:4978', // ECEF 投影(3D 地球)
},
});我的理解:ECEF 是地心地固坐标系,是一个三维直角坐标系统。
我的发现:
我的想法:如果做 3D 地球效果,应该用这个投影!
我的尝试:
import * as mapvthree from '@baidumap/mapv-three';
const container = document.getElementById('container');
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:4978', // 3D 地球模式
center: [0, 0],
range: 30000000, // 很远的距离,能看到整个地球
},
});我的发现:地图变成了一个球体!可以旋转看整个地球,太酷了!
我的感受:这个投影真的很适合做 3D 地球效果!
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:4326', // WGS84 地理坐标系
},
});我的理解:WGS84 是最常用的地理坐标系统,使用经纬度表示位置。
我的发现:
我的想法:如果数据是经纬度格式,用这个投影比较方便!
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:32633', // UTM 33N 带
},
});我的理解:UTM 投影将地球分为 60 个等分带,每个带覆盖 6 度经度。
我的发现:
我的想法:如果做局部区域的地图,可以考虑用 UTM 投影!
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:4491', // 高斯克吕格六度带投影
},
});我的理解:高斯克吕格投影是一种等角投影,角度保持不变,适合进行测量和制图。
我的发现:
我的想法:如果做中国地区的地图,可以考虑用这个投影!
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:8857', // EqualEarth 投影
},
});我的理解:EqualEarth 投影是一种等面积投影,面积保持不变。
我的发现:
我的想法:如果要做面积相关的计算,可以用这个投影!
看到这么多投影类型后,我开始好奇:怎么设置投影?
文档说目标投影只能在引擎初始化时设置,之后不能修改!
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:4978', // 设置目标投影
},
});我的理解:投影必须在创建引擎时设置,创建后不能改。
我的尝试:
import * as mapvthree from '@baidumap/mapv-three';
const container = document.getElementById('container');
// 设置为 3D 地球模式
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:4978', // ECEF 投影
center: [0, 0],
range: 30000000,
},
});我的发现:设置后,地图的显示方式完全变了!
我的注意:投影设置后不能修改,所以要在初始化时就确定好!
看到可以设置投影后,我想:不同的投影会有什么不同的效果?
我试了几个不同的投影:
// Web 墨卡托投影(默认)
const engine1 = new mapvthree.Engine(container1, {
map: {
projection: 'EPSG:3857',
center: [0, 0],
range: 10000000,
},
});
// ECEF 投影(3D 地球)
const engine2 = new mapvthree.Engine(container2, {
map: {
projection: 'EPSG:4978',
center: [0, 0],
range: 30000000,
},
});我的发现:
EPSG:3857:平面地图,像普通的地图EPSG:4978:球体地图,像真实的地球我的感受:不同的投影真的有完全不同的视觉效果!
我的理解:投影决定了地图的"形状",选择合适的投影很重要!
看到可以设置目标投影后,我想:如果我的数据不是经纬度,怎么办?
文档说数据源可以设置自己的投影!
对于 GeoJSON 数据,可以在数据中声明 crs 信息:
const geojson = {
type: 'FeatureCollection',
crs: {
type: 'name',
properties: {
name: 'EPSG:3857', // 声明数据源的投影
},
},
features: [
// ... 数据
],
};
const dataSource = mapvthree.GeoJSONDataSource.fromGeoJSON(geojson);我的理解:在 GeoJSON 中声明 crs,引擎会自动识别并转换。
我的发现:引擎会自动将数据源的投影转换为目标投影!
我的想法:这样就不用手动转换坐标了,引擎会自动处理!
文档说 DataItem 也支持在属性字段设置 crs 信息。
我的理解:每个数据项都可以有自己的投影设置。
我的发现:这样就能处理混合投影的数据了!
看到数据源的投影后,我想:底图的投影怎么处理?
文档说底图的投影由 TileProvider 处理,大部分 TileProvider 内部都能自动处理投影转换!
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:4978', // 目标投影是 ECEF
provider: new mapvthree.BaiduVectorTileProvider(), // 底图 Provider
},
});我的理解:TileProvider 会自动处理底图的投影转换。
我的发现:不需要手动设置底图的投影,Provider 会自动处理!
我的想法:这样就很方便了,不用关心底图的投影问题!
学到这里,我开始想:不同的投影适合什么场景?
如果做普通的网络地图,用 Web 墨卡托投影:
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:3857', // Web 墨卡托投影(默认)
},
});我的想法:这是最常用的投影,适合大多数场景!
如果做 3D 地球效果,用 ECEF 投影:
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:4978', // ECEF 投影
center: [0, 0],
range: 30000000,
},
});我的想法:这个投影最适合做 3D 地球,效果最真实!
如果要做精确的空间计算,用 ECEF 投影:
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:4978', // ECEF 投影,精度高
},
});我的想法:ECEF 投影精度最高,适合做精确计算!
如果要做面积计算,用 EqualEarth 投影:
const engine = new mapvthree.Engine(container, {
map: {
projection: 'EPSG:8857', // EqualEarth 投影
},
});我的想法:这个投影面积比例准确,适合做面积相关的计算!
我想写一个完整的示例,展示不同投影的效果:
import * as mapvthree from '@baidumap/mapv-three';
// 创建多个容器展示不同投影
const container1 = document.getElementById('container1');
const container2 = document.getElementById('container2');
// Web 墨卡托投影(平面地图)
const engine1 = new mapvthree.Engine(container1, {
map: {
projection: 'EPSG:3857',
center: [116.404, 39.915],
range: 10000,
},
});
// ECEF 投影(3D 地球)
const engine2 = new mapvthree.Engine(container2, {
map: {
projection: 'EPSG:4978',
center: [116.404, 39.915],
range: 1000000,
},
});
// 添加一些测试点
const points = [
[116.404, 39.915], // 北京
[121.473, 31.230], // 上海
[113.264, 23.129], // 广州
];
const geojson = {
type: 'FeatureCollection',
features: points.map(coord => ({
type: 'Feature',
properties: {},
geometry: {
type: 'Point',
coordinates: coord,
},
})),
};
const dataSource = mapvthree.GeoJSONDataSource.fromGeoJSON(geojson);
// 在两个引擎中都添加点
const point1 = engine1.add(new mapvthree.SimplePoint({ size: 20 }));
point1.dataSource = dataSource;
const point2 = engine2.add(new mapvthree.SimplePoint({ size: 20 }));
point2.dataSource = dataSource;我的感受:写一个完整的示例,对比不同投影的效果,感觉很有成就感!
我的发现:
虽然代码还很简单,但是已经能展示不同投影的效果了!
作为一个初学者,我踩了不少坑,记录下来避免再犯:
原因:不知道投影只能在初始化时设置。
解决:在创建引擎时就确定好投影方式,之后不能修改。
原因:数据源的投影设置错误,导致显示位置不对。
解决:确保数据源的投影设置正确,或者在 GeoJSON 中正确声明 crs。
原因:不了解不同投影的特点,选择了不合适的投影。
解决:根据应用场景选择合适的投影:
原因:使用 Web 墨卡托投影显示高纬度地区。
解决:高纬度地区建议使用 ECEF 投影或其他适合的投影。
原因:数据投影和目标投影不一致,但没有正确设置。
解决:确保数据源的投影设置正确,引擎会自动转换。
经过这一天的学习,我掌握了:
map.projection 设置crs,引擎会自动转换TileProvider 自动处理我的感受:地图投影虽然概念有点抽象,但是用起来其实不难。关键是要理解不同投影的特点,然后根据应用场景选择合适的投影!
下一步计划:
学习笔记就到这里啦!作为一个初学者,我觉得地图投影虽然概念有点抽象,但是用起来其实不难。关键是要理解不同投影的特点,然后根据应用场景选择合适的投影!希望我的笔记能帮到其他初学者!大家一起加油!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。