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?


person Ace    schedule 03.02.2020    source источник
comment
Перпендикулярные точки необходимо настроить так, чтобы они были истинными точками пересечения внутри и снаружи углов, как в stackoverflow.com/questions/57421223/   -  person Mike    schedule 03.02.2020
comment
Я не вижу, как регулировка перпендикулярных точек может помочь. Не нарушит ли какая-либо корректировка выравнивание градиента со сплошной линией?   -  person Ace    schedule 04.02.2020
comment
Этот код предназначался для параллельных линий. Теперь я вижу, что это не подходит для одной линии с градиентом.   -  person Mike    schedule 04.02.2020


Ответы (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
            })
        })
    );
}
person Mike    schedule 04.02.2020
comment
Ты снова сделал это, Майк. Спасибо за эту альтернативную точку зрения. - person Ace; 04.02.2020