网站搜索

typescript - Openlayers:LineString 上的渐变发光


我有一层渲染 LineStrings,并且正在尝试将发光效果应用到这些线条上。我创建的样式使用自定义渲染器来创建一个沿每个线段垂直的渐变描边:

const glow_style = new Style({
  renderer: (_coords, state) => {
    const ctx = state.context;
    const coords = _coords as Coordinate[];
    ctx.lineWidth = 25;
    for (let i = 1; i < coords.length; i++) {
      const start = coords[i - 1];
      const end = coords[i];
      const [grd_start, grd_end] = getPerpendicularPoints(start, end, ctx.lineWidth);
      const grd = ctx.createLinearGradient(grd_start[0], grd_start[1], grd_end[0], grd_end[1]);
      grd.addColorStop(0, '#ffffff00');
      grd.addColorStop(0.5, 'white');
      grd.addColorStop(1, '#ffffff00');
      ctx.strokeStyle = grd;
      ctx.beginPath();
      ctx.moveTo(start[0], start[1]);
      ctx.lineTo(end[0], end[1]);
      ctx.stroke();
    }
  }
});

这种样式适用于完全的直线,但在拐角处会失效,因为渐变在各线段之间无法很好地连接。如果 ctx.lineCap 保持为 butt,渐变在拐角处是不连续的。如果设置为 round,线段会接触,但由于重叠,渐变会变得不连续。下面是每种情况的示例:

我有哪些选项可以在整个 LineString 上创建平滑的渐变?

答案#1

将整个折线渲染出来,而不将其分段,通过绘制宽度递减的线条会更简单。为了获得平滑的渐变,每条线的透明度应定义为剩余透明度的比例。甚至可以作为 OpenLayers 样式数组来实现:

var steps = 13;
var styles = [];
for (var i = 0; i < steps; i++) {
    styles.push(
        new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: [255, 255, 255, 1/(steps - i)],
                width: (steps-i)*2 - 1
            })
        })
    );
}