From ea3c6587a242b3a27719becd29bfc074ca679862 Mon Sep 17 00:00:00 2001 From: Andrew Harvey Date: Mon, 21 Oct 2019 13:56:34 +1100 Subject: [PATCH 1/5] add essential option to AnimationOptions to ignore prefers-reduced-motion for essential animations --- src/ui/camera.js | 12 ++++++++---- test/unit/ui/camera.test.js | 8 ++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/ui/camera.js b/src/ui/camera.js index 126fc8288ad..e38c4452186 100644 --- a/src/ui/camera.js +++ b/src/ui/camera.js @@ -55,12 +55,15 @@ export type CameraOptions = { * the initial state and 1 is the final state. * @property {PointLike} offset of the target center relative to real map container center at the end of animation. * @property {boolean} animate If `false`, no animation will occur. + * @property {boolean} essential If `true`, then the animation is considered essential and will not be affected by + * [`prefers-reduced-motion`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion). */ export type AnimationOptions = { duration?: number, easing?: (number) => number, offset?: PointLike, - animate?: boolean + animate?: boolean, + essential?: boolean }; /** @@ -655,7 +658,8 @@ class Camera extends Evented { * details not specified in `options`. * * Note: The transition will happen instantly if the user has enabled - * the `reduced motion` accesibility feature enabled in their operating system. + * the `reduced motion` accesibility feature enabled in their operating system, unless options includes + * `essential: true`. * * @memberof Map# * @param options Options describing the destination and animation of the transition. @@ -683,7 +687,7 @@ class Camera extends Evented { easing: defaultEasing }, options); - if (options.animate === false || browser.prefersReducedMotion) options.duration = 0; + if (options.animate === false || (!options.essential && browser.prefersReducedMotion)) options.duration = 0; const tr = this.transform, startZoom = this.getZoom(), @@ -865,7 +869,7 @@ class Camera extends Evented { */ flyTo(options: Object, eventData?: Object) { // Fall through to jumpTo if user has set prefers-reduced-motion - if (browser.prefersReducedMotion) { + if (!options.essential && browser.prefersReducedMotion) { const coercedOptions = (pick(options, ['center', 'zoom', 'bearing', 'pitch', 'around']): CameraOptions); return this.jumpTo(coercedOptions, eventData); } diff --git a/test/unit/ui/camera.test.js b/test/unit/ui/camera.test.js index 49f7af4be7e..4b709edf474 100644 --- a/test/unit/ui/camera.test.js +++ b/test/unit/ui/camera.test.js @@ -889,6 +889,14 @@ test('camera', (t) => { camera.easeTo({center: [100, 0], zoom: 3.2, bearing: 90, duration: 1000}); }); + t.test('annimation occurs when prefers-reduced-motion: reduce is set but overiden by essential: true', (t) => { + const camera = createCamera(); + const stub = t.stub(browser, 'prefersReducedMotion'); + stub.get(() => true); + assertTransitionTime(t, camera, 100, 110); + camera.easeTo({center: [100, 0], zoom: 3.2, bearing: 90, duration: 100, essential: true}); + }); + t.end(); }); From faf305174b6faddb14adfc2f6d85eaf78ba909ab Mon Sep 17 00:00:00 2001 From: Andrew Harvey Date: Mon, 21 Oct 2019 14:13:54 +1100 Subject: [PATCH 2/5] typos --- test/unit/ui/camera.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/ui/camera.test.js b/test/unit/ui/camera.test.js index 4b709edf474..5c7ce31c602 100644 --- a/test/unit/ui/camera.test.js +++ b/test/unit/ui/camera.test.js @@ -889,7 +889,7 @@ test('camera', (t) => { camera.easeTo({center: [100, 0], zoom: 3.2, bearing: 90, duration: 1000}); }); - t.test('annimation occurs when prefers-reduced-motion: reduce is set but overiden by essential: true', (t) => { + t.test('animation occurs when prefers-reduced-motion: reduce is set but overridden by essential: true', (t) => { const camera = createCamera(); const stub = t.stub(browser, 'prefersReducedMotion'); stub.get(() => true); From 812e1fdfcea8a0bc8ccdfd5033cb763a3144de6d Mon Sep 17 00:00:00 2001 From: Andrew Harvey Date: Mon, 28 Oct 2019 14:29:47 +1100 Subject: [PATCH 3/5] fix unit test for ensuring animation occurs when prefers-reduced-motion: reduce is set but overriden by essential: true --- test/unit/ui/camera.test.js | 42 ++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/test/unit/ui/camera.test.js b/test/unit/ui/camera.test.js index 5c7ce31c602..97f40b17cd4 100644 --- a/test/unit/ui/camera.test.js +++ b/test/unit/ui/camera.test.js @@ -881,6 +881,41 @@ test('camera', (t) => { }, 0); }); + t.test('animation occurs when prefers-reduced-motion: reduce is set but overridden by essential: true', (t) => { + const camera = createCamera(); + const stubPrefersReducedMotion = t.stub(browser, 'prefersReducedMotion'); + const stubNow = t.stub(browser, 'now'); + + stubPrefersReducedMotion.get(() => true); + + // camera transition expected to take in this range when prefersReducedMotion is set and essential: true, + // when a duration of 200 is requested + const min = 100; + const max = 300; + + let startTime; + camera + .on('movestart', () => { startTime = browser.now(); }) + .on('moveend', () => { + const endTime = browser.now(); + const timeDiff = endTime - startTime; + t.ok(timeDiff >= min && timeDiff < max, `Camera transition time exceeded expected range( [${min},${max}) ) :${timeDiff}`); + t.end(); + }); + + setTimeout(() => { + stubNow.callsFake(() => 0); + camera.simulateFrame(); + + camera.easeTo({center: [100, 0], zoom: 3.2, bearing: 90, duration: 200, essential: true}); + + setTimeout(() => { + stubNow.callsFake(() => 200); + camera.simulateFrame(); + }, 0); + }, 0); + }); + t.test('duration is 0 when prefers-reduced-motion: reduce is set', (t) => { const camera = createCamera(); const stub = t.stub(browser, 'prefersReducedMotion'); @@ -889,13 +924,6 @@ test('camera', (t) => { camera.easeTo({center: [100, 0], zoom: 3.2, bearing: 90, duration: 1000}); }); - t.test('animation occurs when prefers-reduced-motion: reduce is set but overridden by essential: true', (t) => { - const camera = createCamera(); - const stub = t.stub(browser, 'prefersReducedMotion'); - stub.get(() => true); - assertTransitionTime(t, camera, 100, 110); - camera.easeTo({center: [100, 0], zoom: 3.2, bearing: 90, duration: 100, essential: true}); - }); t.end(); }); From 70b3bfc67894a8310e7154c1a254c2c3da050672 Mon Sep 17 00:00:00 2001 From: Andrew Harvey Date: Mon, 28 Oct 2019 14:32:07 +1100 Subject: [PATCH 4/5] remove empty new line --- test/unit/ui/camera.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/ui/camera.test.js b/test/unit/ui/camera.test.js index 97f40b17cd4..a9f82c6192f 100644 --- a/test/unit/ui/camera.test.js +++ b/test/unit/ui/camera.test.js @@ -924,7 +924,6 @@ test('camera', (t) => { camera.easeTo({center: [100, 0], zoom: 3.2, bearing: 90, duration: 1000}); }); - t.end(); }); From 3435763e563015eef4991b1dbba1cbad0a6163fa Mon Sep 17 00:00:00 2001 From: Andrew Harvey Date: Mon, 28 Oct 2019 16:49:00 +1100 Subject: [PATCH 5/5] include extra documentation on essential: true in flyTo and easeTo documentation --- src/ui/camera.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ui/camera.js b/src/ui/camera.js index e38c4452186..7b88df5eca5 100644 --- a/src/ui/camera.js +++ b/src/ui/camera.js @@ -658,8 +658,8 @@ class Camera extends Evented { * details not specified in `options`. * * Note: The transition will happen instantly if the user has enabled - * the `reduced motion` accesibility feature enabled in their operating system, unless options includes - * `essential: true`. + * the `reduced motion` accesibility feature enabled in their operating system, + * unless 'options' includes `essential: true`. * * @memberof Map# * @param options Options describing the destination and animation of the transition. @@ -815,7 +815,8 @@ class Camera extends Evented { * the user maintain her bearings even after traversing a great distance. * * Note: The animation will be skipped, and this will behave equivalently to `jumpTo` - * if the user has the `reduced motion` accesibility feature enabled in their operating system. + * if the user has the `reduced motion` accesibility feature enabled in their operating system, + * unless 'options' includes `essential: true`. * * @memberof Map# * @param {Object} options Options describing the destination and animation of the transition.