七、美化,使用样式类(设置style)
Making it look nice 让它看起来更漂亮
到目前为止,我们已经具有基本的导入、编辑和导出功能的要素编辑器。但我们还没有花时间尝试使要素看起来漂亮。在 OpenLayers 中创建矢量图层时,会获得一组默认样式。编辑交互操作(绘制和修改)也具有自己的默认样式。您可能已经注意到,在编辑过程中几何图形的描边会变粗。可以通过为矢量图层和编辑交互操作提供样式选项来控制此行为。
首先,我们将导入所需的构造函数:
/**
* 导入样式模块
* 该模块提供了用于定义要素样式的类。
*/
import {Style, Fill, Stroke} from 'ol/style';
-
Style: Style类是OpenLayers中用于定义图层样式的类,它可以包含一个或多个几何对象的样式规则。你可以设置填充颜色、描边颜色、图像图标等,以决定地图上的要素如何显示。
- Fill: Fill类用于设置几何对象内部的填充样式。你可以指定填充颜色,透明度等属性,比如
new Fill({color: '#ff0000'})
将创建一个红色填充。 - Stroke: Stroke类用于定义几何对象边缘的描边样式。你可以设置描边颜色、宽度以及线型等,例如
new Stroke({color: '#000', width: 3})
创建一个黑色、宽度为3的描边。
- Fill: Fill类用于设置几何对象内部的填充样式。你可以指定填充颜色,透明度等属性,比如
Static style 静态样式
如果我们想给所有的特征相同的样式,我们可以这样配置我们的矢量层:
const layer = new VectorLayer({
source: source,
style: new Style({
fill: new Fill({
color: 'red',
}),
stroke: new Stroke({
color: 'white',
}),
}),
});
也可以将 style 属性设置为样式数组:
import {Style, Fill, Stroke, Text} from 'ol/style';
// 定义两种样式
const style1 = new Style({
fill: new Fill({color: 'rgba(255, 0, 0, 1)'}),
stroke: new Stroke({color: 'rgba(0, 0, 0, 0.5)', width: 2}),
});
const style2 = new Style({
fill: new Fill({color: 'rgba(0, 0, 255, 0.2)'}),
stroke: new Stroke({color: 'rgba(0, 0, 0, 0.5)', width: 2}),
});
// 创建样式数组
const styles = [style1, style2];
// layer要渲染的矢量图层
layer.setStyle(styles);
定义了两种样式:style1和style2,每种样式有不同的填充色。然后,我们将这两个样式放入一个数组styles中,并将其设置为矢量图层的样式。OpenLayers会根据图层中要素的具体情况(如果有条件逻辑的话(看下面的动态样式))来应用这些样式。这里没有特定的条件判断逻辑,默认会应用第一个样式。
Dynamic style 动态样式
当您想要根据有关要素或当前视图分辨率的信息来决定如何渲染每个要素时,您可以使用样式函数配置矢量图层。每个渲染帧的每个功能都会调用此函数,因此如果您有很多功能并希望保持良好的渲染性能,那么编写一个高效的函数非常重要。
下面是一个示例,它使用两种样式之一来渲染要素,具体取决于“name”属性是以“A-M”还是“N-Z”开头。
const layer = new VectorLayer({
source: source,
style: function (feature, resolution) {
const name = feature.get('name').toUpperCase();
return name < 'N' ? style1 : style2; // 这里的样式用的上面的style1和style2
},
});
Styling based on geometry area 基于几何区域的样式
为了了解动态样式的工作原理,我们将创建一个样式函数,该函数根据几何区域渲染要素。为此,我们将使用 npm 上的 colormap
包。我们可以将其添加到我们的依赖项中,如下所示:
npm install colormap
现在,我们需要导入 colormap
包和 ol/sphere
来计算球面面积。
/**
* 导入colormap库,用于生成颜色映射。
* 导入ol/sphere中的getArea函数,用于计算地理区域的面积。
*/
import colormap from 'colormap';
import {getArea} from 'ol/sphere';
接下来我们将编写两个函数来根据几何图形的面积确定颜色:
const min = 1e8; // the smallest area
const max = 2e13; // the biggest area
const steps = 50;
const ramp = colormap({
colormap: 'blackbody', // 指定使用'blackbody'颜色映射
nshades: steps, // 设置颜色阶梯的数量
});
//将给定的值限制在指定的最小值和最大值之间。
function clamp(value, low, high) {
return Math.max(low, Math.min(value, high));
}
/**
* 根据给定的地理特征计算并返回一个颜色。
* 该颜色是基于特征的面积大小,在预定义的颜色梯度中进行选择。
*/
function getColor(feature) {
// 计算特征的面积
const area = getArea(feature.getGeometry());
// 根据面积计算一个标准化的值f,用于在颜色梯度中定位颜色
const f = Math.pow(clamp((area - min) / (max - min), 0, 1), 1 / 2);
// 根据f的值,计算在颜色梯度中的索引
const index = Math.round(f * (steps - 1));
// 返回对应索引的颜色
return ramp[index];
}
现在我们可以添加一个函数,根据几何区域创建具有填充颜色的样式。将此函数设置为矢量图层的 style
属性:
const layer = new VectorLayer({
source: source,
style: function (feature) {
return new Style({
fill: new Fill({
color: getColor(feature),// 使用getColor函数获取填充颜色
}),
stroke: new Stroke({
color: 'rgba(255,255,255,0.8)',
}),
});
},
});
可以看到不同大小的多边形颜色是不一样的。