Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 52 additions & 130 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,162 +1,84 @@
# CAT - CSS Animation Timeline

[![Travis CI Build Status](https://travis-ci.org/artoale/angular-cat.svg)](https://travis-ci.org/artoale/angular-cat)
[![codecov.io](https://codecov.io/github/artoale/angular-cat/coverage.svg?branch=master)](https://codecov.io/github/artoale/angular-cat?branch=master)
[![Travis CI Build Status](https://travis-ci.org/artoale/angular-cat.svg)](https://travis-ci.org/artoale/angular-cat) [![codecov.io](https://codecov.io/github/artoale/angular-cat/coverage.svg?branch=master)](https://codecov.io/github/artoale/angular-cat?branch=master)

Set of AngularJS directives to simplify development and composition of
animations on static websites.
Set of AngularJS directives to simplify development and composition of animations on static websites.

## Why
Most modern "static" websites, have loads of complicated animations, often built
out of smaller bits.
You need to sequence CSS transition, CSS animations and custom javascript stuff, manage
scroll-based trigger, make those repeatable.

You don't wont to stick all this complexity in a controller which not only shouldn't be there just because of animations,
you'll also end up having code duplication and find yourself in a code maintenance hell.
Most modern "static" websites, have loads of complicated animations, often built out of smaller bits. You need to sequence CSS transition, CSS animations and custom javascript stuff, manage scroll-based trigger, make those repeatable.

You don't wont to stick all this complexity in a controller which not only shouldn't be there just because of animations, you'll also end up having code duplication and find yourself in a code maintenance hell.

## The solution

A set of
* Declarative
* Reusable
* Composable
* Nestable

- Declarative
- Reusable
- Composable
- Nestable

AngularJS directives!

## Components
## Installation

### cat-scroll-container and cat-visible directives
Detect when an element is fully visible (and fully hidden) in page, and sets
a scope variable accordingly
You can do the usual, with npm

```html
<body cat-scroll-container>
[...]
<div cat-visible="runAnimation">
When I'm visible, `runAnimation` is set to true
</div>
[...]
</body>
```
At the moment, these work only when there are no "nested" scrolling container.

### cat-class directive

Play/stop CSS based animation using a `--start` class modifier.


```html
<style>
.a-class-name {
color: red;
transition: color 1s linear;
}

.a-class-name--start {
color: blue;
transition: none;
}
</style>
<div cat-class="a-class-name"
cat-active="trigger"
cat-undo="1">I am a red text!</div>
<button ng-click="trigger = !trigger">Toggle status</button>
npm install angular-cat
```

The fact that animations are defined "backward", makes it way easier to write CSS
for browser where you don't wont animations to run (mobile, legacy). The final status
of the animation is defined by its default style (`.a-class-name`), while the
`--start` version specifies how to set up the animation.
or, with bower

Note that we use `transition: none` to avoid running the transition "backward", when resetting it (but we could, if we wanted to!)

### cat-delay directive

Introduce a delay in an animation sequence. This is particularly useful when you're sharing
sub-animations and you need to fine tune delays on a per-case scenario.
```
bower install angular-cat
```

Both regular and minified files can be found in the `dist/` folder.

### cat-timeline directive
## Use with angular-spy

Combine all its children directive and, (if `cat-active` is set) runs them in
sequence.
tl;dr - If you need to run animations on scroll, have a look at [angular-spy](https://github.com/flea89/angular-spy) which works very well with angular-cat.

This is where most of the magic happens. You can use the timeline to play a sequence
of simple animations, nest them, or run them in whatever order you want!
Originally, angular-cat shipped with directives to handle scroll-based triggers. We realized though, that coordinating CSS animation and handling scroll-spies are two, quite different things, which can be very useful both by themselves or used together. We decided then to split the two, keep responsibility separated, footprint smaller and allow for more flexibility.

By default, the animations are run in sequence, and not repeated unless `cat-undo` is specified.
## At a glance

```html
<div cat-timeline cat-active="sequence" cat-undo="1">
<div cat-class="animation-1"></div>
<button ng-click="sequence = true">Run the animation!</button>
<div cat-timeline
cat-active="sequence"
cat-undo="true">

<div cat-class="animation-1">I'll be red</div>
<div cat-delay="500"></div>
<div cat-class="animation-2"> </div>
<div cat-class="animation-2">I'll be wider</div>
</div>
```


## APIs

All directives can be controlled both declarative, via HTML attributes, or
programmatically, by requiring their angular controller.

For most use cases, HTML attributes should be enough. You should care about the programmatic interface only if
you're writing custom directives that needs to integrate with the timeline (or if you're contributing to this project!)

### Shared HTML interface

#### `cat-active`
Used to trigger the animation when changes to true. It should be used as a "read only" scope variable by the animation directives and set from the outside (e.g. by `cat-visible`).

#### `cat-undo`
Default: **false**

Tells the directive that the animation should be "cleared" (resetted) when `cat-active` switches back to `false`

#### `cat-animation-name`
Defaults to the directive name

Name to be used when registering the animation on the parent `cat-timeline`.

#### `cat-status`
Read-only variable (written by the directives). Can be used to check the animation
status. Can be 'READY', 'RUNNING', 'CLEARING' or 'FINISHED'. Very useful if you want to
play animations only when other are finished, but don't or can't create a "global" animation for all of them.


### Additional HTML APIs
Not shared among all directives

#### `cat-class="<class-name>"`
Tells the directive to use `<class-name>` as CSS animation class: this will make the animation
add a `<class-name>--start` class to set-up the animation.

#### `cat-delay="<millis>"`
How long to wait, in milliseconds.


### Shared JS interface

### `controller.play() : Promise`
Start the animation and returns a promise, resolved when the animation is over.
If called when the animation is already running, the same promise is returned.

### `controller.clear() : Promise`
Reset the animation to its initial state, returning a promise resolved when the
clearing operation is finished.

#### Additional JS APIs

### `timelineController.register(animationName: string, animationController [, order: number])`
Called by "component" directives to register themselves. The order parameter is
currently only available via JS APIs, but will be added as a shared attribute in
the future.
<style>
.animation-1 {
color: red;
transition: color 1s linear;
}

.animation-1--start {
color: blue;
}

.animation-2 {
width: 500px;
transition: width 1s linear;
}

.animation-2--start {
width: 300px;
}
</style>
```

### `timelineController.get()` //TODO
Not implemented yet, should allow to get a children animation from the controller
for custom animation ordering and sequencing (e.g. first two in parralle, than the third, than another two...)
As you can see, the basic usage is declarative, expressive and CSS friendly.

## Resources

[![Analytics](https://ga-beacon.appspot.com/UA-39387573-2/potato-animation/readme?pixel)](https://github.com/igrigorik/ga-beacon)
For more information and resources head to our [guide](https://artoale.gitbooks.io/angular-cat/content/index.html) or have a look at the [examples](https://github.com/artoale/angular-cat/tree/master/example).
12 changes: 12 additions & 0 deletions book.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"gitbook": "2.5.2",
"structure": {
"summary": "docs/README.md"
},
"plugins": ["github"],
"pluginsConfig": {
"github": {
"url": "https://github.com/artoale/angular-cat/"
}
}
}
3 changes: 2 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"angular-animate": "~1.4.3"
},
"devDependencies": {
"angular-mocks": "~1.4.3"
"angular-mocks": "~1.4.3",
"angular-spy": "~0.0.3"
}
}
6 changes: 6 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Table of contents

- [API Reference](/docs/api/README.md)

- [Directives](/docs/api/Directives.md)
- [Services](/docs/api/Services.md)
94 changes: 94 additions & 0 deletions docs/api/Directives.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Directives documentation

Here you can find directives specific APIs and description. Bear in mind that all directives share a common HTML and JS API, described [here](./README.md).

## catClass

Trigger CSS animation playback.

It works by adding a class on setup and then removing it when `cat-active` expression evaluates to true. The class is constructed by adding the `--start` suffix to the `cat-class` attribute value.

As you can see, animation are written inside-out to make it easy to support browser where you don't want to run animations (mobile, legacy) or even when javascript is disabled (in which case you won't have any animation, but the final state will be there).

### Usage example

```html
<style>
.a-class-name {
color: red;
transition: color 1s linear;
}

.a-class-name--start {
color: blue;
}
</style>


<div cat-class="a-class-name"
cat-active="trigger"
cat-undo="true">I am a red text!</div>
<button ng-click="trigger = !trigger">Toggle status</button>
```

### Additional HTML APIs

#### `cat-class` attribute

Specifies the class which defines the animation. Note that the directive automatically adds this class to the element `classList` so you won't need to add it unless you need to support browser with no javascript.

--------------------------------------------------------------------------------

## catTimeline

Combine all its children directives and runs them in sequence.

This is where most of the magic happens. All anglar-cat directives register themselves on the first parent `cat-timeline` (if any). The timeline supports basic sequence animation by default, but you can customize it easily.

Please note that `cat-timeline` is an animation itself, meaning that you can nest them as much as you want, to build up complex sequences from simple ones.

### Usage example

```html
<div cat-timeline cat-active="sequence" cat-undo="1">
<div cat-class="animation-1"></div>
<div cat-delay="500"></div>
<div cat-class="animation-2"></div>
</div>
```

### Additional JS APIs

#### `timelineController.register(animationName: string, animationController [, order: number])`

Called by "component" directives to register themselves. The order parameter is currently only available via JS APIs, but we plan on adding it in a future release.

#### `timelineController.getAnimation(animationName: string) : animationController`

Return a registered animation by name.

#### `timelineController.getAllAnimations(): object<animationName: animationController>`

Get all animations controller registered on the timeline controller. Returns an object hash with the animation name as key, the controller as value.

#### `timelineController.setCustomAnimation(customRunAnimation: fn)`

Specify a custom function for running the animation.

The function is passed a promise to wait on and should return a promise resolved when the compound animation is finished. See the `cat-timeline` demo for an example of how to write custom animation timelines.

--------------------------------------------------------------------------------

## catDelay

Animations that just waits for the given time in milliseconds.

### Usage example

This directive, practically useless on its own, is very powerful and useful when dealing with complex animation since it allows to introduce delays declaratively. It allows to keep delays outside of CSS transitions and animations, making them much more reusable.

Delay specified in milliseconds.

```html
<div cat-delay="3000"></div>
```
55 changes: 55 additions & 0 deletions docs/api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# API Reference

All the built-in directives share a common interface, accessible both via html attributes and via a javascript interface, which can be accessed by requiring the directive controller in your own custom directive.

In this documentation we sometimes refer to attributes as **read-only** when we intend that only the directive should write these variable (not you!) and **write-only** when a variable is guaranteed to never be set by the directive, but only meant to be set by the outside (you!).

## HTML attributes

`cat-active` _expression_ | **write-only**

Used to trigger the animation when the expression evaluates to true. It should be used as a _write-only_ scope variable by the animation directives and set from the outside (e.g. by `spy-visible`).

If you write a custom animation you should never set this variable.

`cat-undo` _expression_ | Default: `false`

Tells the directive that the animation should be "cleared" (resetted) when `cat-active` switches back to `false`. This allow to replay the animations more then once

`cat-disabled` _expression_ | Default: `false`

Specify that the animation should be disabled. This can be changed dynamically to disable animations depending on your animation status

`cat-animation-name` _string_ | Defaults to the directive name

Name to be used when registering the animation on the parent `cat-timeline`.

`cat-status` _expression_ | **read-only**

Read-only variable (written by the directives). Can be used to check the animation status. It can assume the values of 'READY', 'RUNNING', 'SEEKING' or 'FINISHED'.

Very useful if you want to play animations only when other are finished, but don't or can't create a "wrapper" animation for all of them.

## Animation JS interface

All APIs return a promise, which is resolved when the relative action is successfully completed, or rejected otherwise.

To get an instance of the animation controller you can either require it directly in your own directives or use `timeline` specific functions if you are writing a custom timeline.

`controller.play() : Promise`

Start the animation and returns a promise, resolved when the animation is over. If called when the animation is already running, the same promise is returned.

`controller.seek(progress: string) : Promise`

Argument `progress` can be either the `'start'` or `'end'` string.

Seek to the end or the beginning of the animation, based on the passed parameter. If called when the animation is `RUNNING` it causes the play promise to be rejected.

`controller.setDisabled(disabled: boolean) : Promise`

Set the disabled status of the animation.

`controller.setUp() : Promise`

Called by the linking function on all animation directives to notify the controller that the animation is ready. You should probably never need to call this yourself.
Loading