Skip to content

Commit

Permalink
Adds default 'both' property to 'animation.type'
Browse files Browse the repository at this point in the history
  • Loading branch information
putnikproj authored Jul 19, 2022
1 parent f43dffe commit f9f12e1
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 26 deletions.
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ And then of course you should configure classnames and other parameters in JavaS
* @default
* undefined
*/
prefix?: string;
prefix: string;
/**
* ClassName which element contains before animation starts and should be deleted when animation starts
* @default ''
Expand All @@ -134,7 +134,7 @@ And then of course you should configure classnames and other parameters in JavaS
/**
* ClassName which element contains during the whole animation.
* Usually there you write `animation` or `transition` css properties.
* (on: 1st or 2nd frame, off: last frame)
* (on: 1st frame, off: last frame)
* @default ''
*/
active: string;
Expand All @@ -156,14 +156,15 @@ And then of course you should configure classnames and other parameters in JavaS
animation: {
/**
* When you add animations with css, you can do this either with `transition` or with `animation` property
* You should choose one of this for correct animation end detecting.
* *If you have problems with detecting animation end, see `animation.end`*
* @default 'transition'
* You should choose one of this for correct animation end detecting if you have problems.
* By default ElAnimate adds both `transitionend` and `animationend` handlers
* As a last resort, you can set `animation.name`
* @default 'both'
*/
type: 'transition' | 'animation';
type: 'transition' | 'animation' | 'both';
/**
* if you have several animation, you can additionally set `animation.name` field in config
* Then el-animate can properly detect animation end with this animation name.
* Then ElAnimate can properly detect animation end with this animation name.
* You should type the same string as in @keyframes
*/
name: string | undefined;
Expand Down Expand Up @@ -192,7 +193,7 @@ And then of course you should configure classnames and other parameters in JavaS
* - `restart` means that we should stop current animation and start the new one
* - `replaceToState` means that we only replace final points of animation
* (el-animate replaces `to` className and animation end handler). **Useful if `animation.type` is `transition`.
* Then animtion Then the animation continues without interruption**
* Then the animation continues without interruption**
* @default 'restart'
*/
multiCallHandling: 'block' | 'restart' | 'replaceToState';
Expand All @@ -203,7 +204,7 @@ Also, if in some moment you need to cancel animation and return it to initial po

## Demos

All demos are available [here on codepen.io](https://codepen.io/collection/warqKo?grid_type=list)
All demos are available [here on codepen.io](https://codepen.io/collection/warqKo?grid_type=list). We highly recommend to view them.

## Build

Expand Down
17 changes: 17 additions & 0 deletions playground/scripts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ changeStateButton.addEventListener('click', () => {
},
multiCallHandling: 'replaceToState',
});
animate(target, {
classNames: {
prefix: 'enter',
initial: 'hidden',
},
animation: {
type: 'animation',
},
multiCallHandling: 'replaceToState',
});

return;
}
Expand All @@ -58,4 +68,11 @@ changeStateButton.addEventListener('click', () => {
},
multiCallHandling: 'replaceToState',
});
animate(target, {
classNames: {
prefix: 'leave',
final: 'hidden',
},
multiCallHandling: 'replaceToState',
});
});
43 changes: 37 additions & 6 deletions src/animate/animation-end-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,36 +27,67 @@ export function removeAnimationEndEventListener(elem: HTMLElement) {
return;
}

elem.removeEventListener(animationInfo.eventName, animationInfo.handler);
animationInfo.handlers.forEach((handler) => {
elem.removeEventListener(handler.eventName, handler.function);
});
setIdleState(elem, animationInfo.classNames);
clearAnimationInformation(elem);
}

function addAnimationEndEventListener(elem: HTMLElement, config: Config, cb: () => void) {
const { animation, classNames } = config;
const eventName = getEventName(animation.type);

// Create handlers
const baseHandler = () => {
removeAnimationEndEventListener(elem);
cb();
};

const cssAnimationHandler = (evt: AnimationEvent) => {
const cssAnimationHandler = (evt: AnimationEvent | TransitionEvent) => {
const animEvt = evt as AnimationEvent;
// If user specified animation name, we should call cb only if event refers to the right animation
if (evt.animationName && animation.name && evt.animationName !== animation.name) {
if (animEvt.animationName && animation.name && animEvt.animationName !== animation.name) {
return;
}

baseHandler();
};

// Choose which handlers should add to elem
if (animation.type === 'both') {
elem.addEventListener(AnimationEndEvent.TRANSITION, baseHandler);
elem.addEventListener(AnimationEndEvent.ANIMATION, cssAnimationHandler);
setAnimationInformation(elem, {
classNames,
handlers: [
{
eventName: AnimationEndEvent.TRANSITION,
function: baseHandler,
},
{
eventName: AnimationEndEvent.ANIMATION,
function: cssAnimationHandler,
},
],
});
return;
}

const handler = (evt: TransitionEvent | AnimationEvent) =>
animation.type === AnimationType.ANIMATION
? cssAnimationHandler(evt as AnimationEvent)
: baseHandler();

const eventName = getEventName(animation.type);
elem.addEventListener(eventName, handler);
setAnimationInformation(elem, { handler, classNames, eventName });
setAnimationInformation(elem, {
classNames,
handlers: [
{
eventName,
function: handler,
},
],
});
}

export default function createAnimationEndHandler(
Expand Down
8 changes: 6 additions & 2 deletions src/animate/animation-information.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ const ANIMATION_END_PROPERTY_SETTINGS: PropertyDescriptor = {

type AnimationEndHandler = (evt: AnimationEvent | TransitionEvent) => void;

type AnimationInformation = {
handler: AnimationEndHandler;
type EventListenerHandler = {
function: AnimationEndHandler;
eventName: AnimationEndEvent;
};

type AnimationInformation = {
handlers: EventListenerHandler[];
classNames: Config['classNames'];
};

Expand Down
19 changes: 10 additions & 9 deletions src/animate/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AnimationType, AnimationTypeUnion } from '../helpers/enum';
import { AnimationTypeUnion } from '../helpers/enum';

type Callback = (elem: HTMLElement, currentConfig: Config) => void;

Expand Down Expand Up @@ -29,7 +29,7 @@ export interface Config {
/**
* ClassName which element contains during the whole animation.
* Usually there you write `animation` or `transition` css properties.
* (on: 1st or 2nd frame, off: last frame)
* (on: 1st frame, off: last frame)
* @default ''
*/
active: string;
Expand All @@ -51,14 +51,15 @@ export interface Config {
animation: {
/**
* When you add animations with css, you can do this either with `transition` or with `animation` property
* You should choose one of this for correct animation end detecting.
* *If you have problems with detecting animation end, see `animation.end`*
* @default 'transition'
* By default ElAnimate adds both `transitionend` and `animationend` handlers
* You should choose one of this for correct animation end detecting if you have problems.
* As a last resort, you can set `animation.name`
* @default 'both'
*/
type: AnimationTypeUnion;
type: AnimationTypeUnion | 'both';
/**
* if you have several animation, you can additionally set `animation.name` field in config
* Then el-animate can properly detect animation end with this animation name.
* Then ElAnimate can properly detect animation end with this animation name.
* You should type the same string as in @keyframes
*/
name: string | undefined;
Expand Down Expand Up @@ -87,7 +88,7 @@ export interface Config {
* - `restart` means that we should stop current animation and start the new one
* - `replaceToState` means that we only replace final points of animation
* (el-animate replaces `to` className and animation end handler). **Useful if `animation.type` is `transition`.
* Then animtion Then the animation continues without interruption (See examples on github)**
* Then the animation continues without interruption (See examples on github)**
* @default 'restart'
*/
multiCallHandling: 'block' | 'restart' | 'replaceToState';
Expand All @@ -108,7 +109,7 @@ export function getConfig(options: Partial<Config>): Config {
final: options.classNames?.final || '',
},
animation: {
type: options.animation?.type || AnimationType.TRANSITION,
type: options.animation?.type || 'both',
name: options.animation?.name,
},
callbacks: {
Expand Down

0 comments on commit f9f12e1

Please sign in to comment.