Similar to different vertical and horizontal scaling I think it can only be done in canvas at present (an old pull request for scaling https://github.com/openlayers/openlayers/pull/6100 now conflicts with more recent changes). In this function a negative scale would flip in the image:
function createIconStyle(url, scaleX, scaleY, styleOptions, iconOptions) {
var style = new ol.style.Style(styleOptions);
var img = new Image();
img.crossOrigin = 'anonymous';
img.onload = function(){
var x = Math.round(img.width * scaleX);
var y = Math.round(img.height * scaleY);
var canvas = document.createElement('canvas');
canvas.width = Math.abs(x);
canvas.height = Math.abs(y);
var ctx = canvas.getContext('2d');
ctx.translate(Math.abs(Math.min(0,x)), Math.abs(Math.min(0,y)));
ctx.scale(x<0 ? -1 : 1, y<0 ? -1 : 1);
ctx.drawImage(img, 0, 0, Math.abs(x), Math.abs(y));
var dataUrl = canvas.toDataURL();
canvas.remove();
iconOptions = iconOptions || {};
iconOptions.src = dataUrl;
style.setImage(new ol.style.Icon(iconOptions));
};
img.src = url;
return style;
}
The function could be used to create styles for layers and features and predefined styles for use in a style function, but won't work correctly if called directly in a style function (except for creating cached styles) due to the asynchronous load of the image. The canvas operation means the image must be same origin or CORS enabled. e.g.
feature.setStyle( createIconStyle('url', -1, 1, {}, {rotation: angle}) );
If instead of passing the url you passed pre-loaded image object the method could be used in a style function:
function createIconStyleFromImage(img, scaleX, scaleY, styleOptions, iconOptions) {
var style = new ol.style.Style(styleOptions);
var x = Math.round(img.width * scaleX);
var y = Math.round(img.height * scaleY);
var canvas = document.createElement('canvas');
canvas.width = Math.abs(x);
canvas.height = Math.abs(y);
var ctx = canvas.getContext('2d');
ctx.translate(Math.abs(Math.min(0,x)), Math.abs(Math.min(0,y)));
ctx.scale(x<0 ? -1 : 1, y<0 ? -1 : 1);
ctx.drawImage(img, 0, 0, Math.abs(x), Math.abs(y));
var dataUrl = canvas.toDataURL();
canvas.remove();
iconOptions = iconOptions || {};
iconOptions.src = dataUrl;
style.setImage(new ol.style.Icon(iconOptions));
return style;
}
Example of caching flipped images
var imageCache = {};
function createIconStyle(url, scaleX, scaleY, styleOptions, iconOptions) {
var style = new ol.style.Style(styleOptions);
iconOptions = iconOptions || {};
var dataUrl = imageCache[url + ',' + scaleX + ',' + scaleY];
if (dataUrl) {
iconOptions.src = dataUrl;
style.setImage(new ol.style.Icon(iconOptions));
} else {
var img = document.createElement('img');
img.crossOrigin = 'anonymous';
img.onload = function() {
var x = Math.round(img.width * scaleX);
var y = Math.round(img.height * scaleY);
var canvas = document.createElement('canvas');
canvas.width = Math.abs(x);
canvas.height = Math.abs(y);
var ctx = canvas.getContext('2d');
ctx.translate(Math.abs(Math.min(0,x)), Math.abs(Math.min(0,y)));
ctx.scale(x<0 ? -1 : 1, y<0 ? -1 : 1);
ctx.drawImage(img, 0, 0, Math.abs(x), Math.abs(y));
var dataUrl = canvas.toDataURL();
imageCache[url + ',' + scaleX + ',' + scaleY] = dataUrl;
canvas.remove();
iconOptions.src = dataUrl;
style.setImage(new ol.style.Icon(iconOptions));
// maybe force an immediate re-render?
//map.renderSync();
};
img.src = url;
}
return style;
}