自定义样式
SDK 支持灵活的地图样式自定义功能,可以通过多种方式修改地图外观,包括图层样式覆盖、主题切换等。
样式覆盖
使用 setStyle 方法
setStyle 方法允许你覆盖特定图层的样式:
javascript
sdk.setStyle({
// 单个图层样式
"airport-label": {
paint: {
"text-color": "#ff0000",
"text-size": 14,
},
},
// 多个图层样式
"airline": {
paint: {
"line-color": "#00ff00",
"line-width": 2,
},
},
});数组类型图层样式
对于数组类型的图层(如 amm、controlled、restricted、airspace、airline),需要使用数组格式:
javascript
sdk.setStyle({
amm: [
{
"amm-layer-1": {
paint: {
"fill-color": "#ff0000",
},
},
},
{
"amm-layer-2": {
paint: {
"fill-color": "#00ff00",
},
},
},
],
controlled: [
{
"controlled-layer-1": {
paint: {
"fill-color": "#0000ff",
},
},
},
],
});使用 Theme 类
SDK 内部使用 Theme 类来管理样式,你也可以直接使用:
javascript
// Theme 类会自动处理样式应用
const theme = sdk.theme;
// 应用样式
theme.setStyle({
"airport-label": {
paint: {
"text-color": "#ff0000",
},
},
});图层样式更新
更新单个图层样式
javascript
sdk.updateLayerStyle("airport-label", {
paint: {
"text-color": "#ff0000",
"text-size": 16,
},
layout: {
"text-field": ["get", "name"],
"text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
},
});批量更新图层样式
javascript
// 更新多个图层
const styles = {
"airport-label": {
paint: { "text-color": "#ff0000" },
},
"airline": {
paint: { "line-color": "#00ff00" },
},
};
Object.entries(styles).forEach(([layerId, style]) => {
sdk.updateLayerStyle(layerId, style);
});动态样式切换
根据缩放级别切换样式
javascript
sdk.on("zoom", () => {
const zoom = sdk.getZoom();
if (zoom < 10) {
// 低缩放级别:简化样式
sdk.setStyle({
"airport-label": {
layout: {
visibility: "none",
},
},
});
} else {
// 高缩放级别:显示详细样式
sdk.setStyle({
"airport-label": {
layout: {
visibility: "visible",
},
paint: {
"text-size": 14,
},
},
});
}
});根据时间切换样式(夜间模式)
javascript
function toggleNightMode(isNight) {
if (isNight) {
sdk.setStyle({
"airport-label": {
paint: {
"text-color": "#ffffff",
},
},
"airline": {
paint: {
"line-color": "#ffff00",
},
},
});
} else {
sdk.setStyle({
"airport-label": {
paint: {
"text-color": "#000000",
},
},
"airline": {
paint: {
"line-color": "#0000ff",
},
},
});
}
}
// 根据时间自动切换
const hour = new Date().getHours();
toggleNightMode(hour >= 18 || hour < 6);主题配置
使用预定义主题
SDK 提供了预定义的主题样式文件:
javascript
// 加载暗色主题
const darkTheme = await fetch("/styles/dark.json").then(r => r.json());
sdk.setMapStyle(darkTheme);
// 加载亮色主题
const lightTheme = await fetch("/styles/light.json").then(r => r.json());
sdk.setMapStyle(lightTheme);自定义主题配置
创建自定义主题配置文件:
json
{
"airport-label": {
"paint": {
"text-color": "#ff0000",
"text-size": 14
}
},
"airline": {
"paint": {
"line-color": "#00ff00",
"line-width": 2
}
},
"amm": [
{
"amm-layer-1": {
"paint": {
"fill-color": "#0000ff"
}
}
}
]
}加载自定义主题:
javascript
async function loadCustomTheme(themePath) {
const theme = await fetch(themePath).then(r => r.json());
sdk.setStyle(theme);
}
loadCustomTheme("/styles/custom-theme.json");样式属性
Paint 属性
paint 属性控制图层的视觉外观:
javascript
sdk.setStyle({
"airport-label": {
paint: {
// 文本颜色
"text-color": "#ff0000",
// 文本大小
"text-size": 14,
// 文本描边颜色
"text-halo-color": "#ffffff",
// 文本描边宽度
"text-halo-width": 2,
},
},
"airline": {
paint: {
// 线条颜色
"line-color": "#00ff00",
// 线条宽度
"line-width": 2,
// 线条透明度
"line-opacity": 0.8,
// 虚线样式
"line-dasharray": [2, 2],
},
},
});Layout 属性
layout 属性控制图层的布局和可见性:
javascript
sdk.setStyle({
"airport-label": {
layout: {
// 可见性
visibility: "visible", // "visible" | "none"
// 文本字段
"text-field": ["get", "name"],
// 文本字体
"text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
// 文本锚点
"text-anchor": "center",
// 文本偏移
"text-offset": [0, 1],
},
},
});样式表达式
SDK 支持 MapBox 样式表达式,可以实现动态样式:
javascript
sdk.setStyle({
"airport-label": {
paint: {
// 根据属性值设置颜色
"text-color": [
"case",
["==", ["get", "type"], "civil"],
"#0000ff", // 民用机场:蓝色
"#ff0000", // 军用机场:红色
],
// 根据缩放级别设置大小
"text-size": [
"interpolate",
["linear"],
["zoom"],
10, 12, // 缩放级别 10 时大小为 12
15, 16, // 缩放级别 15 时大小为 16
],
},
},
});完整示例
javascript
let sdk;
async function initMap() {
sdk = new navMap.MapSDK({
container: "map",
center: [116.39, 39.9],
zoom: 10,
});
sdk.on("loadComplete", () => {
setupCustomStyles();
});
}
function setupCustomStyles() {
// 1. 基础样式覆盖
sdk.setStyle({
"airport-label": {
paint: {
"text-color": "#ff0000",
"text-size": 14,
},
},
});
// 2. 动态样式切换
sdk.on("zoom", () => {
const zoom = sdk.getZoom();
sdk.setStyle({
"airport-label": {
paint: {
"text-size": zoom < 12 ? 12 : 16,
},
},
});
});
// 3. 主题切换按钮
document.getElementById("dark-theme-btn").addEventListener("click", () => {
loadTheme("/styles/dark.json");
});
document.getElementById("light-theme-btn").addEventListener("click", () => {
loadTheme("/styles/light.json");
});
}
async function loadTheme(themePath) {
const theme = await fetch(themePath).then(r => r.json());
sdk.setStyle(theme);
}
initMap();注意事项
- 图层ID:确保使用的图层ID正确,错误的ID会被忽略
- 样式时机:在地图
loadComplete后再应用样式 - 性能考虑:频繁的样式更新可能影响性能,考虑批量更新
- 样式优先级:后应用的样式会覆盖先应用的样式
- 数组图层:对于
amm、controlled等数组类型图层,必须使用数组格式
