Hit detect everything with a pixel ratio of 1

This commit is contained in:
Andreas Hocevar
2020-07-27 19:56:35 +02:00
parent cad5057a96
commit ac5f52a21f
7 changed files with 50 additions and 71 deletions

View File

@@ -163,20 +163,17 @@ class CanvasImageBuilder extends CanvasBuilder {
myEnd, myEnd,
this.hitDetectionImage_, this.hitDetectionImage_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order // Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_ * this.imagePixelRatio_, this.anchorX_,
this.anchorY_ * this.imagePixelRatio_, this.anchorY_,
this.declutterGroups_, this.declutterGroups_,
Math.ceil(this.height_ * this.imagePixelRatio_), this.height_,
this.opacity_, this.opacity_,
this.originX_, this.originX_,
this.originY_, this.originY_,
this.rotateWithView_, this.rotateWithView_,
this.rotation_, this.rotation_,
[ this.scale_,
(this.scale_[0] * this.pixelRatio) / this.imagePixelRatio_, this.width_,
(this.scale_[1] * this.pixelRatio) / this.imagePixelRatio_,
],
Math.ceil(this.width_ * this.imagePixelRatio_),
]); ]);
this.endGeometry(feature); this.endGeometry(feature);
} }
@@ -226,20 +223,17 @@ class CanvasImageBuilder extends CanvasBuilder {
myEnd, myEnd,
this.hitDetectionImage_, this.hitDetectionImage_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order // Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_ * this.imagePixelRatio_, this.anchorX_,
this.anchorY_ * this.imagePixelRatio_, this.anchorY_,
this.declutterGroups_, this.declutterGroups_,
Math.ceil(this.height_ * this.imagePixelRatio_), this.height_,
this.opacity_, this.opacity_,
this.originX_, this.originX_,
this.originY_, this.originY_,
this.rotateWithView_, this.rotateWithView_,
this.rotation_, this.rotation_,
[ this.scale_,
(this.scale_[0] * this.pixelRatio) / this.imagePixelRatio_, this.width_,
(this.scale_[1] * this.pixelRatio) / this.imagePixelRatio_,
],
Math.ceil(this.width_ * this.imagePixelRatio_),
]); ]);
this.endGeometry(feature); this.endGeometry(feature);
} }
@@ -273,7 +267,7 @@ class CanvasImageBuilder extends CanvasBuilder {
setImageStyle(imageStyle, declutterGroups) { setImageStyle(imageStyle, declutterGroups) {
const anchor = imageStyle.getAnchor(); const anchor = imageStyle.getAnchor();
const size = imageStyle.getSize(); const size = imageStyle.getSize();
const hitDetectionImage = imageStyle.getHitDetectionImage(this.pixelRatio); const hitDetectionImage = imageStyle.getHitDetectionImage();
const image = imageStyle.getImage(this.pixelRatio); const image = imageStyle.getImage(this.pixelRatio);
const origin = imageStyle.getOrigin(); const origin = imageStyle.getOrigin();
this.imagePixelRatio_ = imageStyle.getPixelRatio(this.pixelRatio); this.imagePixelRatio_ = imageStyle.getPixelRatio(this.pixelRatio);

View File

@@ -352,11 +352,10 @@ class Icon extends ImageStyle {
} }
/** /**
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLImageElement|HTMLCanvasElement} Image element. * @return {HTMLImageElement|HTMLCanvasElement} Image element.
*/ */
getHitDetectionImage(pixelRatio) { getHitDetectionImage() {
return this.iconImage_.getHitDetectionImage(pixelRatio); return this.iconImage_.getHitDetectionImage();
} }
/** /**

View File

@@ -28,9 +28,9 @@ class IconImage extends EventTarget {
/** /**
* @private * @private
* @type {Object<number, HTMLImageElement|HTMLCanvasElement>} * @type {HTMLImageElement|HTMLCanvasElement}
*/ */
this.hitDetectionImage_ = {}; this.hitDetectionImage_ = null;
/** /**
* @private * @private
@@ -162,27 +162,21 @@ class IconImage extends EventTarget {
} }
/** /**
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLImageElement|HTMLCanvasElement} Image element. * @return {HTMLImageElement|HTMLCanvasElement} Image element.
*/ */
getHitDetectionImage(pixelRatio) { getHitDetectionImage() {
if (!this.hitDetectionImage_[pixelRatio]) { if (!this.hitDetectionImage_) {
if (this.isTainted_()) { if (this.isTainted_()) {
const usedPixelRatio = this.color_ ? pixelRatio : 1;
const width = this.size_[0]; const width = this.size_[0];
const height = this.size_[1]; const height = this.size_[1];
const context = createCanvasContext2D( const context = createCanvasContext2D(width, height);
Math.ceil(width * usedPixelRatio),
Math.ceil(height * usedPixelRatio)
);
context.scale(usedPixelRatio, usedPixelRatio);
context.fillRect(0, 0, width, height); context.fillRect(0, 0, width, height);
this.hitDetectionImage_[pixelRatio] = context.canvas; this.hitDetectionImage_ = context.canvas;
} else { } else {
this.hitDetectionImage_[pixelRatio] = this.image_; this.hitDetectionImage_ = this.image_;
} }
} }
return this.hitDetectionImage_[pixelRatio]; return this.hitDetectionImage_;
} }
/** /**

View File

@@ -154,10 +154,9 @@ class ImageStyle {
/** /**
* @abstract * @abstract
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} Image element. * @return {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} Image element.
*/ */
getHitDetectionImage(pixelRatio) { getHitDetectionImage() {
return abstract(); return abstract();
} }

View File

@@ -79,9 +79,9 @@ class RegularShape extends ImageStyle {
/** /**
* @private * @private
* @type {Object<number, HTMLCanvasElement>} * @type {HTMLCanvasElement}
*/ */
this.hitDetectionCanvas_ = {}; this.hitDetectionCanvas_ = null;
/** /**
* @private * @private
@@ -204,16 +204,15 @@ class RegularShape extends ImageStyle {
} }
/** /**
* @param {number} pixelRatio Pixel ratio.
* @return {HTMLCanvasElement} Image element. * @return {HTMLCanvasElement} Image element.
*/ */
getHitDetectionImage(pixelRatio) { getHitDetectionImage() {
if (!this.hitDetectionCanvas_[pixelRatio || 1]) { if (!this.hitDetectionCanvas_) {
const renderOptions = this.createRenderOptions(); const renderOptions = this.createRenderOptions();
this.createHitDetectionCanvas_(renderOptions, pixelRatio || 1); this.createHitDetectionCanvas_(renderOptions);
} }
return this.hitDetectionCanvas_[pixelRatio || 1]; return this.hitDetectionCanvas_;
} }
/** /**
@@ -410,7 +409,7 @@ class RegularShape extends ImageStyle {
const displacement = this.getDisplacement(); const displacement = this.getDisplacement();
this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size]; this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size];
this.createHitDetectionCanvas_(renderOptions, 1); this.createHitDetectionCanvas_(renderOptions);
this.anchor_ = [size / 2 - displacement[0], size / 2 + displacement[1]]; this.anchor_ = [size / 2 - displacement[0], size / 2 + displacement[1]];
this.size_ = [size, size]; this.size_ = [size, size];
@@ -488,10 +487,9 @@ class RegularShape extends ImageStyle {
/** /**
* @private * @private
* @param {RenderOptions} renderOptions Render options. * @param {RenderOptions} renderOptions Render options.
* @param {number} pixelRatio The pixel ratio.
*/ */
createHitDetectionCanvas_(renderOptions, pixelRatio) { createHitDetectionCanvas_(renderOptions) {
this.hitDetectionCanvas_[pixelRatio] = this.getImage(pixelRatio); this.hitDetectionCanvas_ = this.getImage(1);
if (this.fill_) { if (this.fill_) {
let color = this.fill_.getColor(); let color = this.fill_.getColor();
@@ -509,12 +507,12 @@ class RegularShape extends ImageStyle {
// if a transparent fill style is set, create an extra hit-detection image // if a transparent fill style is set, create an extra hit-detection image
// with a default fill style // with a default fill style
const context = createCanvasContext2D( const context = createCanvasContext2D(
renderOptions.size * pixelRatio, renderOptions.size,
renderOptions.size * pixelRatio renderOptions.size
); );
this.hitDetectionCanvas_[pixelRatio] = context.canvas; this.hitDetectionCanvas_ = context.canvas;
this.drawHitDetectionCanvas_(renderOptions, context, 0, 0, pixelRatio); this.drawHitDetectionCanvas_(renderOptions, context, 0, 0);
} }
} }
} }
@@ -525,13 +523,9 @@ class RegularShape extends ImageStyle {
* @param {CanvasRenderingContext2D} context The context. * @param {CanvasRenderingContext2D} context The context.
* @param {number} x The origin for the symbol (x). * @param {number} x The origin for the symbol (x).
* @param {number} y The origin for the symbol (y). * @param {number} y The origin for the symbol (y).
* @param {number} pixelRatio The pixel ratio.
*/ */
drawHitDetectionCanvas_(renderOptions, context, x, y, pixelRatio) { drawHitDetectionCanvas_(renderOptions, context, x, y) {
// reset transform // move to (x, y)
context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
// then move to (x, y)
context.translate(x, y); context.translate(x, y);
context.beginPath(); context.beginPath();

View File

@@ -12,8 +12,8 @@ describe('ol.style.Circle', function () {
expect(style.getOrigin()).to.eql([0, 0]); expect(style.getOrigin()).to.eql([0, 0]);
expect(style.getAnchor()).to.eql([10.5, 10.5]); expect(style.getAnchor()).to.eql([10.5, 10.5]);
// no hit-detection image is created, because no fill style is set // no hit-detection image is created, because no fill style is set
expect(style.getImage(1)).to.be(style.getHitDetectionImage(1)); expect(style.getImage(1)).to.be(style.getHitDetectionImage());
expect(style.getHitDetectionImage(1)).to.be.an(HTMLCanvasElement); expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement);
expect(style.getHitDetectionImageSize()).to.eql([21, 21]); expect(style.getHitDetectionImageSize()).to.eql([21, 21]);
}); });
@@ -30,8 +30,8 @@ describe('ol.style.Circle', function () {
expect(style.getOrigin()).to.eql([0, 0]); expect(style.getOrigin()).to.eql([0, 0]);
expect(style.getAnchor()).to.eql([10.5, 10.5]); expect(style.getAnchor()).to.eql([10.5, 10.5]);
// hit-detection image is created, because transparent fill style is set // hit-detection image is created, because transparent fill style is set
expect(style.getImage(1)).to.not.be(style.getHitDetectionImage(1)); expect(style.getImage(1)).to.not.be(style.getHitDetectionImage());
expect(style.getHitDetectionImage(1)).to.be.an(HTMLCanvasElement); expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement);
expect(style.getHitDetectionImageSize()).to.eql([21, 21]); expect(style.getHitDetectionImageSize()).to.eql([21, 21]);
}); });
@@ -48,8 +48,8 @@ describe('ol.style.Circle', function () {
expect(style.getOrigin()).to.eql([0, 0]); expect(style.getOrigin()).to.eql([0, 0]);
expect(style.getAnchor()).to.eql([10.5, 10.5]); expect(style.getAnchor()).to.eql([10.5, 10.5]);
// no hit-detection image is created, because non-transparent fill style is set // no hit-detection image is created, because non-transparent fill style is set
expect(style.getImage(1)).to.be(style.getHitDetectionImage(1)); expect(style.getImage(1)).to.be(style.getHitDetectionImage());
expect(style.getHitDetectionImage(1)).to.be.an(HTMLCanvasElement); expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement);
expect(style.getHitDetectionImageSize()).to.eql([21, 21]); expect(style.getHitDetectionImageSize()).to.eql([21, 21]);
}); });
}); });

View File

@@ -38,8 +38,8 @@ describe('ol.style.RegularShape', function () {
expect(style.getOrigin()).to.eql([0, 0]); expect(style.getOrigin()).to.eql([0, 0]);
expect(style.getAnchor()).to.eql([10.5, 10.5]); expect(style.getAnchor()).to.eql([10.5, 10.5]);
// no hit-detection image is created, because no fill style is set // no hit-detection image is created, because no fill style is set
expect(style.getImage(1)).to.be(style.getHitDetectionImage(1)); expect(style.getImage(1)).to.be(style.getHitDetectionImage());
expect(style.getHitDetectionImage(1)).to.be.an(HTMLCanvasElement); expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement);
expect(style.getHitDetectionImageSize()).to.eql([21, 21]); expect(style.getHitDetectionImageSize()).to.eql([21, 21]);
}); });
@@ -59,11 +59,10 @@ describe('ol.style.RegularShape', function () {
expect(style.getOrigin()).to.eql([0, 0]); expect(style.getOrigin()).to.eql([0, 0]);
expect(style.getAnchor()).to.eql([10.5, 10.5]); expect(style.getAnchor()).to.eql([10.5, 10.5]);
// hit-detection image is created, because transparent fill style is set // hit-detection image is created, because transparent fill style is set
expect(style.getImage(1)).to.not.be(style.getHitDetectionImage(1)); expect(style.getImage(1)).to.not.be(style.getHitDetectionImage());
expect(style.getHitDetectionImage(1)).to.be.an(HTMLCanvasElement); expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement);
expect(style.getHitDetectionImageSize()).to.eql([21, 21]); expect(style.getHitDetectionImageSize()).to.eql([21, 21]);
expect(style.getHitDetectionImage(1).width).to.be(21); expect(style.getHitDetectionImage().width).to.be(21);
expect(style.getHitDetectionImage(2).width).to.be(42);
}); });
it('creates a canvas (non-transparent fill-style)', function () { it('creates a canvas (non-transparent fill-style)', function () {
@@ -79,8 +78,8 @@ describe('ol.style.RegularShape', function () {
expect(style.getOrigin()).to.eql([0, 0]); expect(style.getOrigin()).to.eql([0, 0]);
expect(style.getAnchor()).to.eql([10.5, 10.5]); expect(style.getAnchor()).to.eql([10.5, 10.5]);
// no hit-detection image is created, because non-transparent fill style is set // no hit-detection image is created, because non-transparent fill style is set
expect(style.getImage(1)).to.be(style.getHitDetectionImage(1)); expect(style.getImage(1)).to.be(style.getHitDetectionImage());
expect(style.getHitDetectionImage(1)).to.be.an(HTMLCanvasElement); expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement);
expect(style.getHitDetectionImageSize()).to.eql([21, 21]); expect(style.getHitDetectionImageSize()).to.eql([21, 21]);
}); });