问题
CONTEXT
I have a vector composed of multi polygons, each one of these have a unique class and I set a style related to it. I currently doing this way:
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;
}
}
});
The styleArea()
is a function that returns an OpenLayers style:
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;
}
PROBLEM
Now I trying to create a function that returns an OL's style, but this time as a pattern image. After the help in this question made by myself I was able to apply the pattern style to a vector, but now I need to apply in a multi polygon vector. If I try the same way as before, all the other styles are rewrited. I tried different solutions and some of them generate the error:
TypeError: "style.getImage is not a function"
which I think is because the image isn't load yet when it is applied to the style. I believe that if I just declare the vector, then modify the style based on the filtered classes the problem can be solved (don't figured out how to yet), but I really want to return the fill partern as an OL style from a function, so that I can use later on other vectors.
- Ionic version: 5.4.9
- OL version: 6.1.1
My latest attempt:
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;
}
This way I don't receive any errors and I can see the pattern image loaded in Dev Tools, but it wasn't applied to the vector style.
回答1:
The style function must return the style, not the onload function. Due to the asynchronous loading you will need a style cache solution similar to this question Scaling the icon-image size to an absolute value You might also want to pass the feature to your stylePattern function to force a rerender when the pattern is set, so the function might look something like this
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;
}
来源:https://stackoverflow.com/questions/59274588/how-to-apply-a-pattern-fill-style-to-a-multipolygon-that-returns-multiple-styles