From cb3d76889d15470395c4f2cebf4d8ec761bc83dd Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Thu, 1 Jul 2021 09:34:00 -0400 Subject: [PATCH] improve sl-animation --- docs/components/animation.md | 45 ++++++++++++++++++------- docs/resources/changelog.md | 10 ++++++ src/components/animation/animation.ts | 48 ++++++++++++++++----------- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/docs/components/animation.md b/docs/components/animation.md index 459b798f..fa78af38 100644 --- a/docs/components/animation.md +++ b/docs/components/animation.md @@ -4,14 +4,14 @@ Animate elements declaratively with nearly 100 baked-in presets, or roll your own with custom keyframes. Powered by the [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API). -To animate an element, wrap it in `` and set a `name` and `duration`. Refer to the [properties table](#properties) for additional options. +To animate an element, wrap it in `` and set an animation `name`. The animation not start until you add the `play` attribute. Refer to the [properties table](#properties) for a list of all animation options. ```html preview
-
-
-
-
+
+
+
+
``` -?> The animation will be applied only to the first child element found in ``. +?> The animation will only be applied to the first child element found in ``. ## Examples @@ -35,7 +35,7 @@ This example demonstrates all of the baked-in animations and easings. Animations ```html preview
- +
@@ -115,11 +115,10 @@ Use an [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/ const observer = new IntersectionObserver(entries => { if (entries[0].isIntersecting) { // Start the animation when the box enters the viewport - animation.pause = null; + animation.play = true; } else { - // Reset the animation when the box leaves the viewport - animation.pause = true; - animation.setCurrentTime(0); + animation.play = false; + animation.currentTime = 0; } }); observer.observe(box); @@ -141,7 +140,7 @@ Supply your own [keyframe formats](https://developer.mozilla.org/en-US/docs/Web/ ```html preview
- +
@@ -175,4 +174,26 @@ Supply your own [keyframe formats](https://developer.mozilla.org/en-US/docs/Web/ ``` +### Playing Animations on Demand + +Animations won't play until you apply the `play` attribute. You can omit it initially, then apply it on demand such as after a user interaction. In this example, the button will animate once every time the button is clicked. + +```html preview +
+ + Click me + +
+ + +``` + [component-metadata:sl-animation] diff --git a/docs/resources/changelog.md b/docs/resources/changelog.md index 332fd999..69e5bc4c 100644 --- a/docs/resources/changelog.md +++ b/docs/resources/changelog.md @@ -6,6 +6,16 @@ Components with the Experimental badge _During the beta period, these restrictions may be relaxed in the event of a mission-critical bug._ 🐛 +## 2.0.0-beta.46 + +This release improves the developer experience of ``. Previously, an animation was assumed to be playing unless the `pause` attribute was set. This behavior has been reversed and `pause` has been removed. Now, animations will not play until the new `play` attribute is applied. + +This is a lot more intuitive and makes it easier to activate animations imperatively. In addition, the `play` attribute is automatically removed automatically when the animation finishes or cancels, making it easier to restart finite animations. Lastly, the animation's timing is now accessible through the new `currentTime` property instead of `getCurrentTime()` and `setCurrentTime()`. + +- 🚨 BREAKING: removed the `pause` prop from `sl-animation` (use the `play` prop to start and stop the animation instead) +- 🚨 BREAKING: removed `getCurrentTime()` and `setCurrentTime()` from `sl-animation` (use the `currentTime` property instead) +- Added `currentTime` to `sl-animation` to control the current time without methods + ## 2.0.0-beta.45 This release changes the way component metadata is generated. Previously, the project used TypeDoc to analyze components and generate a very large file with type data. The data was then parsed and converted to an easier-to-consume file called `metadata.json`. Alas, TypeDoc is expensive to run and the metadata format wasn't standard. diff --git a/src/components/animation/animation.ts b/src/components/animation/animation.ts index 840b9755..5e4d2ca9 100644 --- a/src/components/animation/animation.ts +++ b/src/components/animation/animation.ts @@ -27,6 +27,12 @@ export default class SlAnimation extends LitElement { /** The name of the built-in animation to use. For custom animations, use the `keyframes` prop. */ @property() name = 'none'; + /** + * Plays the animation. When omitted, the animation will be paused. This prop will be automatically removed when the + * animation finishes or gets canceled. + */ + @property({ type: Boolean, reflect: true }) play = false; + /** The number of milliseconds to delay the start of the animation. */ @property({ type: Number }) delay = 0; @@ -64,8 +70,16 @@ export default class SlAnimation extends LitElement { */ @property({ attribute: 'playback-rate', type: Number }) playbackRate = 1; - /** Pauses the animation. The animation will resume when this prop is removed. */ - @property({ type: Boolean }) pause = false; + /** Gets and sets the current animation time. */ + get currentTime(): number { + return this.animation?.currentTime || 0; + } + + set currentTime(time: number) { + if (this.animation) { + this.animation.currentTime = time; + } + } connectedCallback() { super.connectedCallback(); @@ -98,23 +112,27 @@ export default class SlAnimation extends LitElement { } handleAnimationFinish() { + this.play = false; + this.hasStarted = false; emit(this, 'sl-finish'); } handleAnimationCancel() { + this.play = false; + this.hasStarted = false; emit(this, 'sl-cancel'); } - @watch('pause') - handlePauseChange() { + @watch('play') + handlePlayChange() { if (this.animation) { - this.pause ? this.animation.pause() : this.animation.play(); - - if (!this.pause && !this.hasStarted) { + if (this.play && !this.hasStarted) { this.hasStarted = true; emit(this, 'sl-start'); } + this.play ? this.animation.play() : this.animation.pause(); + return true; } else { return false; @@ -158,11 +176,11 @@ export default class SlAnimation extends LitElement { this.animation.addEventListener('cancel', this.handleAnimationCancel); this.animation.addEventListener('finish', this.handleAnimationFinish); - if (this.pause) { - this.animation.pause(); - } else { + if (this.play) { this.hasStarted = true; emit(this, 'sl-start'); + } else { + this.animation.pause(); } return true; @@ -191,16 +209,6 @@ export default class SlAnimation extends LitElement { } catch {} } - /** Gets the current time of the animation in milliseconds. */ - getCurrentTime() { - return this.animation.currentTime; - } - - /** Sets the current time of the animation in milliseconds. */ - setCurrentTime(time: number) { - this.animation.currentTime = time; - } - render() { return html` `; }