openlayers聚合效果效果下,渲染自定义样式,动态展示
先上效果
openlayers 聚合自定义渲染加动作效果
这个动态效果想过很久,本来只是一个静态的,但是甲方爸爸不满意,那就得做动态,这个是最终的效果。首先openlayer官网上我没有找见我需要的相关的动态效果方法,我这里首先是一个聚合效果,然后聚合点中需要加入一个动态效果。
如何实现聚合效果openlayers官网上也有,那我就不多说了,然后是一个点渲染效果,在这里依旧参考openlayers官网上的效果用canvas渲染。
canvas渲染代码
style = new Style({
renderer(coordinates, state) {
const ctx = state.context;
const gradientOutside = ctx.createRadialGradient(coordinates[0], coordinates[1], radius * 0.6 , coordinates[0], coordinates[1], radius * 1 );
gradientOutside.addColorStop(0, 'rgba(255, 255, 255, 0.5)');
gradientOutside.addColorStop(0.6, 'rgba(255, 255, 255, 0.3)');
gradientOutside.addColorStop(0.7, 'rgba(255, 255, 255, 0.2)');
gradientOutside.addColorStop(0.9, "rgba(255, 255, 255, 0.1)");
gradientOutside.addColorStop(1, "rgba(255, 255, 255, 0)");
//绘制放射性渐变圆
ctx.beginPath();// 创建一个新路径方法
ctx.arc(coordinates[0], coordinates[1], radius * 1, 0, 2 * Math.PI, true); // 圆圈路径
ctx.fillStyle = gradientOutside; // 描述颜色
ctx.fill();// 填充当前样式
ctx.globalCompositeOperation = 'source-over';
const gradientInside = ctx.createRadialGradient(coordinates[0], coordinates[1], radius * 0.6 , coordinates[0], coordinates[1], radius * 0.8 );
gradientInside.addColorStop(0, 'rgba(36, 137, 201, 0.6)');
gradientInside.addColorStop(1, "rgba(36, 137, 201, 0.6)");
//绘制放射性渐变圆
ctx.beginPath();// 创建一个新路径方法
ctx.arc(coordinates[0], coordinates[1], radius * 0.8, 0, 2 * Math.PI, true); // 圆圈路径
ctx.fillStyle = gradientInside; // 描述颜色
ctx.fill();// 填充当前样式
ctx.globalCompositeOperation = 'source-over';
const gradient = ctx.createRadialGradient(coordinates[0], coordinates[1], radius * 0.5 , coordinates[0], coordinates[1], radius * 0.7 );
gradient.addColorStop(0, 'rgba(44, 138, 202, 0.3)');
gradient.addColorStop(0.3, 'rgba(44, 138, 202, 0.3)');
gradient.addColorStop(0.5, 'rgba(44, 138, 202, 0.5)');
gradient.addColorStop(0.7, "rgba(44, 138, 202, 0.7)");
gradient.addColorStop(1, "rgba(44, 138, 202, 1)");
//绘制放射性渐变圆
ctx.beginPath();// 创建一个新路径方法
ctx.arc(coordinates[0], coordinates[1], radius * 0.7, 0, 2 * Math.PI, true); // 圆圈路径
ctx.fillStyle = gradient; // 描述颜色
ctx.fill();// 填充当前样式
ctx.globalCompositeOperation = 'source-over';
if ( radius > 29 ) {
ctx.beginPath();
ctx.font = font;
ctx.fillStyle = '#fff'
ctx.fillText(size, coordinates[0] - (radius/2.2) , coordinates[1]+ (radius/4.5) );
} else if ( radius > 19 ) {
ctx.beginPath();
ctx.font = font;
ctx.fillStyle = '#fff'
ctx.fillText(size, coordinates[0] - (radius/1.8) , coordinates[1]+ (radius/3.5) );
} else {
ctx.beginPath();
ctx.font = font;
ctx.fillStyle = '#fff'
ctx.fillText(size, coordinates[0] - (radius/2.7) , coordinates[1]+ (radius/2.3) );
}
},
})
动作效果
动作效果我想了很久,首先还是查看mdn文档,mdn上的例子大概是要用requestAnimationFrame () 方法,实际上方法是对的,但是我这里因为渲染聚合点,所以有多个返回的style,如果要调用渲染方法的话势必会造成无限递归,虽然渲染点位的增多,程序就卡死的越快,而且无法消除之前的递归事件,之后我在openlayer官网找到例子使用layer.on(‘postrender’, animate);方法做动态效果,一次渲染所有点,保证只有一个递归函数存在在页面中,减少浏览器性能消耗。
function animate (event) {
i += 0.015
let cos = Math.abs(Math.cos(i))
let vectorContext = getVectorContext(event);
let features = event.target.getSource().getFeatures();
features.map( ( item ) => {
if ( item.values_.features.length === 1 ) {
return;
}
let style = new Style({
image: new CircleStyle({
radius: item.get('radius') * ( 0.8 + 0.3 * cos ),
stroke: new Stroke({
color: `rgba(255, 255, 255, ${ 1 - cos } )`,
width: 1 + cos ,
}),
}),
zIndex: 700
})
vectorContext.setStyle( style );
vectorContext.drawGeometry( item.getGeometry() );
});
map.render();
}