diff --git a/src/ol/style/atlasmanager.js b/src/ol/style/atlasmanager.js index 45bbb1a55f..5eb7bf9ce4 100644 --- a/src/ol/style/atlasmanager.js +++ b/src/ol/style/atlasmanager.js @@ -8,12 +8,16 @@ goog.require('goog.object'); /** - * Provides information for an image inside an atlas. - * `offsetX` and `offsetY` are the position of the image inside + * Provides information for an image inside an atlas manager. + * `offsetX` and `offsetY` is the position of the image inside * the atlas image `image`. - * @typedef {{offsetX: number, offsetY: number, image: HTMLCanvasElement}} + * `hitOffsetX` and `hitOffsetY` ist the position of the hit-detection image + * inside the hit-detection atlas image `hitImage` (only when a hit-detection + * image was created for this image). + * @typedef {{offsetX: number, offsetY: number, image: HTMLCanvasElement, + * hitOffsetX: number, hitOffsetY: number, hitImage: HTMLCanvasElement}} */ -ol.style.AtlasInfo; +ol.style.AtlasManagerInfo; @@ -66,20 +70,54 @@ ol.style.AtlasManager = function(opt_options) { * @type {Array.} */ this.atlases_ = [new ol.style.Atlas(this.currentSize_, this.space_)]; + + /** + * The size in pixels of the latest atlas image for hit-detection images. + * @private + * @type {number} + */ + this.currentHitSize_ = this.currentSize_; + + /** + * @private + * @type {Array.} + */ + this.hitAtlases_ = [new ol.style.Atlas(this.currentHitSize_, this.space_)]; }; /** * @param {string} id The identifier of the entry to check. - * @return {?ol.style.AtlasInfo} The position and atlas image for the entry, - * or `null` if the entry is not part of the atlas manager. + * @return {?ol.style.AtlasManagerInfo} The position and atlas image for the + * entry, or `null` if the entry is not part of the atlas manager. */ ol.style.AtlasManager.prototype.getInfo = function(id) { + /** @type {?ol.style.AtlasInfo} */ + var info = this.getInfo_(this.atlases_, id); + + if (goog.isNull(info)) { + return null; + } + /** @type {?ol.style.AtlasInfo} */ + var hitInfo = this.getInfo_(this.hitAtlases_, id); + + return this.mergeInfos_(info, hitInfo); +}; + + +/** + * @private + * @param {Array.} atlases The atlases to search. + * @param {string} id The identifier of the entry to check. + * @return {?ol.style.AtlasInfo} The position and atlas image for the entry, + * or `null` if the entry is not part of the atlases. + */ +ol.style.AtlasManager.prototype.getInfo_ = function(atlases, id) { var atlas, info, i, ii; - for (i = 0, ii = this.atlases_.length; i < ii; ++i) { - atlas = this.atlases_[i]; + for (i = 0, ii = atlases.length; i < ii; ++i) { + atlas = atlases[i]; info = atlas.get(id); - if (info !== null) { + if (!goog.isNull(info)) { return info; } } @@ -87,41 +125,109 @@ ol.style.AtlasManager.prototype.getInfo = function(id) { }; +/** + * @private + * @param {ol.style.AtlasInfo} info The info for the real image. + * @param {?ol.style.AtlasInfo} hitInfo The info for the hit-detection + * image. + * @return {?ol.style.AtlasManagerInfo} The position and atlas image for the + * entry, or `null` if the entry is not part of the atlases. + */ +ol.style.AtlasManager.prototype.mergeInfos_ = function(info, hitInfo) { + return /** @type {ol.style.AtlasManagerInfo} */ ({ + offsetX: info.offsetX, + offsetY: info.offsetY, + image: info.image, + hitOffsetX: goog.isNull(hitInfo) ? undefined : hitInfo.offsetX, + hitOffsetY: goog.isNull(hitInfo) ? undefined : hitInfo.offsetY, + hitImage: goog.isNull(hitInfo) ? undefined : hitInfo.image + }); +}; + + /** * Add an image to the atlas manager. * * If an entry for the given id already exists, the entry will * be overridden (but the space on the atlas graphic will not be freed). * + * If `renderHitCallback` is provided, the image (or the hit-detection version + * of the image) will be rendered into a separate hit-detection atlas image. + * + * @param {string} id The identifier of the entry to add. + * @param {number} width The width. + * @param {number} height The height. + * @param {function(CanvasRenderingContext2D, number, number)} renderCallback + * Called to render the new image onto an atlas image. + * @param {function(CanvasRenderingContext2D, number, number)=} + * opt_renderHitCallback Called to render a hit-detection image onto a hit + * detection atlas image. + * @param {Object=} opt_this Value to use as `this` when executing + * `renderCallback` and `renderHitCallback`. + * @return {?ol.style.AtlasManagerInfo} The position and atlas image for the + * entry, or `null` if the image is too big. + */ +ol.style.AtlasManager.prototype.add = + function(id, width, height, + renderCallback, opt_renderHitCallback, opt_this) { + if (width + this.space_ > this.maxSize_ || + height + this.space_ > this.maxSize_) { + return null; + } + + /** @type {?ol.style.AtlasInfo} */ + var info = this.add_(false, + id, width, height, renderCallback, opt_this); + if (goog.isNull(info)) { + return null; + } + + /** @type {?ol.style.AtlasInfo} */ + var hitInfo = null; + if (goog.isDef(opt_renderHitCallback)) { + hitInfo = this.add_(true, + id, width, height, opt_renderHitCallback, opt_this); + } + return this.mergeInfos_(info, hitInfo); +}; + + +/** + * @private + * @param {boolean} isHitAtlas If the hit-detection atlases are used. * @param {string} id The identifier of the entry to add. * @param {number} width The width. * @param {number} height The height. * @param {function(CanvasRenderingContext2D, number, number)} renderCallback * Called to render the new image onto an atlas image. * @param {Object=} opt_this Value to use as `this` when executing - * `renderCallback`. + * `renderCallback` and `renderHitCallback`. * @return {?ol.style.AtlasInfo} The position and atlas image for the entry, * or `null` if the image is too big. */ -ol.style.AtlasManager.prototype.add = - function(id, width, height, renderCallback, opt_this) { - if (width + this.space_ > this.maxSize_ || - height + this.space_ > this.maxSize_) { - return null; - } - +ol.style.AtlasManager.prototype.add_ = + function(isHitAtlas, id, width, height, + renderCallback, opt_this) { + var atlases = (isHitAtlas) ? this.hitAtlases_ : this.atlases_; var atlas, info, i, ii; - for (i = 0, ii = this.atlases_.length; i < ii; ++i) { - atlas = this.atlases_[i]; + for (i = 0, ii = atlases.length; i < ii; ++i) { + atlas = atlases[i]; info = atlas.add(id, width, height, renderCallback, opt_this); - if (info !== null) { + if (!goog.isNull(info)) { return info; - } else if (info === null && i === ii - 1) { + } else if (goog.isNull(info) && i === ii - 1) { // the entry could not be added to one of the existing atlases, // create a new atlas that is twice as big and try to add to this one. - this.currentSize_ = Math.min(this.currentSize_ * 2, this.maxSize_); - atlas = new ol.style.Atlas(this.currentSize_, this.space_); - this.atlases_.push(atlas); + var size; + if (isHitAtlas) { + size = Math.min(this.currentHitSize_ * 2, this.maxSize_); + this.currentHitSize_ = size; + } else { + size = Math.min(this.currentSize_ * 2, this.maxSize_); + this.currentSize_ = size; + } + atlas = new ol.style.Atlas(size, this.space_); + atlases.push(atlas); // run the loop another time ++ii; } @@ -130,6 +236,15 @@ ol.style.AtlasManager.prototype.add = }; +/** + * Provides information for an image inside an atlas. + * `offsetX` and `offsetY` are the position of the image inside + * the atlas image `image`. + * @typedef {{offsetX: number, offsetY: number, image: HTMLCanvasElement}} + */ +ol.style.AtlasInfo; + + /** * This class facilitates the creation of image atlases. diff --git a/src/ol/style/circlestyle.js b/src/ol/style/circlestyle.js index dd5f63c8f2..6f976cc39e 100644 --- a/src/ol/style/circlestyle.js +++ b/src/ol/style/circlestyle.js @@ -69,6 +69,12 @@ ol.style.Circle = function(opt_options) { */ this.origin_ = [0, 0]; + /** + * @private + * @type {Array.} + */ + this.hitDetectionOrigin_ = [0, 0]; + /** * @private * @type {Array.} @@ -87,6 +93,12 @@ ol.style.Circle = function(opt_options) { */ this.imageSize_ = null; + /** + * @private + * @type {ol.Size} + */ + this.hitDetectionImageSize_ = null; + this.render_(options.atlasManager); /** @@ -159,6 +171,14 @@ ol.style.Circle.prototype.getImageSize = function() { }; +/** + * @inheritDoc + */ +ol.style.Circle.prototype.getHitDetectionImageSize = function() { + return this.hitDetectionImageSize_; +}; + + /** * @inheritDoc * @api @@ -168,6 +188,14 @@ ol.style.Circle.prototype.getOrigin = function() { }; +/** + * @inheritDoc + */ +ol.style.Circle.prototype.getHitDetectionOrigin = function() { + return this.hitDetectionOrigin_; +}; + + /** * @return {number} Radius. * @api @@ -259,30 +287,45 @@ ol.style.Circle.prototype.render_ = function(atlasManager) { var context = /** @type {CanvasRenderingContext2D} */ (this.canvas_.getContext('2d')); this.draw_(renderOptions, context, 0, 0); + + this.createHitDetectionCanvas_(renderOptions); } else { // an atlas manager is used, add the symbol to an atlas size = Math.round(size); + var hasCustomHitDetectionImage = goog.isNull(this.fill_); + var renderHitDetectionCallback; + if (hasCustomHitDetectionImage) { + // render the hit-detection image into a separate atlas image + renderHitDetectionCallback = + goog.bind(this.drawHitDetectionCanvas_, this, renderOptions); + } + var id = this.getChecksum(); var info = atlasManager.add( - id, size, size, goog.bind(this.draw_, this, renderOptions)); + id, size, size, goog.bind(this.draw_, this, renderOptions), + renderHitDetectionCallback); goog.asserts.assert(info !== null, 'circle radius is too large'); this.canvas_ = info.image; this.origin_ = [info.offsetX, info.offsetY]; imageSize = info.image.width; + + if (hasCustomHitDetectionImage) { + this.hitDetectionCanvas_ = info.hitImage; + this.hitDetectionOrigin_ = [info.hitOffsetX, info.hitOffsetY]; + this.hitDetectionImageSize_ = + [info.hitImage.width, info.hitImage.height]; + } else { + this.hitDetectionCanvas_ = this.canvas_; + this.hitDetectionOrigin_ = this.origin_; + this.hitDetectionImageSize_ = [imageSize, imageSize]; + } } this.anchor_ = [size / 2, size / 2]; this.size_ = [size, size]; this.imageSize_ = [imageSize, imageSize]; - - // deal with the hit detection canvas - if (!goog.isNull(this.fill_)) { - this.hitDetectionCanvas_ = this.canvas_; - } else { - this.createHitDetectionCanvas_(renderOptions); - } }; @@ -323,6 +366,14 @@ ol.style.Circle.prototype.draw_ = function(renderOptions, context, x, y) { * @param {ol.style.Circle.RenderOptions} renderOptions */ ol.style.Circle.prototype.createHitDetectionCanvas_ = function(renderOptions) { + this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size]; + if (!goog.isNull(this.fill_)) { + this.hitDetectionCanvas_ = this.canvas_; + return; + } + + // if no fill style is set, create an extra hit-detection image with a + // default fill style this.hitDetectionCanvas_ = /** @type {HTMLCanvasElement} */ (goog.dom.createElement(goog.dom.TagName.CANVAS)); var canvas = this.hitDetectionCanvas_; @@ -332,6 +383,26 @@ ol.style.Circle.prototype.createHitDetectionCanvas_ = function(renderOptions) { var context = /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d')); + this.drawHitDetectionCanvas_(renderOptions, context, 0, 0); +}; + + +/** + * @private + * @param {ol.style.Circle.RenderOptions} renderOptions + * @param {CanvasRenderingContext2D} context + * @param {number} x The origin for the symbol (x). + * @param {number} y The origin for the symbol (y). + */ +ol.style.Circle.prototype.drawHitDetectionCanvas_ = + function(renderOptions, context, x, y) { + // reset transform + context.setTransform(1, 0, 0, 1, 0, 0); + + // then move to (x, y) + context.translate(x, y); + + context.beginPath(); context.arc( renderOptions.size / 2, renderOptions.size / 2, this.radius_, 0, 2 * Math.PI, true); @@ -343,6 +414,7 @@ ol.style.Circle.prototype.createHitDetectionCanvas_ = function(renderOptions) { context.lineWidth = renderOptions.strokeWidth; context.stroke(); } + context.closePath(); }; diff --git a/src/ol/style/iconstyle.js b/src/ol/style/iconstyle.js index c82881420a..9913c6412a 100644 --- a/src/ol/style/iconstyle.js +++ b/src/ol/style/iconstyle.js @@ -246,6 +246,14 @@ ol.style.Icon.prototype.getImageSize = function() { }; +/** + * @inheritDoc + */ +ol.style.Icon.prototype.getHitDetectionImageSize = function() { + return this.getImageSize(); +}; + + /** * @inheritDoc */ @@ -293,6 +301,14 @@ ol.style.Icon.prototype.getOrigin = function() { }; +/** + * @inheritDoc + */ +ol.style.Icon.prototype.getHitDetectionOrigin = function() { + return this.getOrigin(); +}; + + /** * @return {string|undefined} Image src. * @api diff --git a/src/ol/style/imagestyle.js b/src/ol/style/imagestyle.js index bf306ab65c..be7c270788 100644 --- a/src/ol/style/imagestyle.js +++ b/src/ol/style/imagestyle.js @@ -126,6 +126,13 @@ ol.style.Image.prototype.getAnchor = goog.abstractMethod; ol.style.Image.prototype.getImage = goog.abstractMethod; +/** + * @param {number} pixelRatio Pixel ratio. + * @return {HTMLCanvasElement|HTMLVideoElement|Image} Image element. + */ +ol.style.Image.prototype.getHitDetectionImage = goog.abstractMethod; + + /** * @return {ol.style.ImageState} Image state. */ @@ -139,10 +146,9 @@ ol.style.Image.prototype.getImageSize = goog.abstractMethod; /** - * @param {number} pixelRatio Pixel ratio. - * @return {HTMLCanvasElement|HTMLVideoElement|Image} Image element. + * @return {ol.Size} Size of the hit-detection image. */ -ol.style.Image.prototype.getHitDetectionImage = goog.abstractMethod; +ol.style.Image.prototype.getHitDetectionImageSize = goog.abstractMethod; /** @@ -152,6 +158,13 @@ ol.style.Image.prototype.getHitDetectionImage = goog.abstractMethod; ol.style.Image.prototype.getOrigin = goog.abstractMethod; +/** + * @function + * @return {Array.} Origin for the hit-detection image. + */ +ol.style.Image.prototype.getHitDetectionOrigin = goog.abstractMethod; + + /** * @function * @return {ol.Size} Size. diff --git a/src/ol/style/regularshapestyle.js b/src/ol/style/regularshapestyle.js index 381a674d5d..9eb5864ade 100644 --- a/src/ol/style/regularshapestyle.js +++ b/src/ol/style/regularshapestyle.js @@ -56,6 +56,12 @@ ol.style.RegularShape = function(opt_options) { */ this.origin_ = [0, 0]; + /** + * @private + * @type {Array.} + */ + this.hitDetectionOrigin_ = [0, 0]; + /** * @private * @type {number} @@ -105,6 +111,12 @@ ol.style.RegularShape = function(opt_options) { */ this.imageSize_ = null; + /** + * @private + * @type {ol.Size} + */ + this.hitDetectionImageSize_ = null; + this.render_(options.atlasManager); /** @@ -168,6 +180,14 @@ ol.style.RegularShape.prototype.getImageSize = function() { }; +/** + * @inheritDoc + */ +ol.style.RegularShape.prototype.getHitDetectionImageSize = function() { + return this.hitDetectionImageSize_; +}; + + /** * @inheritDoc */ @@ -185,6 +205,14 @@ ol.style.RegularShape.prototype.getOrigin = function() { }; +/** + * @inheritDoc + */ +ol.style.RegularShape.prototype.getHitDetectionOrigin = function() { + return this.hitDetectionOrigin_; +}; + + /** * @return {number} Radius. * @api @@ -276,30 +304,45 @@ ol.style.RegularShape.prototype.render_ = function(atlasManager) { var context = /** @type {CanvasRenderingContext2D} */ (this.canvas_.getContext('2d')); this.draw_(renderOptions, context, 0, 0); + + this.createHitDetectionCanvas_(renderOptions); } else { // an atlas manager is used, add the symbol to an atlas size = Math.round(size); + var hasCustomHitDetectionImage = goog.isNull(this.fill_); + var renderHitDetectionCallback; + if (hasCustomHitDetectionImage) { + // render the hit-detection image into a separate atlas image + renderHitDetectionCallback = + goog.bind(this.drawHitDetectionCanvas_, this, renderOptions); + } + var id = this.getChecksum(); var info = atlasManager.add( - id, size, size, goog.bind(this.draw_, this, renderOptions)); + id, size, size, goog.bind(this.draw_, this, renderOptions), + renderHitDetectionCallback); goog.asserts.assert(info !== null, 'shape size is too large'); this.canvas_ = info.image; this.origin_ = [info.offsetX, info.offsetY]; imageSize = info.image.width; + + if (hasCustomHitDetectionImage) { + this.hitDetectionCanvas_ = info.hitImage; + this.hitDetectionOrigin_ = [info.hitOffsetX, info.hitOffsetY]; + this.hitDetectionImageSize_ = + [info.hitImage.width, info.hitImage.height]; + } else { + this.hitDetectionCanvas_ = this.canvas_; + this.hitDetectionOrigin_ = this.origin_; + this.hitDetectionImageSize_ = [imageSize, imageSize]; + } } this.anchor_ = [size / 2, size / 2]; this.size_ = [size, size]; this.imageSize_ = [imageSize, imageSize]; - - // deal with the hit detection canvas - if (!goog.isNull(this.fill_)) { - this.hitDetectionCanvas_ = this.canvas_; - } else { - this.createHitDetectionCanvas_(renderOptions); - } }; @@ -348,6 +391,14 @@ ol.style.RegularShape.prototype.draw_ = function(renderOptions, context, x, y) { */ ol.style.RegularShape.prototype.createHitDetectionCanvas_ = function(renderOptions) { + this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size]; + if (!goog.isNull(this.fill_)) { + this.hitDetectionCanvas_ = this.canvas_; + return; + } + + // if no fill style is set, create an extra hit-detection image with a + // default fill style this.hitDetectionCanvas_ = /** @type {HTMLCanvasElement} */ (goog.dom.createElement(goog.dom.TagName.CANVAS)); var canvas = this.hitDetectionCanvas_; @@ -357,6 +408,25 @@ ol.style.RegularShape.prototype.createHitDetectionCanvas_ = var context = /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d')); + this.drawHitDetectionCanvas_(renderOptions, context, 0, 0); +}; + + +/** + * @private + * @param {ol.style.RegularShape.RenderOptions} renderOptions + * @param {CanvasRenderingContext2D} context + * @param {number} x The origin for the symbol (x). + * @param {number} y The origin for the symbol (y). + */ +ol.style.RegularShape.prototype.drawHitDetectionCanvas_ = + function(renderOptions, context, x, y) { + // reset transform + context.setTransform(1, 0, 0, 1, 0, 0); + + // then move to (x, y) + context.translate(x, y); + context.beginPath(); if (this.radius2_ !== this.radius_) { this.points_ = 2 * this.points_; @@ -376,6 +446,7 @@ ol.style.RegularShape.prototype.createHitDetectionCanvas_ = context.lineWidth = renderOptions.strokeWidth; context.stroke(); } + context.closePath(); }; diff --git a/test/spec/ol/style/atlasmanager.test.js b/test/spec/ol/style/atlasmanager.test.js index b24d832dc0..69c414ba07 100644 --- a/test/spec/ol/style/atlasmanager.test.js +++ b/test/spec/ol/style/atlasmanager.test.js @@ -189,46 +189,73 @@ describe('ol.style.AtlasManager', function() { var manager = new ol.style.AtlasManager({size: 128}); var info = manager.add('1', 32, 32, defaultRender); - expect(info).to.eql( - {offsetX: 1, offsetY: 1, image: manager.atlases_[0].canvas_}); + expect(info).to.eql({ + offsetX: 1, offsetY: 1, image: manager.atlases_[0].canvas_, + hitOffsetX: undefined, hitOffsetY: undefined, hitImage: undefined}); + + expect(manager.getInfo('1')).to.eql(info); + }); + + it('adds one entry (also to the hit detection atlas)', function() { + var manager = new ol.style.AtlasManager({size: 128}); + var info = manager.add('1', 32, 32, defaultRender, defaultRender); + + expect(info).to.eql({ + offsetX: 1, offsetY: 1, image: manager.atlases_[0].canvas_, + hitOffsetX: 1, hitOffsetY: 1, + hitImage: manager.hitAtlases_[0].canvas_}); expect(manager.getInfo('1')).to.eql(info); }); it('creates a new atlas if needed', function() { var manager = new ol.style.AtlasManager({size: 128}); - expect(manager.add('1', 100, 100, defaultRender)).to.be.ok(); - var info = manager.add('2', 100, 100, defaultRender); + expect(manager.add('1', 100, 100, defaultRender, defaultRender)) + .to.be.ok(); + var info = manager.add('2', 100, 100, defaultRender, defaultRender); expect(info).to.be.ok(); expect(info.image.width).to.eql(256); expect(manager.atlases_).to.have.length(2); + expect(info.hitImage.width).to.eql(256); + expect(manager.hitAtlases_).to.have.length(2); }); it('creates new atlases until one is large enough', function() { var manager = new ol.style.AtlasManager({size: 128}); - expect(manager.add('1', 100, 100, defaultRender)).to.be.ok(); + expect(manager.add('1', 100, 100, defaultRender, defaultRender)) + .to.be.ok(); expect(manager.atlases_).to.have.length(1); - var info = manager.add('2', 500, 500, defaultRender); + expect(manager.hitAtlases_).to.have.length(1); + var info = manager.add('2', 500, 500, defaultRender, defaultRender); expect(info).to.be.ok(); expect(info.image.width).to.eql(512); expect(manager.atlases_).to.have.length(3); + expect(info.hitImage.width).to.eql(512); + expect(manager.hitAtlases_).to.have.length(3); }); it('checks all existing atlases and create a new if needed', function() { var manager = new ol.style.AtlasManager({size: 128}); - expect(manager.add('1', 100, 100, defaultRender)).to.be.ok(); - expect(manager.add('2', 100, 100, defaultRender)).to.be.ok(); + expect(manager.add('1', 100, 100, defaultRender, defaultRender)) + .to.be.ok(); + expect(manager.add('2', 100, 100, defaultRender, defaultRender)) + .to.be.ok(); expect(manager.atlases_).to.have.length(2); - var info = manager.add(3, 500, 500, defaultRender); + expect(manager.hitAtlases_).to.have.length(2); + var info = manager.add(3, 500, 500, defaultRender, defaultRender); expect(info).to.be.ok(); expect(info.image.width).to.eql(512); expect(manager.atlases_).to.have.length(3); + expect(info.hitImage.width).to.eql(512); + expect(manager.hitAtlases_).to.have.length(3); }); it('returns null if the size exceeds the maximum size', function() { var manager = new ol.style.AtlasManager({size: 128}); - expect(manager.add('1', 100, 100, defaultRender)).to.be.ok(); - expect(manager.add('2', 2048, 2048, defaultRender)).to.eql(null); + expect(manager.add('1', 100, 100, defaultRender, defaultRender)) + .to.be.ok(); + expect(manager.add('2', 2048, 2048, defaultRender, defaultRender)) + .to.eql(null); }); }); diff --git a/test/spec/ol/style/circlestyle.test.js b/test/spec/ol/style/circlestyle.test.js index 40c9f66b5a..a7bc6ba40d 100644 --- a/test/spec/ol/style/circlestyle.test.js +++ b/test/spec/ol/style/circlestyle.test.js @@ -5,18 +5,40 @@ describe('ol.style.Circle', function() { describe('#constructor', function() { - it('creates a canvas if no atlas is used', function() { + it('creates a canvas if no atlas is used (no fill-style)', function() { var style = new ol.style.Circle({radius: 10}); expect(style.getImage()).to.be.an(HTMLCanvasElement); expect(style.getSize()).to.eql([21, 21]); expect(style.getImageSize()).to.eql([21, 21]); expect(style.getOrigin()).to.eql([0, 0]); expect(style.getAnchor()).to.eql([10.5, 10.5]); + // hit-detection image is created, because no fill style is set expect(style.getImage()).to.not.be(style.getHitDetectionImage()); expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement); + expect(style.getHitDetectionImageSize()).to.eql([21, 21]); + expect(style.getHitDetectionOrigin()).to.eql([0, 0]); }); - it('adds itself to an atlas manager', function() { + it('creates a canvas if no atlas is used (fill-style)', function() { + var style = new ol.style.Circle({ + radius: 10, + fill: new ol.style.Fill({ + color: '#FFFF00' + }) + }); + expect(style.getImage()).to.be.an(HTMLCanvasElement); + expect(style.getSize()).to.eql([21, 21]); + expect(style.getImageSize()).to.eql([21, 21]); + expect(style.getOrigin()).to.eql([0, 0]); + expect(style.getAnchor()).to.eql([10.5, 10.5]); + // no hit-detection image is created, because fill style is set + expect(style.getImage()).to.be(style.getHitDetectionImage()); + expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement); + expect(style.getHitDetectionImageSize()).to.eql([21, 21]); + expect(style.getHitDetectionOrigin()).to.eql([0, 0]); + }); + + it('adds itself to an atlas manager (no fill-style)', function() { var atlasManager = new ol.style.AtlasManager({size: 512}); var style = new ol.style.Circle({radius: 10, atlasManager: atlasManager}); expect(style.getImage()).to.be.an(HTMLCanvasElement); @@ -24,8 +46,32 @@ describe('ol.style.Circle', function() { expect(style.getImageSize()).to.eql([512, 512]); expect(style.getOrigin()).to.eql([1, 1]); expect(style.getAnchor()).to.eql([10.5, 10.5]); + // hit-detection image is created, because no fill style is set expect(style.getImage()).to.not.be(style.getHitDetectionImage()); expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement); + expect(style.getHitDetectionImageSize()).to.eql([512, 512]); + expect(style.getHitDetectionOrigin()).to.eql([1, 1]); + }); + + it('adds itself to an atlas manager (fill-style)', function() { + var atlasManager = new ol.style.AtlasManager({size: 512}); + var style = new ol.style.Circle({ + radius: 10, + atlasManager: atlasManager, + fill: new ol.style.Fill({ + color: '#FFFF00' + }) + }); + expect(style.getImage()).to.be.an(HTMLCanvasElement); + expect(style.getSize()).to.eql([21, 21]); + expect(style.getImageSize()).to.eql([512, 512]); + expect(style.getOrigin()).to.eql([1, 1]); + expect(style.getAnchor()).to.eql([10.5, 10.5]); + // no hit-detection image is created, because fill style is set + expect(style.getImage()).to.be(style.getHitDetectionImage()); + expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement); + expect(style.getHitDetectionImageSize()).to.eql([512, 512]); + expect(style.getHitDetectionOrigin()).to.eql([1, 1]); }); }); diff --git a/test/spec/ol/style/regularshapestyle.test.js b/test/spec/ol/style/regularshapestyle.test.js index c382da8a59..585d34c2f6 100644 --- a/test/spec/ol/style/regularshapestyle.test.js +++ b/test/spec/ol/style/regularshapestyle.test.js @@ -5,18 +5,40 @@ describe('ol.style.RegularShape', function() { describe('#constructor', function() { - it('creates a canvas if no atlas is used', function() { + it('creates a canvas if no atlas is used (no fill-style)', function() { var style = new ol.style.RegularShape({radius: 10}); expect(style.getImage()).to.be.an(HTMLCanvasElement); expect(style.getSize()).to.eql([21, 21]); expect(style.getImageSize()).to.eql([21, 21]); expect(style.getOrigin()).to.eql([0, 0]); expect(style.getAnchor()).to.eql([10.5, 10.5]); + // hit-detection image is created, because no fill style is set expect(style.getImage()).to.not.be(style.getHitDetectionImage()); expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement); + expect(style.getHitDetectionImageSize()).to.eql([21, 21]); + expect(style.getHitDetectionOrigin()).to.eql([0, 0]); }); - it('adds itself to an atlas manager', function() { + it('creates a canvas if no atlas is used (fill-style)', function() { + var style = new ol.style.RegularShape({ + radius: 10, + fill: new ol.style.Fill({ + color: '#FFFF00' + }) + }); + expect(style.getImage()).to.be.an(HTMLCanvasElement); + expect(style.getSize()).to.eql([21, 21]); + expect(style.getImageSize()).to.eql([21, 21]); + expect(style.getOrigin()).to.eql([0, 0]); + expect(style.getAnchor()).to.eql([10.5, 10.5]); + // no hit-detection image is created, because fill style is set + expect(style.getImage()).to.be(style.getHitDetectionImage()); + expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement); + expect(style.getHitDetectionImageSize()).to.eql([21, 21]); + expect(style.getHitDetectionOrigin()).to.eql([0, 0]); + }); + + it('adds itself to an atlas manager (no fill-style)', function() { var atlasManager = new ol.style.AtlasManager({size: 512}); var style = new ol.style.RegularShape( {radius: 10, atlasManager: atlasManager}); @@ -25,8 +47,32 @@ describe('ol.style.RegularShape', function() { expect(style.getImageSize()).to.eql([512, 512]); expect(style.getOrigin()).to.eql([1, 1]); expect(style.getAnchor()).to.eql([10.5, 10.5]); + // hit-detection image is created, because no fill style is set expect(style.getImage()).to.not.be(style.getHitDetectionImage()); expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement); + expect(style.getHitDetectionImageSize()).to.eql([512, 512]); + expect(style.getHitDetectionOrigin()).to.eql([1, 1]); + }); + + it('adds itself to an atlas manager (fill-style)', function() { + var atlasManager = new ol.style.AtlasManager({size: 512}); + var style = new ol.style.RegularShape({ + radius: 10, + atlasManager: atlasManager, + fill: new ol.style.Fill({ + color: '#FFFF00' + }) + }); + expect(style.getImage()).to.be.an(HTMLCanvasElement); + expect(style.getSize()).to.eql([21, 21]); + expect(style.getImageSize()).to.eql([512, 512]); + expect(style.getOrigin()).to.eql([1, 1]); + expect(style.getAnchor()).to.eql([10.5, 10.5]); + // no hit-detection image is created, because fill style is set + expect(style.getImage()).to.be(style.getHitDetectionImage()); + expect(style.getHitDetectionImage()).to.be.an(HTMLCanvasElement); + expect(style.getHitDetectionImageSize()).to.eql([512, 512]); + expect(style.getHitDetectionOrigin()).to.eql([1, 1]); }); });