常见问题
去掉地图中间的红色叉号
var map = new maptalks.Map("map", {
zoom: 1,
center: [0, 0],
centerCross: false,
});
map.config({
centerCross: true,
});
map.config({
centerCross: false,
});
强制限制地图的边界
地图设置了最大边界后并开启limitExtentOnMaxExtent
即可
WARNING
该特性要求 maptalks 版本>1.0.0-rc.33
var map = new maptalks.Map("map", {
center: [120, 31.498568],
zoom: 4,
limitExtentOnMaxExtent: true,
zoomControl: true,
});
map.on("click", (e) => {
// console.log(e);
});
const baseLayer = new maptalks.TileLayer("base", {
repeatWorld: false,
urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
subdomains: ["a", "b", "c", "d"],
attribution:
'© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a> ',
}).addTo(map);
var bbox = [
118.681640625, 30.929531859423406, 121.318359375, 32.06416211965538,
];
var bbox = [-180, -85, 180, 85];
map.setMaxExtent(bbox);
const layer = new maptalks.VectorLayer("layer").addTo(map);
const debugBBOX = bbox.map((v, index) => {
const offset = 0.01;
if (index < 2) {
return v + offset;
}
return v - offset;
});
const line = new maptalks.LineString(new maptalks.Extent(debugBBOX).toArray(), {
symbol: {
lineDasharray: [5, 5],
},
}).addTo(layer);
const polygon = new maptalks.Polygon([map.getMaxExtent().toArray()]);
baseLayer.setMask(polygon);
const point = new maptalks.Marker(map.getMaxExtent().getCenter()).addTo(layer);
多个地图之间进行同步
社区里有个插件 maptalks.mapsync 专门用来 控制多个地图之间的视角同步
计算两点之间的距离
map上提供了computeLength
方法了
const c1 = new maptalks.Coordinate(0, 0);
const c2 = new maptalks.Coordinate(1, 0);
const len = map.computeLength(c1, c2);
地图容器默认隐藏导致地图初始不能完成
初始化地图时不要将地图容器(dom)设置为不显示display=none
,因为地图初始化时需要读取地图容器的大小, 如果使用隐藏的dom容器会导致读取到的地图大小为0,因为地图内部要初始化canvas和webgl等, 如果大小为0可能导致webgl上下文初始化失败
WARNING
注意是地图初始化时,如果地图初始化完成了隐藏地图容器没有这种问题
要想隐藏容器可以通过其他方法:
- css visibility
- css zIndex
- 或者把地图容器移出当前视野外(margin top bottom 等)
怎样修改地图的背景?
地图容器根节点一般是个DIV元素,直接用CSS设置其背景即可
.map {
background: black;
}
高分屏上地图比较大导致地图非常卡?
- 地图的容器进行CSS缩放(scale)
.container {
width: 400px;
height: 200px;
/*https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform-origin*/
transform: scale(2, 2);
transform-origin: top left;
}
- 设置地图的 devicePixelRatio 配置项
- 具体例子 scale container for high resolution
WARNING
devicePixelRatio的值一般比CSS scale的倍数小,比如地图容器放大 4倍,devicePixelRatio可能设置为 2 倍,即在清晰图允许的情况下 devicePixelRatio值越小,性能越好,所以使用时不要盲目的设置 devicePixelRatio的值为很大的值,否则可能导致地图奔溃
扩大地图的缩放的最大级别
maptalks里地图默认最大到22
级别,如果你需要扩大到更大的层级,需要自定义地图的空间投影,把切图的参数(resolutions)调整到你需要的级别即可
var MAX_ZOOM = 28;
var spatialReference = {
projection: "EPSG:3857",
resolutions: (function () {
const resolutions = [];
const d = 2 * 6378137 * Math.PI;
for (let i = 0; i < MAX_ZOOM; i++) {
resolutions[i] = d / (256 * Math.pow(2, i));
}
return resolutions;
})(),
fullExtent: {
top: 6378137 * Math.PI,
left: -6378137 * Math.PI,
bottom: -6378137 * Math.PI,
right: 6378137 * Math.PI,
},
};
// const spatialReference4326 = {
// projection: "EPSG:4326",
// fullExtent: {
// top: 90,
// left: -180,
// bottom: -90,
// right: 180,
// },
// resolutions: (function () {
// const resolutions = [];
// for (let i = 0; i < MAX_ZOOM; i++) {
// resolutions[i] = 180 / (Math.pow(2, i) * 128);
// }
// return resolutions;
// })(),
// };
var map = new maptalks.Map("map", {
center: [-0.113049, 51.498568],
zoom: 14,
spatialReference: spatialReference,
baseLayer: new maptalks.TileLayer("base", {
maxAvailableZoom: 20,
urlTemplate:
"https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
subdomains: ["a", "b", "c", "d"],
attribution:
'© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>',
}),
layers: [new maptalks.VectorLayer("v")],
});
具体的例子Customize map's resolutions
地图添加了天空盒后,底图看不见了
maptalks里 地图的baseLayer
是最底下的图层,在地图里会第一个绘制baseLayer,而天空盒是在baselayer之后绘制的, 从而导致baselayer被天空盒盖住了,解决方式就是把baseLayer放到GroupGLLayaer
const baseLayer = new maptalks.TileLayer("base", {
urlTemplate:
"https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
subdomains: ["a", "b", "c", "d"],
spatialReference: {
projection: "EPSG:3857",
},
});
const groupLayer = new maptalks.GroupGLLayer("group", [baseLayer], {
sceneConfig: {
environment: {
enable: true,
mode: 1,
level: 0,
brightness: 0,
},
shadow: {
type: "esm",
enable: true,
quality: "high",
opacity: 0.11,
color: [0, 0, 0],
blurOffset: 1,
},
postProcess: {
enable: true,
antialias: {
enable: true,
taa: true,
jitterRatio: 0.25,
},
ssr: {
enable: true,
},
bloom: {
enable: true,
threshold: 0,
factor: 0.2,
radius: 0.105,
},
ssao: {
enable: true,
bias: 0.08,
radius: 0.08,
intensity: 1.5,
},
sharpen: {
enable: false,
factor: 0.2,
},
},
ground: {
enable: false,
renderPlugin: {
type: "fill",
},
symbol: {
polygonFill: [0.517647, 0.517647, 0.517647, 1],
},
},
},
});
groupLayer.addTo(map);
TIP
注意map里的baseLayer属性需要注释掉
var map = new maptalks.Map("map", {
center: [-0.113049, 51.498568],
zoom: 14,
// baseLayer: new maptalks.TileLayer('base', {
// urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
// subdomains: ["a","b","c","d"],
// attribution: '© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>'
// })
});
关于地图的baseLayer
地图里的baseLayer比较特殊,在地图的所有图层集合里其是第一个被绘制的图层,其特点有:
- baseLayer表示基础图层,一般用来作为底图参考
- baseLayer可以是任何图层,
TileLayer
,VectorLayer
,VectorTileLayer
等
WARNING
一般业务都是用TileLayer作为底图,但是这个不是绝对的,有业务决定,有的底图可能很简单,使用ImageLayer作为底图也是可能的 比如简单的一个地铁的应用,用ImageLayer来加载一个地图图片,上面叠加一些业务图层等
在地图的整个绘制过程中,baseLayer永远是第一个被绘制的图层,即使你把baseLayer的zIndex值设置的很大也不行的,其仍然是第一个被绘制
地图的baseLayer的设置主要方法有:
初始化地图设置了地图的
baseLayer
属性jsvar map = new maptalks.Map("map", { center: [-0.113049, 51.498568], zoom: 14, baseLayer: new maptalks.TileLayer("base", { urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png", subdomains: ["a", "b", "c", "d"], attribution: '© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>', }), });
通过地图的
setBaseLayer
方法设置
jsconst baseLayer = new maptalks.TileLayer("base", { urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png", subdomains: ["a", "b", "c", "d"], attribution: '© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>', }); map.setBaseLayer(layer);
如果你想维持图层的层级关系(zIndex):
- 不要将一个图层(一般是TileLayer)设置为baseLayer,直接把其加到地图上即可
var map = new maptalks.Map("map", {
center: [-0.113049, 51.498568],
zoom: 14,
});
const baseLayer = new maptalks.TileLayer("base", {
urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
subdomains: ["a", "b", "c", "d"],
attribution:
'© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>',
});
baseLayer.addTo(map);
- 如果你想维持地图上图层的三维关系,请把他们加入的
GroupGLLayer
里即可:
const baseLayer = new maptalks.TileLayer("base", {
urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
subdomains: ["a", "b", "c", "d"],
attribution:
'© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>',
});
const groupLayer = new maptalks.GroupGLLayer("group", [baseLayer], {});
groupLayer.addTo(map);
TIP
如果你的业务是强三维的,GroupGLLayer是必须的,把你的所有图层往GroupGLLayer放就是了
WARNING
注意VectorLayer不能被加入到GroupGLLayer
鼠标进入地图后报跨域警告
maptalks的数据渲染是canvas或者webgl,因为浏览器限制的关系canvas/webgl等是不允许跨域的,例如如下方法等:
canvas.toDataURL();
canvas.getImageData();
一般都是因为你的图标,图片,纹理图片等是跨域导致的
解决方法:
- 资源本地化
- 服务端允许跨域
- 服务代理等
导出地图为图片
地图自带了toDataURL
方法了
map.toDataURL({ save: true });
WARNING
地图自带的方法只能导出地图canvas
画布上的内容,地图上的dom元素时不能被导出的,像弹窗啊,比例尺控件啊等
导出地图上的所有内容
这时我们需要借助社区的一些库
- html2canvas
- html-to-image
- 其他开源库等
const size = map.getSize();
const { width, height } = size;
htmlToImage
.toBlob(map.getContainer(), { width, height: height + 100 })
.then(function (blob) {
saveFile(blob);
});
WARNING
外联的css样式需要开启跨域
<link
rel="stylesheet"
href="./../assets/lib/maptalks/dist/maptalks.css"
crossorigin="anonymous"
/>
将地图和其他dom元素一起导出
新建一个dom节点,然后把地图和你想要导出的dom一起放进来,然后直接导出这个节点
<div class="container" id="container">
<div class="panel">
<button>hello</button>
<button>hello</button>
<button>hello</button>
<button>hello</button>
<button>hello</button>
<button>hello</button>
<button>hello</button>
<button>hello</button>
</div>
<div id="map"></div>
<div>
<table>
<thead>
<tr>
<th colspan="2">The table header</th>
</tr>
</thead>
<tbody>
<tr>
<td>The table body</td>
<td>with two columns</td>
</tr>
</tbody>
</table>
</div>
</div>
htmlToImage
.toBlob(document.getElementById("container"), {})
.then(function (blob) {
saveFile(blob);
});
VectorLayer渲染的图形远处悬浮
可以调节下地图的maxVisualPitch
// default map object
var map = new maptalks.Map("mapDiv", {
maxVisualPitch: 65,
center: [117.131072, 31.83786],
});
地图进行强制重绘
一般情况下地图的重绘和图层重绘是有引擎内部控制的,是不需要手动控制的,如果你真的有这个需求你可以:
- 图层重绘:
const renderer = layer.getRenderer();
if (renderer && renderer.setToRedraw) {
renderer.setToRedraw();
}
- 地图重绘:
const renderer = map.getRenderer();
if (renderer && renderer.setToRedraw) {
renderer.setToRedraw();
}
WARNING
注意在maptalks内绘制全部是异步的,其完全是游戏渲染的那一套流程,即每帧渲染一次,不是html那种改变html后立马 重绘的,是么意思:
当你设置了图层或者地图重绘后,是不能立马拿到绘制的结果的,必须等到下一帧绘制结束后才能拿到绘制的结果的
地图提供了帧绘制的事件的:
- framestart
- frameend
map.on("framestart frameend", (e) => {
//do some things if need
});