diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index 50cbd40cbf..b04622625b 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -941,6 +941,7 @@ * `'fraction'`. * @property {null|string|undefined} crossOrigin crossOrigin setting for image. * @property {number|undefined} scale Scale. + * @property {boolean|undefined} rotateWithView Whether to rotate the icon with the view. Default is `false`. * @property {number|undefined} rotation Rotation. * @property {ol.Size|undefined} size Icon size in pixel. * @property {string} src Image source URI. diff --git a/src/ol/render/canvas/canvasimmediate.js b/src/ol/render/canvas/canvasimmediate.js index b1be7d6453..933724d370 100644 --- a/src/ol/render/canvas/canvasimmediate.js +++ b/src/ol/render/canvas/canvasimmediate.js @@ -25,9 +25,11 @@ goog.require('ol.vec.Mat4'); * @param {number} pixelRatio Pixel ratio. * @param {ol.Extent} extent Extent. * @param {goog.vec.Mat4.Number} transform Transform. + * @param {number} viewRotation View rotation. * @struct */ -ol.render.canvas.Immediate = function(context, pixelRatio, extent, transform) { +ol.render.canvas.Immediate = + function(context, pixelRatio, extent, transform, viewRotation) { /** * @private @@ -60,6 +62,12 @@ ol.render.canvas.Immediate = function(context, pixelRatio, extent, transform) { */ this.transform_ = transform; + /** + * @private + * @type {number} + */ + this.viewRotation_ = viewRotation; + /** * @private * @type {?ol.render.canvas.FillState} @@ -120,6 +128,12 @@ ol.render.canvas.Immediate = function(context, pixelRatio, extent, transform) { */ this.imageOpacity_ = 0; + /** + * @private + * @type {boolean} + */ + this.imageRotateWithView_ = false; + /** * @private * @type {number} @@ -217,6 +231,10 @@ ol.render.canvas.Immediate.prototype.drawImages_ = if (this.imageOpacity_ != 1) { context.globalAlpha = alpha * this.imageOpacity_; } + var rotation = this.imageRotation_; + if (this.imageRotateWithView_) { + rotation += this.viewRotation_; + } var i, ii; for (i = 0, ii = pixelCoordinates.length; i < ii; i += 2) { var x = pixelCoordinates[i] - this.imageAnchorX_; @@ -225,12 +243,12 @@ ol.render.canvas.Immediate.prototype.drawImages_ = x = (x + 0.5) | 0; y = (y + 0.5) | 0; } - if (this.imageRotation_ !== 0 || this.imageScale_ != 1) { + if (rotation !== 0 || this.imageScale_ != 1) { var centerX = x + this.imageAnchorX_; var centerY = y + this.imageAnchorY_; ol.vec.Mat4.makeTransform2D(localTransform, centerX, centerY, this.imageScale_, this.imageScale_, - this.imageRotation_, -centerX, -centerY); + rotation, -centerX, -centerY); context.setTransform( goog.vec.Mat4.getElement(localTransform, 0, 0), goog.vec.Mat4.getElement(localTransform, 1, 0), @@ -241,7 +259,7 @@ ol.render.canvas.Immediate.prototype.drawImages_ = } context.drawImage(this.image_, x, y, this.imageWidth_, this.imageHeight_); } - if (this.imageRotation_ !== 0 || this.imageScale_ != 1) { + if (rotation !== 0 || this.imageScale_ != 1) { context.setTransform(1, 0, 0, 1, 0, 0); } if (this.imageOpacity_ != 1) { @@ -780,6 +798,7 @@ ol.render.canvas.Immediate.prototype.setImageStyle = function(imageStyle) { // FIXME pixel ratio var imageImage = imageStyle.getImage(1); var imageOpacity = imageStyle.getOpacity(); + var imageRotateWithView = imageStyle.getRotateWithView(); var imageRotation = imageStyle.getRotation(); var imageScale = imageStyle.getScale(); var imageSize = imageStyle.getSize(); @@ -792,6 +811,8 @@ ol.render.canvas.Immediate.prototype.setImageStyle = function(imageStyle) { this.imageHeight_ = imageSize[1]; this.image_ = imageImage; this.imageOpacity_ = goog.isDef(imageOpacity) ? imageOpacity : 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) ? diff --git a/src/ol/render/canvas/canvasreplay.js b/src/ol/render/canvas/canvasreplay.js index 024fe9365e..f54a704e20 100644 --- a/src/ol/render/canvas/canvasreplay.js +++ b/src/ol/render/canvas/canvasreplay.js @@ -159,6 +159,7 @@ ol.render.canvas.Replay.prototype.beginGeometry = function(geometry) { * @param {CanvasRenderingContext2D} context Context. * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. + * @param {number} viewRotation View rotation. * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render * geometry function. * @param {Array.<*>} instructions Instructions array. @@ -167,9 +168,9 @@ ol.render.canvas.Replay.prototype.beginGeometry = function(geometry) { * @return {T|undefined} Callback result. * @template T */ -ol.render.canvas.Replay.prototype.replay_ = - function(context, pixelRatio, transform, renderGeometryFunction, - instructions, geometryCallback) { +ol.render.canvas.Replay.prototype.replay_ = function( + context, pixelRatio, transform, viewRotation, renderGeometryFunction, + instructions, geometryCallback) { /** @type {Array.} */ var pixelCoordinates; if (ol.vec.Mat4.equals2D(transform, this.renderedTransform_)) { @@ -230,10 +231,14 @@ ol.render.canvas.Replay.prototype.replay_ = var anchorY = /** @type {number} */ (instruction[5]) * pixelRatio; var height = /** @type {number} */ (instruction[6]) * pixelRatio; var opacity = /** @type {number} */ (instruction[7]); - var rotation = /** @type {number} */ (instruction[8]); - var scale = /** @type {number} */ (instruction[9]); - var snapToPixel = /** @type {boolean|undefined} */ (instruction[10]); - var width = /** @type {number} */ (instruction[11]) * pixelRatio; + var rotateWithView = /** @type {boolean} */ (instruction[8]); + var rotation = /** @type {number} */ (instruction[9]); + var scale = /** @type {number} */ (instruction[10]); + var snapToPixel = /** @type {boolean|undefined} */ (instruction[11]); + var width = /** @type {number} */ (instruction[12]) * pixelRatio; + if (rotateWithView) { + rotation += viewRotation; + } for (; d < dd; d += 2) { x = pixelCoordinates[d] - anchorX; y = pixelCoordinates[d + 1] - anchorY; @@ -389,22 +394,24 @@ ol.render.canvas.Replay.prototype.replay_ = * @param {CanvasRenderingContext2D} context Context. * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. + * @param {number} viewRotation View rotation. * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render * geometry function. * @return {T|undefined} Callback result. * @template T */ -ol.render.canvas.Replay.prototype.replay = - function(context, pixelRatio, transform, renderGeometryFunction) { +ol.render.canvas.Replay.prototype.replay = function( + context, pixelRatio, transform, viewRotation, renderGeometryFunction) { var instructions = this.instructions; - return this.replay_(context, pixelRatio, transform, renderGeometryFunction, - instructions, undefined); + return this.replay_(context, pixelRatio, transform, viewRotation, + renderGeometryFunction, instructions, undefined); }; /** * @param {CanvasRenderingContext2D} context Context. * @param {goog.vec.Mat4.Number} transform Transform. + * @param {number} viewRotation View rotation. * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render * geometry function. * @param {function(ol.geom.Geometry, Object): T=} opt_geometryCallback @@ -412,11 +419,12 @@ ol.render.canvas.Replay.prototype.replay = * @return {T|undefined} Callback result. * @template T */ -ol.render.canvas.Replay.prototype.replayHitDetection = - function(context, transform, renderGeometryFunction, opt_geometryCallback) { +ol.render.canvas.Replay.prototype.replayHitDetection = function( + context, transform, viewRotation, renderGeometryFunction, + opt_geometryCallback) { var instructions = this.hitDetectionInstructions; - return this.replay_(context, 1, transform, renderGeometryFunction, - instructions, opt_geometryCallback); + return this.replay_(context, 1, transform, viewRotation, + renderGeometryFunction, instructions, opt_geometryCallback); }; @@ -617,6 +625,12 @@ ol.render.canvas.ImageReplay = function(tolerance) { */ this.opacity_ = undefined; + /** + * @private + * @type {boolean|undefined} + */ + this.rotateWithView_ = undefined; + /** * @private * @type {number|undefined} @@ -672,6 +686,7 @@ ol.render.canvas.ImageReplay.prototype.drawPointGeometry = goog.asserts.assert(goog.isDef(this.anchorY_)); goog.asserts.assert(goog.isDef(this.height_)); goog.asserts.assert(goog.isDef(this.opacity_)); + goog.asserts.assert(goog.isDef(this.rotateWithView_)); goog.asserts.assert(goog.isDef(this.rotation_)); goog.asserts.assert(goog.isDef(this.scale_)); goog.asserts.assert(goog.isDef(this.width_)); @@ -685,15 +700,17 @@ ol.render.canvas.ImageReplay.prototype.drawPointGeometry = this.instructions.push([ ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_, // Remaining arguments to DRAW_IMAGE are in alphabetical order - this.anchorX_, this.anchorY_, this.height_, this.opacity_, this.rotation_, - this.scale_, this.snapToPixel_, this.width_ + this.anchorX_, this.anchorY_, this.height_, this.opacity_, + this.rotateWithView_, this.rotation_, this.scale_, this.snapToPixel_, + this.width_ ]); this.hitDetectionInstructions.push([ ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.hitDetectionImage_, // Remaining arguments to DRAW_IMAGE are in alphabetical order - this.anchorX_, this.anchorY_, this.height_, this.opacity_, this.rotation_, - this.scale_, this.snapToPixel_, this.width_ + this.anchorX_, this.anchorY_, this.height_, this.opacity_, + this.rotateWithView_, this.rotation_, this.scale_, this.snapToPixel_, + this.width_ ]); this.endGeometry(pointGeometry, data); }; @@ -711,6 +728,7 @@ ol.render.canvas.ImageReplay.prototype.drawMultiPointGeometry = goog.asserts.assert(goog.isDef(this.anchorY_)); goog.asserts.assert(goog.isDef(this.height_)); goog.asserts.assert(goog.isDef(this.opacity_)); + goog.asserts.assert(goog.isDef(this.rotateWithView_)); goog.asserts.assert(goog.isDef(this.rotation_)); goog.asserts.assert(goog.isDef(this.scale_)); goog.asserts.assert(goog.isDef(this.width_)); @@ -724,15 +742,17 @@ ol.render.canvas.ImageReplay.prototype.drawMultiPointGeometry = this.instructions.push([ ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_, // Remaining arguments to DRAW_IMAGE are in alphabetical order - this.anchorX_, this.anchorY_, this.height_, this.opacity_, this.rotation_, - this.scale_, this.snapToPixel_, this.width_ + this.anchorX_, this.anchorY_, this.height_, this.opacity_, + this.rotateWithView_, this.rotation_, this.scale_, this.snapToPixel_, + this.width_ ]); this.hitDetectionInstructions.push([ ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.hitDetectionImage_, // Remaining arguments to DRAW_IMAGE are in alphabetical order - this.anchorX_, this.anchorY_, this.height_, this.opacity_, this.rotation_, - this.scale_, this.snapToPixel_, this.width_ + this.anchorX_, this.anchorY_, this.height_, this.opacity_, + this.rotateWithView_, this.rotation_, this.scale_, this.snapToPixel_, + this.width_ ]); this.endGeometry(multiPointGeometry, data); }; @@ -751,6 +771,7 @@ ol.render.canvas.ImageReplay.prototype.finish = function() { this.height_ = undefined; this.scale_ = undefined; this.opacity_ = undefined; + this.rotateWithView_ = undefined; this.rotation_ = undefined; this.snapToPixel_ = undefined; this.width_ = undefined; @@ -776,6 +797,7 @@ ol.render.canvas.ImageReplay.prototype.setImageStyle = function(imageStyle) { this.image_ = image; this.height_ = size[1]; this.opacity_ = imageStyle.getOpacity(); + this.rotateWithView_ = imageStyle.getRotateWithView(); this.rotation_ = imageStyle.getRotation(); this.scale_ = imageStyle.getScale(); this.snapToPixel_ = imageStyle.getSnapToPixel(); @@ -1683,18 +1705,19 @@ ol.render.canvas.ReplayGroup = function(tolerance) { * @param {ol.Extent} extent Extent. * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. + * @param {number} viewRotation View rotation. * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render * geometry function. * @return {T|undefined} Callback result. * @template T */ ol.render.canvas.ReplayGroup.prototype.replay = function(context, extent, - pixelRatio, transform, renderGeometryFunction) { + pixelRatio, transform, viewRotation, renderGeometryFunction) { /** @type {Array.} */ var zs = goog.array.map(goog.object.getKeys(this.replaysByZIndex_), Number); goog.array.sort(zs); - return this.replay_( - zs, context, extent, pixelRatio, transform, renderGeometryFunction); + return this.replay_(zs, context, extent, pixelRatio, transform, + viewRotation, renderGeometryFunction); }; @@ -1704,6 +1727,7 @@ ol.render.canvas.ReplayGroup.prototype.replay = function(context, extent, * @param {CanvasRenderingContext2D} context Context. * @param {ol.Extent} extent Extent. * @param {goog.vec.Mat4.Number} transform Transform. + * @param {number} viewRotation View rotation. * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render * geometry function. * @param {function(ol.geom.Geometry, Object): T} geometryCallback Geometry @@ -1711,17 +1735,17 @@ ol.render.canvas.ReplayGroup.prototype.replay = function(context, extent, * @return {T|undefined} Callback result. * @template T */ -ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = - function(zs, context, extent, transform, renderGeometryFunction, - geometryCallback) { +ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function( + zs, context, extent, transform, viewRotation, renderGeometryFunction, + geometryCallback) { var i, ii, replays, replayType, replay, result; for (i = 0, ii = zs.length; i < ii; ++i) { replays = this.replaysByZIndex_[zs[i].toString()]; for (replayType in replays) { replay = replays[replayType]; if (ol.extent.intersects(extent, replay.getExtent())) { - result = replay.replayHitDetection( - context, transform, renderGeometryFunction, geometryCallback); + result = replay.replayHitDetection(context, transform, viewRotation, + renderGeometryFunction, geometryCallback); if (result) { return result; } @@ -1739,14 +1763,15 @@ ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = * @param {ol.Extent} extent Extent. * @param {number} pixelRatio Pixel ratio. * @param {goog.vec.Mat4.Number} transform Transform. + * @param {number} viewRotation View rotation. * @param {function(ol.geom.Geometry): boolean} renderGeometryFunction Render * geometry function. * @return {T|undefined} Callback result. * @template T */ -ol.render.canvas.ReplayGroup.prototype.replay_ = - function(zs, context, extent, pixelRatio, transform, - renderGeometryFunction) { +ol.render.canvas.ReplayGroup.prototype.replay_ = function( + zs, context, extent, pixelRatio, transform, viewRotation, + renderGeometryFunction) { var i, ii, j, jj, replays, replayType, replay, result; for (i = 0, ii = zs.length; i < ii; ++i) { replays = this.replaysByZIndex_[zs[i].toString()]; @@ -1754,8 +1779,8 @@ ol.render.canvas.ReplayGroup.prototype.replay_ = replay = replays[ol.render.REPLAY_ORDER[j]]; if (goog.isDef(replay) && ol.extent.intersects(extent, replay.getExtent())) { - result = replay.replay( - context, pixelRatio, transform, renderGeometryFunction); + result = replay.replay(context, pixelRatio, transform, viewRotation, + renderGeometryFunction); if (result) { return result; } @@ -1794,7 +1819,7 @@ ol.render.canvas.ReplayGroup.prototype.forEachGeometryAtPixel = function( context.clearRect(0, 0, 1, 1); return this.replayHitDetection_(zs, context, extent, transform, - renderGeometryFunction, + rotation, renderGeometryFunction, /** * @param {ol.geom.Geometry} geometry Geometry. * @param {Object} data Opaque data object. diff --git a/src/ol/renderer/canvas/canvaslayerrenderer.js b/src/ol/renderer/canvas/canvaslayerrenderer.js index e2a9ae7949..57df2fa90e 100644 --- a/src/ol/renderer/canvas/canvaslayerrenderer.js +++ b/src/ol/renderer/canvas/canvaslayerrenderer.js @@ -86,7 +86,8 @@ ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ = var transform = goog.isDef(opt_transform) ? opt_transform : this.getTransform(frameState); var render = new ol.render.canvas.Immediate( - context, frameState.pixelRatio, frameState.extent, transform); + context, frameState.pixelRatio, frameState.extent, transform, + frameState.view2DState.rotation); var composeEvent = new ol.render.Event(type, layer, render, frameState, context, null); layer.dispatchEvent(composeEvent); diff --git a/src/ol/renderer/canvas/canvasmaprenderer.js b/src/ol/renderer/canvas/canvasmaprenderer.js index 5e9469a002..793b692658 100644 --- a/src/ol/renderer/canvas/canvasmaprenderer.js +++ b/src/ol/renderer/canvas/canvasmaprenderer.js @@ -104,8 +104,8 @@ ol.renderer.canvas.Map.prototype.dispatchComposeEvent_ = -pixelRatio / view2DState.resolution, -view2DState.rotation, -view2DState.center[0], -view2DState.center[1]); - var render = new ol.render.canvas.Immediate( - context, pixelRatio, frameState.extent, this.transform_); + var render = new ol.render.canvas.Immediate(context, pixelRatio, + frameState.extent, this.transform_, view2DState.rotation); var composeEvent = new ol.render.Event(type, map, render, frameState, context, null); map.dispatchEvent(composeEvent); diff --git a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js index 9022383214..47c786aa5c 100644 --- a/src/ol/renderer/canvas/canvasvectorlayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectorlayerrenderer.js @@ -75,7 +75,7 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = context.globalAlpha = layerState.opacity; replayGroup.replay( context, frameState.extent, frameState.pixelRatio, transform, - renderGeometryFunction); + frameState.view2DState.rotation, renderGeometryFunction); } this.dispatchPostComposeEvent(context, frameState, transform); diff --git a/src/ol/source/imagevectorsource.js b/src/ol/source/imagevectorsource.js index d6050ac8d4..7ec8e04888 100644 --- a/src/ol/source/imagevectorsource.js +++ b/src/ol/source/imagevectorsource.js @@ -139,7 +139,7 @@ ol.source.ImageVector.prototype.canvasFunctionInternal_ = var transform = this.getTransform_(ol.extent.getCenter(extent), resolution, pixelRatio, size); - replayGroup.replay(this.canvasContext_, extent, pixelRatio, transform, + replayGroup.replay(this.canvasContext_, extent, pixelRatio, transform, 0, goog.functions.TRUE); this.replayGroup_ = replayGroup; diff --git a/src/ol/style/circlestyle.js b/src/ol/style/circlestyle.js index fc1b88cd17..91647681db 100644 --- a/src/ol/style/circlestyle.js +++ b/src/ol/style/circlestyle.js @@ -70,10 +70,10 @@ ol.style.Circle = function(opt_options) { goog.base(this, { opacity: 1, + rotateWithView: false, rotation: 0, scale: 1, - snapToPixel: undefined, - subtractViewRotation: false + snapToPixel: undefined }); }; diff --git a/src/ol/style/iconstyle.js b/src/ol/style/iconstyle.js index 2d38f59bfb..ccfc83b7cd 100644 --- a/src/ol/style/iconstyle.js +++ b/src/ol/style/iconstyle.js @@ -96,6 +96,12 @@ ol.style.Icon = function(opt_options) { */ var opacity = goog.isDef(options.opacity) ? options.opacity : 1; + /** + * @type {boolean} + */ + var rotateWithView = goog.isDef(options.rotateWithView) ? + options.rotateWithView : false; + /** * @type {number} */ @@ -111,7 +117,7 @@ ol.style.Icon = function(opt_options) { rotation: rotation, scale: scale, snapToPixel: undefined, - subtractViewRotation: false + rotateWithView: rotateWithView }); }; diff --git a/src/ol/style/imagestyle.js b/src/ol/style/imagestyle.js index caf76bb90d..9b0411a22f 100644 --- a/src/ol/style/imagestyle.js +++ b/src/ol/style/imagestyle.js @@ -17,10 +17,10 @@ ol.style.ImageState = { /** * @typedef {{opacity: number, + * rotateWithView: boolean, * rotation: number, * scale: number, - * snapToPixel: (boolean|undefined), - * subtractViewRotation: boolean}} + * snapToPixel: (boolean|undefined)}} */ ol.style.ImageOptions; @@ -38,6 +38,12 @@ ol.style.Image = function(options) { */ this.opacity_ = options.opacity; + /** + * @private + * @type {boolean} + */ + this.rotateWithView_ = options.rotateWithView; + /** * @private * @type {number} @@ -56,12 +62,6 @@ ol.style.Image = function(options) { */ this.snapToPixel_ = options.snapToPixel; - /** - * @private - * @type {boolean|undefined} - */ - this.subtractViewRotation_ = options.subtractViewRotation; - }; @@ -73,6 +73,14 @@ ol.style.Image.prototype.getOpacity = function() { }; +/** + * @return {boolean} Rotate with map. + */ +ol.style.Image.prototype.getRotateWithView = function() { + return this.rotateWithView_; +}; + + /** * @return {number} Rotation. */ @@ -97,14 +105,6 @@ ol.style.Image.prototype.getSnapToPixel = function() { }; -/** - * @return {boolean|undefined} Subtract view rotation? - */ -ol.style.Image.prototype.getSubtractViewRotation = function() { - return this.subtractViewRotation_; -}; - - /** * @return {Array.} Anchor. */