Skip to content

Commit

Permalink
Remove ol/style/Icon's imgSize property
Browse files Browse the repository at this point in the history
  • Loading branch information
ahocevar committed Aug 30, 2023
1 parent db0acde commit 54fae09
Show file tree
Hide file tree
Showing 15 changed files with 136 additions and 150 deletions.
8 changes: 8 additions & 0 deletions changelog/upgrade-notes.md
Expand Up @@ -69,6 +69,14 @@ const staticOptions = {
```
Try to get rid of such an unintended use, or replace the `imageSize` option with an extent calculation like the above.

##### Removal of `ol/style/Icon`'s `imgSize` property

The `imgSize` property is no longer needed. If you had it configured, simply remove it.

##### Removal of the `icon-img-size` flat style property

This property is no longer needed and can simply be removed.

##### Change of the symbol style format in `ol/layer/WebGLPointsLayer`

The `WebGLPointsLayer` class used to rely on a custom style format that was made specifically for this layer and which looked like this:
Expand Down
1 change: 0 additions & 1 deletion examples/animated-gif.js
Expand Up @@ -43,7 +43,6 @@ gif.frames(
new Style({
image: new Icon({
img: ctx.canvas,
imgSize: [frame.width, frame.height],
opacity: 0.8,
}),
})
Expand Down
1 change: 0 additions & 1 deletion examples/earthquake-custom-symbol.js
Expand Up @@ -48,7 +48,6 @@ const styleFunction = function (feature) {
style = new Style({
image: new Icon({
img: canvas,
imgSize: [size, size],
rotation: 1.2,
}),
});
Expand Down
4 changes: 2 additions & 2 deletions src/ol/render/canvas/ImageBuilder.js
Expand Up @@ -16,13 +16,13 @@ class CanvasImageBuilder extends CanvasBuilder {

/**
* @private
* @type {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement}
* @type {import('../../DataTile.js').ImageLike}
*/
this.hitDetectionImage_ = null;

/**
* @private
* @type {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement}
* @type {import('../../DataTile.js').ImageLike}
*/
this.image_ = null;

Expand Down
2 changes: 1 addition & 1 deletion src/ol/render/canvas/Immediate.js
Expand Up @@ -142,7 +142,7 @@ class CanvasImmediateRenderer extends VectorContext {

/**
* @private
* @type {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement}
* @type {import('../../DataTile.js').ImageLike}
*/
this.image_ = null;

Expand Down
1 change: 0 additions & 1 deletion src/ol/render/canvas/hitdetect.js
Expand Up @@ -101,7 +101,6 @@ export function createHitDetectionImageData(
style.setImage(
new Icon({
img: img,
imgSize: imgSize,
anchor: image.getAnchor(),
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
Expand Down
70 changes: 27 additions & 43 deletions src/ol/style/Icon.js
Expand Up @@ -35,11 +35,7 @@ import {getUid} from '../util.js';
* @property {null|string} [crossOrigin] The `crossOrigin` attribute for loaded images. Note that you must provide a
* `crossOrigin` value if you want to access pixel data with the Canvas renderer.
* See https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image for more detail.
* @property {HTMLImageElement|HTMLCanvasElement} [img] Image object for the icon. If the `src` option is not provided then the
* provided image must already be loaded. And in that case, it is required
* to provide the size of the image, with the `imgSize` option.
* @property {import("../size.js").Size} [imgSize] Image size in pixels. Only required if `img` is set and `src` is not.
* The provided `imgSize` needs to match the actual size of the image.
* @property {HTMLImageElement|HTMLCanvasElement|ImageBitmap} [img] Image object for the icon.
* @property {Array<number>} [displacement=[0, 0]] Displacement of the icon in pixels.
* Positive values will shift the icon right and up.
* @property {number} [opacity=1] Opacity of the icon.
Expand Down Expand Up @@ -161,36 +157,20 @@ class Icon extends ImageStyle {
this.crossOrigin_ =
options.crossOrigin !== undefined ? options.crossOrigin : null;

/**
* @type {HTMLImageElement|HTMLCanvasElement}
*/
const image = options.img !== undefined ? options.img : null;

/**
* @private
* @type {import("../size.js").Size|undefined}
*/
this.imgSize_ = options.imgSize;

/**
* @type {string|undefined}
*/
let src = options.src;
let cacheKey = options.src;

assert(
!(src !== undefined && image),
!(cacheKey !== undefined && image),
'`image` and `src` cannot be provided at the same time'
);
assert(
!image || (image && this.imgSize_),
'`imgSize` must be set when `image` is provided'
);

if ((src === undefined || src.length === 0) && image) {
src = /** @type {HTMLImageElement} */ (image).src || getUid(image);
if ((cacheKey === undefined || cacheKey.length === 0) && image) {
cacheKey = /** @type {HTMLImageElement} */ (image).src || getUid(image);
}
assert(
src !== undefined && src.length > 0,
cacheKey !== undefined && cacheKey.length > 0,
'A defined and non-empty `src` or `image` must be provided'
);

Expand All @@ -202,11 +182,20 @@ class Icon extends ImageStyle {
'`width` or `height` cannot be provided together with `scale`'
);

/**
* @type {import("../ImageState.js").default}
*/
const imageState =
options.src !== undefined ? ImageState.IDLE : ImageState.LOADED;
let imageState;
if (options.src !== undefined) {
imageState = ImageState.IDLE;
} else if (image !== undefined) {
if (image instanceof HTMLImageElement) {
if (image.complete) {
imageState = image.src ? ImageState.LOADED : ImageState.IDLE;
} else {
imageState = ImageState.LOADING;
}
} else {
imageState = ImageState.LOADED;
}
}

/**
* @private
Expand All @@ -220,8 +209,7 @@ class Icon extends ImageStyle {
*/
this.iconImage_ = getIconImage(
image,
/** @type {string} */ (src),
this.imgSize_ !== undefined ? this.imgSize_ : null,
/** @type {string} */ (cacheKey),
this.crossOrigin_,
imageState,
this.color_
Expand Down Expand Up @@ -260,13 +248,10 @@ class Icon extends ImageStyle {
[width, height] = options.size;
} else {
const image = this.getImage(1);
if (
image instanceof HTMLCanvasElement ||
(image.src && image.complete)
) {
if (image.width && image.height) {
width = image.width;
height = image.height;
} else {
} else if (image instanceof HTMLImageElement) {
this.initialOptions_ = options;
const onload = () => {
this.unlistenImageChange(onload);
Expand Down Expand Up @@ -309,7 +294,7 @@ class Icon extends ImageStyle {
scale = this.getScale();
scale = Array.isArray(scale) ? scale.slice() : scale;
}
const clone = new Icon({
return new Icon({
anchor: this.anchor_.slice(),
anchorOrigin: this.anchorOrigin_,
anchorXUnits: this.anchorXUnits_,
Expand All @@ -319,7 +304,6 @@ class Icon extends ImageStyle {
? this.color_.slice()
: this.color_ || undefined,
crossOrigin: this.crossOrigin_,
imgSize: this.imgSize_,
offset: this.offset_.slice(),
offsetOrigin: this.offsetOrigin_,
opacity: this.getOpacity(),
Expand All @@ -333,7 +317,6 @@ class Icon extends ImageStyle {
displacement: this.getDisplacement().slice(),
declutterMode: this.getDeclutterMode(),
});
return clone;
}

/**
Expand Down Expand Up @@ -419,7 +402,8 @@ class Icon extends ImageStyle {
/**
* Get the image icon.
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLImageElement|HTMLCanvasElement} Image or Canvas element.
* @return {HTMLImageElement|HTMLCanvasElement|ImageBitmap} Image or Canvas element. If the Icon
* style was configured with `src` or with a not let loaded `img`, an `ImageBitmap` will be returned.
* @api
*/
getImage(pixelRatio) {
Expand Down Expand Up @@ -451,7 +435,7 @@ class Icon extends ImageStyle {
}

/**
* @return {HTMLImageElement|HTMLCanvasElement} Image element.
* @return {HTMLImageElement|HTMLCanvasElement|ImageBitmap} Image element.
*/
getHitDetectionImage() {
return this.iconImage_.getHitDetectionImage();
Expand Down
88 changes: 38 additions & 50 deletions src/ol/style/IconImage.js
Expand Up @@ -7,8 +7,8 @@ import EventType from '../events/EventType.js';
import ImageState from '../ImageState.js';
import {asString} from '../color.js';
import {createCanvasContext2D} from '../dom.js';
import {decodeFallback} from '../Image.js';
import {shared as iconImageCache} from './IconImageCache.js';
import {listenImage} from '../Image.js';

/**
* @type {CanvasRenderingContext2D}
Expand All @@ -17,25 +17,24 @@ let taintedTestContext = null;

class IconImage extends EventTarget {
/**
* @param {HTMLImageElement|HTMLCanvasElement} image Image.
* @param {HTMLImageElement|HTMLCanvasElement|ImageBitmap} image Image.
* @param {string|undefined} src Src.
* @param {import("../size.js").Size} size Size.
* @param {?string} crossOrigin Cross origin.
* @param {import("../ImageState.js").default} imageState Image state.
* @param {import("../color.js").Color} color Color.
*/
constructor(image, src, size, crossOrigin, imageState, color) {
constructor(image, src, crossOrigin, imageState, color) {
super();

/**
* @private
* @type {HTMLImageElement|HTMLCanvasElement}
* @type {HTMLImageElement|HTMLCanvasElement|ImageBitmap}
*/
this.hitDetectionImage_ = null;

/**
* @private
* @type {HTMLImageElement|HTMLCanvasElement}
* @type {HTMLImageElement|HTMLCanvasElement|ImageBitmap}
*/
this.image_ = image;

Expand All @@ -57,23 +56,18 @@ class IconImage extends EventTarget {
*/
this.color_ = color;

/**
* @private
* @type {?function():void}
*/
this.unlisten_ = null;

/**
* @private
* @type {import("../ImageState.js").default}
*/
this.imageState_ = imageState;
this.imageState_ = imageState === undefined ? ImageState.IDLE : imageState;

/**
* @private
* @type {import("../size.js").Size}
* @type {import("../size.js").Size|null}
*/
this.size_ = size;
this.size_ =
image && image.width && image.height ? [image.width, image.height] : null;

/**
* @private
Expand Down Expand Up @@ -132,7 +126,6 @@ class IconImage extends EventTarget {
*/
handleImageError_() {
this.imageState_ = ImageState.ERROR;
this.unlistenImage_();
this.dispatchChangeEvent_();
}

Expand All @@ -141,19 +134,13 @@ class IconImage extends EventTarget {
*/
handleImageLoad_() {
this.imageState_ = ImageState.LOADED;
if (this.size_) {
this.image_.width = this.size_[0];
this.image_.height = this.size_[1];
} else {
this.size_ = [this.image_.width, this.image_.height];
}
this.unlistenImage_();
this.size_ = [this.image_.width, this.image_.height];
this.dispatchChangeEvent_();
}

/**
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLImageElement|HTMLCanvasElement} Image or Canvas element.
* @return {HTMLImageElement|HTMLCanvasElement|ImageBitmap} Image or Canvas element or image bitmap.
*/
getImage(pixelRatio) {
if (!this.image_) {
Expand All @@ -180,7 +167,7 @@ class IconImage extends EventTarget {
}

/**
* @return {HTMLImageElement|HTMLCanvasElement} Image element.
* @return {HTMLImageElement|HTMLCanvasElement|ImageBitmap} Image element.
*/
getHitDetectionImage() {
if (!this.image_) {
Expand Down Expand Up @@ -228,15 +215,20 @@ class IconImage extends EventTarget {

this.imageState_ = ImageState.LOADING;
try {
/** @type {HTMLImageElement} */ (this.image_).src = this.src_;
if (this.src_ !== undefined) {
/** @type {HTMLImageElement} */ (this.image_).src = this.src_;
}
} catch (e) {
this.handleImageError_();
}
this.unlisten_ = listenImage(
this.image_,
this.handleImageLoad_.bind(this),
this.handleImageError_.bind(this)
);
if (this.image_ instanceof HTMLImageElement) {
decodeFallback(this.image_, this.src_)
.then((image) => {
this.image_ = image;
this.handleImageLoad_();
})
.catch(this.handleImageError_.bind(this));
}
}

/**
Expand Down Expand Up @@ -270,34 +262,30 @@ class IconImage extends EventTarget {

this.canvas_[pixelRatio] = canvas;
}

/**
* Discards event handlers which listen for load completion or errors.
*
* @private
*/
unlistenImage_() {
if (this.unlisten_) {
this.unlisten_();
this.unlisten_ = null;
}
}
}

/**
* @param {HTMLImageElement|HTMLCanvasElement} image Image.
* @param {string} src Src.
* @param {import("../size.js").Size} size Size.
* @param {HTMLImageElement|HTMLCanvasElement|ImageBitmap} image Image.
* @param {string} cacheKey Src.
* @param {?string} crossOrigin Cross origin.
* @param {import("../ImageState.js").default} imageState Image state.
* @param {import("../color.js").Color} color Color.
* @return {IconImage} Icon image.
*/
export function get(image, src, size, crossOrigin, imageState, color) {
let iconImage = iconImageCache.get(src, crossOrigin, color);
export function get(image, cacheKey, crossOrigin, imageState, color) {
let iconImage =
cacheKey === undefined
? undefined
: iconImageCache.get(cacheKey, crossOrigin, color);
if (!iconImage) {
iconImage = new IconImage(image, src, size, crossOrigin, imageState, color);
iconImageCache.set(src, crossOrigin, color, iconImage);
iconImage = new IconImage(
image,
image instanceof HTMLImageElement ? image.src || undefined : cacheKey,
crossOrigin,
imageState,
color
);
iconImageCache.set(cacheKey, crossOrigin, color, iconImage);
}
return iconImage;
}
Expand Down

0 comments on commit 54fae09

Please sign in to comment.