样式函数漏了 return,一半要素不画
按属性给不同颜色的点,结果只有一类点显示,其余全部消失,控制台还报了一个读属性失败的错误。
现象
图层里 800 个要素,只有 status 为 alarm 的 120 个能显示, 其余按条件走到另一个分支后消失。控制台报:
Uncaught TypeError: Cannot read properties of undefined (reading 'getType')
at executeDeclutter (VectorLayer.js:1268)
原因
style 函数必须返回一个 ol.style.Style、
样式数组或 null。分支里只写了条件赋值、没有 return,
函数返回 undefined,渲染器拿到空值后既不能绘制也无法判断,
在开启 declutter 时直接抛出类型错误。
null 是合法的“不渲染”信号,undefined 不是。
两者看起来一样,行为完全不同。
排查过程
把样式函数单独抽出来,用几个典型要素手动调用,看返回值:
var styleFn = layer.getStyleFunction();
features.slice(0, 5).forEach(function (f) {
var s = styleFn(f, map.getView().getResolution());
console.log(f.get('status'), s && s.length, s);
});
// alarm 1
// normal undefined ← 问题所在
解决方案
每个分支都明确返回。需要“不显示”时返回 null,不要什么都不写:
var alarmStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 8,
fill: new ol.style.Fill({ color: '#e03131' }),
stroke: new ol.style.Stroke({ color: '#ffffff', width: 1 })
})
});
var normalStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({ color: '#1c7ed6' })
})
});
var hiddenStyle = null;
function styleFn(feature) {
var status = feature.get('status');
if (status === 'alarm') return alarmStyle;
if (status === 'normal') return normalStyle;
return hiddenStyle;
}
var layer = new ol.layer.Vector({
source: source,
style: styleFn,
declutter: true
});
样式对象提前建好、循环外复用,不要在每个要素回调里 new ol.style.Style。
要素数量大时,这会让内存与 GC 压力成倍增长:
// 错误:每个要素每次渲染都新建
// style: function (f) { return new ol.style.Style({ ... }); }
// 正确:样式在模块级创建一次
var sharedStyle = new ol.style.Style({
stroke: new ol.style.Stroke({ color: '#2b8a3e', width: 2 })
});
function lineStyle(feature) {
var width = feature.get('lanes') >= 4 ? 4 : 2;
sharedStyle.getStroke().setWidth(width);
return sharedStyle;
}
验证
所有要素都按状态显示,数量与数据源一致。
控制台不再出现 reading 'getType'。
在 map.getFeaturesAtPixel 中能命中原本“消失”的要素。
返回值三选一:Style、Style[]、null。
写样式函数时把这三个当成函数签名的一部分,能避免大部分“部分要素不显示”的问题。
经纬志(2026)。《样式函数漏了 return,一半要素不画》。https://www.jingweizhi.com/cookbook/ol-style-function-undefined.html(访问日期 2026-11-03)。