经纬志
首页 / OpenLayers / 教程

矢量图层与样式

先看结论

矢量部分是 OpenLayers 相对轻量地图库的主要优势: 几何体、要素、数据源、图层四层分离,样式可以是常量,也可以随缩放级别和属性动态计算。

最后验证 2026-11-03 · OpenLayers 10.3.1 · 更新 2026-10-27 · 引用本文

四层结构

层级类作用
图层ol.layer.Vector控制可见性、透明度、叠放顺序
数据源ol.source.Vector持有要素集合,负责增删和范围计算
要素ol.Feature几何体加属性,一条业务记录
几何ol.geom.Point 等实际坐标,决定画在哪

要素上的属性用 get / set 读写,没有固定表结构:

var feature = new ol.Feature({
  geometry: new ol.geom.Point(ol.proj.fromLonLat([116.404, 39.915])),
  name: '王府井',
  level: 'high'
});

feature.get('name');        // '王府井'
feature.set('level', 'low');

三种设置样式的方式

第一种,给要素单独设置,适合少量重点要素:

feature.setStyle(new ol.style.Style({
  image: new ol.style.Circle({
    radius: 6,
    fill: new ol.style.Fill({ color: '#1f5fd0' }),
    stroke: new ol.style.Stroke({ color: '#fff', width: 2 })
  })
}));

第二种,给图层设置样式函数,适合按属性分类。函数返回数组时同一个要素可以叠加多层符号:

var styleFunction = function (feature, resolution) {
  var isKey = feature.get('level') === 'high';

  return [
    new ol.style.Style({
      image: new ol.style.Circle({
        radius: isKey ? 8 : 5,
        fill: new ol.style.Fill({ color: isKey ? '#d0453a' : '#1f5fd0' })
      })
    }),
    new ol.style.Style({
      text: new ol.style.Text({
        text: feature.get('name'),
        offsetY: -16,
        font: '500 12px sans-serif',
        fill: new ol.style.Fill({ color: '#16181d' }),
        stroke: new ol.style.Stroke({ color: '#fff', width: 3 })
      })
    })
  ];
};

var layer = new ol.layer.Vector({
  source: source,
  style: styleFunction
});

第三种,在 ol.source.Vector 上设置,对该数据源派生的所有图层生效。 用得多的是前两种,第三种适合多个图层共用一套符号。

性能提醒:样式函数在每次重绘、每个要素上都会被调用, 里面不要做 DOM 操作或网络请求。需要缓存时按属性值预先建好 ol.style.Style 对象,函数里只做查表。

按分辨率分级显示

样式函数的第二个参数是当前分辨率,用它控制“放大后才显示标注”这类规则:

var labelStyle = new ol.style.Style({
  text: new ol.style.Text({ text: '标注', font: '12px sans-serif' })
});

var styleFunction = function (feature, resolution) {
  var base = new ol.style.Style({
    image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: '#1f5fd0' }) })
  });

  // 分辨率小于 20 米/像素,大约相当于 14 级以上
  return resolution < 20 ? [base, labelStyle] : base;
};

几何类型

类坐标结构样式字段
ol.geom.Point[x, y]image
ol.geom.LineString[[x, y], ...]stroke
ol.geom.Polygon[[[x, y], ...]]fill + stroke
ol.geom.MultiPolygon多一层数组同上

多边形注意外环和内环的区别:外环按逆时针给出, 内环(洞)按顺时针,数组第一个是外环。

var polygon = new ol.geom.Polygon([[
  ol.proj.fromLonLat([116.35, 39.93]),
  ol.proj.fromLonLat([116.45, 39.93]),
  ol.proj.fromLonLat([116.45, 39.88]),
  ol.proj.fromLonLat([116.35, 39.88]),
  ol.proj.fromLonLat([116.35, 39.93])
]]);

修改样式后为什么没变化

用 feature.setStyle() 改单个要素会立即重绘。 但如果样式来自函数或图层,属性变了不会自动触发重绘, 需要显式通知图层:

feature.set('level', 'high');   // 属性已改,画面未变
layer.changed();                // 触发重新应用样式函数

批量新增要素时用 source.addFeatures(features) 一次加入, 比循环 addFeature 少很多次重绘。

文字标注的常见处理

  • 给 ol.style.Text 配白色描边,深色底图上才看得清。
  • 标注互相压盖时,图层开启 declutter: true,由渲染器自动避让。
  • overflow: true 允许文字超出几何体范围,点位密集时更整齐。
  • 标注内容为空字符串时整个 text 样式不渲染,可以用它做条件开关。
var layer = new ol.layer.Vector({
  source: source,
  declutter: true,
  style: styleFunction
});

要素数量很大时(超过几千个点),普通矢量图层会明显卡顿。 可换成 ol.layer.Heatmap、ol.source.Cluster 聚合, 或改用 WebGL 渲染的 ol.layer.WebGLPoints。

引用本文

经纬志(2026)。《矢量图层与样式》。https://www.jingweizhi.com/openlayers/tutorial/vector-style.html(访问日期 2026-11-03)。