Как применить стиль заливки узором к мультиполигону, который возвращает несколько стилей

КОНТЕКСТ

У меня есть вектор, состоящий из нескольких полигонов, каждый из которых имеет уникальный класс, и я установил связанный с ним стиль. Сейчас я делаю так:

let multiPolyVector = new VectorLayer({
    source: new VectorSource ({
        format: new GeoJSON({dataProjection: 'EPSG:31982'}),
        url: 'assets/geojson/randomVector.geojson'
    }),
    style: (feature) => {
        let class = feature.get("CLASS");
        switch(class) {
            case "CLASS1":
                return this.styleArea('rgba(240, 240, 240, 1)'); // 
            break;
            case "CLASS2":
                return this.styleArea('rgba(115, 115, 240, 1)'); 
            break;
            case "CLASS3":
                return this.styleArea('rgba(168, 168, 0, 1)'); // 
            break;
            case "CLASS4":
                return this.stylePoint('rgba(255, 255, 115, 1)'); // 
            break;
        }
    }
});

styleArea() - это функция, которая возвращает стиль OpenLayers:

styleArea(insideColor:string, exteriorColor:string=insideColor, exteriorWidth=2){
    let area = new Style({
        stroke: new Stroke({
            color: exteriorColor,
            width: exteriorWidth
        }),
            fill: new Fill({
            color: insideColor
        })
    });
    return area;
}

ПРОБЛЕМА

Теперь я пытаюсь создать функцию, которая возвращает стиль OL, но на этот раз как изображение шаблона. После помощи в этот вопрос, сделанный мной. Мне удалось применить стиль узора к вектору, но теперь мне нужно применить его к вектору с несколькими полигонами. Если я попробую так же, как и раньше, все остальные стили будут переписаны. Я пробовал разные решения, и некоторые из них выдают ошибку:

TypeError: «style.getImage не является функцией»

что, я думаю, связано с тем, что изображение еще не загружено, когда оно применяется к стилю. Я считаю, что если я просто объявлю вектор, а затем изменю стиль на основе отфильтрованных классов, проблема может быть решена (пока не понял, как это сделать), но я действительно хочу вернуть элемент заливки как стиль OL из функция, так что я могу использовать позже для других векторов.

  • Ионная версия: 5.4.9
  • Версия OL: 6.1.1

Моя последняя попытка:

stylePattern(pattern:string) {
    console.log("Function Fired");
    let patternSrc = "assets/images/patterns/" + pattern; // The pattern passed is the name of the PNG file
    let ctx = document.createElement('canvas').getContext('2d');
    let image = new Image();
    let createdPattern = ctx.createPattern(image, 'repeat');

    image.onload = () => {
        return new Style({
            fill: new Fill({
                color: createdPattern
            })
        });
    };
    image.src = patternSrc;             
}

Таким образом, я не получаю никаких ошибок и вижу изображение шаблона, загруженное в Dev Tools, но оно не было применено к векторному стилю.


person leonardofmed    schedule 10.12.2019    source источник


Ответы (1)


Функция стиля должна возвращать стиль, а не функция загрузки. Из-за асинхронной загрузки вам понадобится решение для кеширования стилей, подобное этому вопросу Масштабирование размера изображения значка до абсолютного значения Вы также можете передать эту функцию в свою функцию stylePattern, чтобы принудительно выполнить повторную визуализацию при установке шаблона, чтобы функция могла выглядеть примерно так

let styleCache = {};

stylePattern(pattern:string, feature) {
    console.log("Function Fired");
    let style = styleCache[pattern];
    if (!style) {
      let ctx = document.createElement('canvas').getContext('2d');
      let image = new Image();
      style = new Style({
          fill: new Fill({
            color: 'transparent'
          })
        });
      styleCache[pattern] = style;
      image.onload = () => {
        let createdPattern = ctx.createPattern(image, 'repeat');
        style.getFill().setColor(createdPattern);
        feature.changed();  // force a refresh or just wait until next render?
      }
      let patternSrc = "assets/images/patterns/" + pattern; // The pattern passed is the name of the PNG file
      image.src = patternSrc;
    }
    return style;
}
person Mike    schedule 10.12.2019