From 0bea162f877ee3ae220ee37d9d7596823206af94 Mon Sep 17 00:00:00 2001 From: mike-000 <49240900+mike-000@users.noreply.github.com> Date: Sun, 14 Aug 2022 19:36:04 +0100 Subject: [PATCH 1/2] fix text rotation with offset --- src/ol/render/canvas/Immediate.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/ol/render/canvas/Immediate.js b/src/ol/render/canvas/Immediate.js index db24fc488b..4ae8f80b2a 100644 --- a/src/ol/render/canvas/Immediate.js +++ b/src/ol/render/canvas/Immediate.js @@ -386,18 +386,9 @@ class CanvasImmediateRenderer extends VectorContext { this.textScale_[0] != 1 || this.textScale_[1] != 1 ) { - const localTransform = composeTransform( - this.tmpLocalTransform_, - x, - y, - 1, - 1, - rotation, - -x, - -y - ); - context.setTransform.apply(context, localTransform); - context.translate(x, y); + context.translate(x - this.textOffsetX_, y - this.textOffsetY_); + context.rotate(rotation); + context.translate(this.textOffsetX_, this.textOffsetY_); context.scale(this.textScale_[0], this.textScale_[1]); if (this.textStrokeState_) { context.strokeText(this.text_, 0, 0); From 3e0b942b150940d7caf2418e3073fcbb89402971 Mon Sep 17 00:00:00 2001 From: mike-000 <49240900+mike-000@users.noreply.github.com> Date: Tue, 16 Aug 2022 22:46:28 +0100 Subject: [PATCH 2/2] test text rotation with offset --- .../cases/text-style-offset/expected.png | Bin 0 -> 8580 bytes .../rendering/cases/text-style-offset/main.js | 121 ++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 test/rendering/cases/text-style-offset/expected.png create mode 100644 test/rendering/cases/text-style-offset/main.js diff --git a/test/rendering/cases/text-style-offset/expected.png b/test/rendering/cases/text-style-offset/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..e7167fc1d03ea208e625a2944302f9fd357718b3 GIT binary patch literal 8580 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 literal 0 HcmV?d00001 diff --git a/test/rendering/cases/text-style-offset/main.js b/test/rendering/cases/text-style-offset/main.js new file mode 100644 index 0000000000..398eef4fa8 --- /dev/null +++ b/test/rendering/cases/text-style-offset/main.js @@ -0,0 +1,121 @@ +import Circle from '../../../../src/ol/style/Circle.js'; +import Feature from '../../../../src/ol/Feature.js'; +import Fill from '../../../../src/ol/style/Fill.js'; +import Map from '../../../../src/ol/Map.js'; +import Point from '../../../../src/ol/geom/Point.js'; +import Stroke from '../../../../src/ol/style/Stroke.js'; +import Style from '../../../../src/ol/style/Style.js'; +import Text from '../../../../src/ol/style/Text.js'; +import VectorLayer from '../../../../src/ol/layer/Vector.js'; +import VectorSource from '../../../../src/ol/source/Vector.js'; +import View from '../../../../src/ol/View.js'; +import {getVectorContext} from '../../../../src/ol/render.js'; + +const offsetX = new Style({ + image: new Circle({ + radius: 5, + fill: new Fill({ + color: 'green', + }), + }), + text: new Text({ + font: '24px Ubuntu', + text: 'offsetX', + offsetX: -40, + rotation: Math.PI / 4, + fill: new Stroke({ + color: 'green', + }), + }), +}); + +const noOffset = new Style({ + image: new Circle({ + radius: 5, + fill: new Fill({ + color: 'black', + }), + }), + text: new Text({ + font: '24px Ubuntu', + text: 'no offset', + rotation: Math.PI / 4, + fill: new Stroke({ + color: 'black', + }), + }), +}); + +const offsetY = new Style({ + image: new Circle({ + radius: 5, + fill: new Fill({ + color: 'red', + }), + }), + text: new Text({ + font: '24px Ubuntu', + text: 'offsetY', + offsetY: -20, + rotation: Math.PI / 4, + fill: new Stroke({ + color: 'red', + }), + }), +}); + +const vectorSource = new VectorSource(); +const vectorLayer = new VectorLayer({ + source: vectorSource, +}); + +let feature; + +feature = new Feature({ + geometry: new Point([-50, -50]), +}); +feature.setStyle(offsetX); +vectorSource.addFeature(feature); + +feature = new Feature({ + geometry: new Point([-50, 0]), +}); +feature.setStyle(noOffset); +vectorSource.addFeature(feature); + +feature = new Feature({ + geometry: new Point([-50, 50]), +}); +feature.setStyle(offsetY); +vectorSource.addFeature(feature); + +vectorLayer.on('postrender', function (event) { + const vectorContext = getVectorContext(event); + + feature = new Feature({ + geometry: new Point([50, -50]), + }); + vectorContext.drawFeature(feature, offsetX); + + feature = new Feature({ + geometry: new Point([50, 0]), + }); + vectorContext.drawFeature(feature, noOffset); + + feature = new Feature({ + geometry: new Point([50, 50]), + }); + vectorContext.drawFeature(feature, offsetY); +}); + +new Map({ + pixelRatio: 1, + layers: [vectorLayer], + target: 'map', + view: new View({ + center: [0, 0], + resolution: 1, + }), +}); + +render({tolerance: 0.02});