diff --git a/examples/dynamic-data.js b/examples/dynamic-data.js index e2e7d0216a..313fa14bba 100644 --- a/examples/dynamic-data.js +++ b/examples/dynamic-data.js @@ -23,6 +23,7 @@ var map = new ol.Map({ var imageStyle = new ol.style.Circle({ radius: 5, + snapToPixel: false, fill: new ol.style.Fill({color: 'yellow'}), stroke: new ol.style.Stroke({color: 'red', width: 1}) }); diff --git a/externs/olx.js b/externs/olx.js index 0203f15369..3ce37eb603 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -4380,6 +4380,7 @@ olx.source.ZoomifyOptions.prototype.size; /** * @typedef {{fill: (ol.style.Fill|undefined), * radius: number, + * snapToPixel: (boolean|undefined), * stroke: (ol.style.Stroke|undefined)}} * @todo api */ @@ -4400,6 +4401,19 @@ olx.style.CircleOptions.prototype.fill; olx.style.CircleOptions.prototype.radius; +/** + * If `true` integral numbers of pixels are used as the X and Y pixel + * coordinate when drawing the circle in the output canvas. If `false` + * fractional numbers may be used. Using `true` allows for "sharp" + * rendering (no blur), while using `false` allows for "accurate" + * rendering. Note that accuracy is important if the circle's + * position is animated. Without it, the circle may jitter noticeably. + * Default value is `true`. + * @type {boolean|undefined} + */ +olx.style.CircleOptions.prototype.snapToPixel; + + /** * Stroke style. * @type {ol.style.Stroke|undefined} @@ -4429,6 +4443,7 @@ olx.style.FillOptions.prototype.color; * crossOrigin: (null|string|undefined), * origin: (Array.|undefined), * scale: (number|undefined), + * snapToPixel: (boolean|undefined), * rotateWithView: (boolean|undefined), * rotation: (number|undefined), * size: (ol.Size|undefined), @@ -4494,6 +4509,19 @@ olx.style.IconOptions.prototype.origin; olx.style.IconOptions.prototype.scale; +/** + * If `true` integral numbers of pixels are used as the X and Y pixel + * coordinate when drawing the icon in the output canvas. If `false` + * fractional numbers may be used. Using `true` allows for "sharp" + * rendering (no blur), while using `false` allows for "accurate" + * rendering. Note that accuracy is important if the icon's position + * is animated. Without it, the icon may jitter noticeably. Default + * value is `true`. + * @type {boolean|undefined} + */ +olx.style.IconOptions.prototype.snapToPixel; + + /** * Whether to rotate the icon with the view. Default is `false`. * @type {boolean|undefined} diff --git a/src/ol/render/canvas/canvasimmediate.js b/src/ol/render/canvas/canvasimmediate.js index b38c36dfb4..41e4a67484 100644 --- a/src/ol/render/canvas/canvasimmediate.js +++ b/src/ol/render/canvas/canvasimmediate.js @@ -886,13 +886,8 @@ ol.render.canvas.Immediate.prototype.setImageStyle = function(imageStyle) { var imageAnchor = imageStyle.getAnchor(); // FIXME pixel ratio var imageImage = imageStyle.getImage(1); - var imageOpacity = imageStyle.getOpacity(); var imageOrigin = imageStyle.getOrigin(); - var imageRotateWithView = imageStyle.getRotateWithView(); - var imageRotation = imageStyle.getRotation(); - var imageScale = imageStyle.getScale(); var imageSize = imageStyle.getSize(); - var imageSnapToPixel = imageStyle.getSnapToPixel(); goog.asserts.assert(!goog.isNull(imageAnchor)); goog.asserts.assert(!goog.isNull(imageImage)); goog.asserts.assert(!goog.isNull(imageOrigin)); @@ -901,15 +896,13 @@ ol.render.canvas.Immediate.prototype.setImageStyle = function(imageStyle) { this.imageAnchorY_ = imageAnchor[1]; this.imageHeight_ = imageSize[1]; this.image_ = imageImage; - this.imageOpacity_ = goog.isDef(imageOpacity) ? imageOpacity : 1; + this.imageOpacity_ = imageStyle.getOpacity(); this.imageOriginX_ = imageOrigin[0]; this.imageOriginY_ = imageOrigin[1]; - this.imageRotateWithView_ = goog.isDef(imageRotateWithView) ? - imageRotateWithView : false; - this.imageRotation_ = goog.isDef(imageRotation) ? imageRotation : 0; - this.imageScale_ = goog.isDef(imageScale) ? imageScale : 1; - this.imageSnapToPixel_ = goog.isDef(imageSnapToPixel) ? - imageSnapToPixel : false; + this.imageRotateWithView_ = imageStyle.getRotateWithView(); + this.imageRotation_ = imageStyle.getRotation(); + this.imageScale_ = imageStyle.getScale(); + this.imageSnapToPixel_ = imageStyle.getSnapToPixel(); this.imageWidth_ = imageSize[0]; } }; diff --git a/src/ol/render/canvas/canvasreplay.js b/src/ol/render/canvas/canvasreplay.js index 4eae5b3d6f..e28bd0aea7 100644 --- a/src/ol/render/canvas/canvasreplay.js +++ b/src/ol/render/canvas/canvasreplay.js @@ -1,4 +1,3 @@ -// FIXME decide default snapToPixel behaviour // FIXME add option to apply snapToPixel to all coordinates? // FIXME can eliminate empty set styles and strokes (when all geoms skipped) @@ -291,7 +290,7 @@ ol.render.canvas.Replay.prototype.replay_ = function( var rotateWithView = /** @type {boolean} */ (instruction[10]); var rotation = /** @type {number} */ (instruction[11]); var scale = /** @type {number} */ (instruction[12]); - var snapToPixel = /** @type {boolean|undefined} */ (instruction[13]); + var snapToPixel = /** @type {boolean} */ (instruction[13]); var width = /** @type {number} */ (instruction[14]) * pixelRatio; if (rotateWithView) { rotation += viewRotation; diff --git a/src/ol/style/circlestyle.js b/src/ol/style/circlestyle.js index 3bc83ed12d..564dbd5edd 100644 --- a/src/ol/style/circlestyle.js +++ b/src/ol/style/circlestyle.js @@ -1,5 +1,3 @@ -// FIXME decide default value for snapToPixel - goog.provide('ol.style.Circle'); goog.require('goog.dom'); @@ -68,13 +66,19 @@ ol.style.Circle = function(opt_options) { */ this.size_ = [size, size]; + /** + * @type {boolean} + */ + var snapToPixel = goog.isDef(options.snapToPixel) ? + options.snapToPixel : true; + goog.base(this, { opacity: 1, origin: [0, 0], rotateWithView: false, rotation: 0, scale: 1, - snapToPixel: undefined + snapToPixel: snapToPixel }); }; diff --git a/src/ol/style/iconstyle.js b/src/ol/style/iconstyle.js index 3b5c00b0d4..8ba1e08c66 100644 --- a/src/ol/style/iconstyle.js +++ b/src/ol/style/iconstyle.js @@ -1,5 +1,3 @@ -// FIXME decide default value for snapToPixel - goog.provide('ol.style.Icon'); goog.provide('ol.style.IconAnchorOrigin'); goog.provide('ol.style.IconAnchorUnits'); @@ -124,12 +122,18 @@ ol.style.Icon = function(opt_options) { */ var scale = goog.isDef(options.scale) ? options.scale : 1; + /** + * @type {boolean} + */ + var snapToPixel = goog.isDef(options.snapToPixel) ? + options.snapToPixel : true; + goog.base(this, { opacity: opacity, origin: origin, rotation: rotation, scale: scale, - snapToPixel: undefined, + snapToPixel: snapToPixel, rotateWithView: rotateWithView }); diff --git a/src/ol/style/imagestyle.js b/src/ol/style/imagestyle.js index 7fe5b08a87..20c8912c51 100644 --- a/src/ol/style/imagestyle.js +++ b/src/ol/style/imagestyle.js @@ -21,7 +21,7 @@ ol.style.ImageState = { * rotateWithView: boolean, * rotation: number, * scale: number, - * snapToPixel: (boolean|undefined)}} + * snapToPixel: boolean}} */ ol.style.ImageOptions; @@ -66,7 +66,7 @@ ol.style.Image = function(options) { /** * @private - * @type {boolean|undefined} + * @type {boolean} */ this.snapToPixel_ = options.snapToPixel; @@ -116,7 +116,7 @@ ol.style.Image.prototype.getScale = function() { /** - * @return {boolean|undefined} Snap to pixel? + * @return {boolean} Snap to pixel? */ ol.style.Image.prototype.getSnapToPixel = function() { return this.snapToPixel_;