OpenLayers v5绘制渐变圆形时如何展示动态半径文本?
OpenLayers v5 自定义圆形渐变样式显示文本解决方案
问题原因
- 当你给
ol.style.Style配置自定义renderer属性时,会完全覆盖OpenLayers的默认样式渲染流程,你额外配置的ol.style.Text不会被自动渲染,所有绘制逻辑需要自行在renderer中实现,或者拆分样式配置。 - 你在renderer中写的
ctx.textStyle、ctx.text不是原生Canvas 2D上下文的合法API,无法完成文本绘制。
解决方案
推荐两种实现方式,均可满足渐变圆形+动态半径文本展示的需求:
方案1:拆分样式为数组(推荐,无需自行实现文本渲染逻辑)
OpenLayers的style配置支持传入样式数组,多个样式会依次独立渲染,互不影响。你可以把渐变圆形、文本拆成两个独立样式:
// 1. 定义样式函数,支持动态读取feature的半径属性 const stylex = (feature) => { const radius = feature.get('radius') || 0; return [ // 第一个样式:专门渲染渐变圆形 new ol.style.Style({ renderer(coordinates, state) { const [[x, y], [x1, y1]] = coordinates; const ctx = state.context; const dx = x1 - x; const dy = y1 - y; const radius = Math.sqrt(dx * dx + dy * dy); const innerRadius = 0; const outerRadius = radius * 1.4; const gradient = ctx.createRadialGradient( x, y, innerRadius, x, y, outerRadius ); gradient.addColorStop(0, 'rgba(255,0,0,0)'); gradient.addColorStop(0.6, 'rgba(255,0,0,0.2)'); gradient.addColorStop(1, 'rgba(255,0,0,0.8)'); ctx.beginPath(); ctx.arc(x, y, radius, 0, 2 * Math.PI, true); ctx.fillStyle = gradient; ctx.fill(); ctx.beginPath(); ctx.arc(x, y, radius, 0, 2 * Math.PI, true); ctx.strokeStyle = 'rgba(255,0,0,1)'; ctx.stroke(); } }), // 第二个样式:专门渲染文本,走OpenLayers默认渲染逻辑 new ol.style.Style({ text: new ol.style.Text({ font: 'Normal 16px Arial', text: `${radius} m`, fill: new ol.style.Fill({ color: '#fff' }), stroke: new ol.style.Stroke({ color: '#000000', width: 3 }), offsetY: 0 }) }) ] }; // 2. drawend事件中把半径存入feature属性 draw.on('drawend',function(f){ const radius = f.feature.getGeometry().getRadius().toFixed(2); f.feature.set('radius', radius); console.log("radius:"+ radius +" m"); });
方案2:直接在自定义renderer中实现文本绘制
如果不想拆分样式,也可以直接用原生Canvas API在renderer末尾添加文本绘制逻辑:
renderer(coordinates, state) { // 原有渐变圆形绘制逻辑不变 const [[x, y], [x1, y1]] = coordinates; const ctx = state.context; const dx = x1 - x; const dy = y1 - y; const radius = Math.sqrt(dx * dx + dy * dy); const innerRadius = 0; const outerRadius = radius * 1.4; const gradient = ctx.createRadialGradient( x, y, innerRadius, x, y, outerRadius ); gradient.addColorStop(0, 'rgba(255,0,0,0)'); gradient.addColorStop(0.6, 'rgba(255,0,0,0.2)'); gradient.addColorStop(1, 'rgba(255,0,0,0.8)'); ctx.beginPath(); ctx.arc(x, y, radius, 0, 2 * Math.PI, true); ctx.fillStyle = gradient; ctx.fill(); ctx.beginPath(); ctx.arc(x, y, radius, 0, 2 * Math.PI, true); ctx.strokeStyle = 'rgba(255,0,0,1)'; ctx.stroke(); // 新增文本绘制逻辑 ctx.font = 'Normal 16px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; // 先描边保证文本清晰度 ctx.strokeStyle = '#000'; ctx.lineWidth = 3; ctx.strokeText(`${radius.toFixed(2)} m`, x, y); // 再填充文本颜色 ctx.fillStyle = '#fff'; ctx.fillText(`${radius.toFixed(2)} m`, x, y); }
内容的提问来源于stack exchange,提问作者user3565914
相关产品推荐
相关产品推荐

