Skip to content

Commit

Permalink
💥 Use CSS variables for transition customization
Browse files Browse the repository at this point in the history
  • Loading branch information
NeoLegends committed Mar 16, 2018
1 parent 7092f06 commit a920039
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 141 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dom-flip",
"version": "0.2.10",
"version": "0.3.0",
"description": "Smooth position animation for web components",
"main": "dist/dom-flip.js",
"repository": "https://github.com/NeoLegends/dom-flip.git",
Expand Down
182 changes: 42 additions & 140 deletions src/element.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
declare global {
interface Window {
ShadyCSS?: any;
}
}

/**
* All used attribute names.
*/
const enum AttributeNames {
Active = 'active',
AttrName = 'attr-name',
DelayMs = 'delay-ms',
DurationMs = 'duration-ms',
Easing = 'easing',
TransitionClassName = 'transition-class-name',
}

/**
Expand Down Expand Up @@ -72,6 +74,29 @@ const isCloseTo = (actual: number, target: number, epsilon: number = 1e-5) =>
*/
const transformRegex = /matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s*0\)/;

// tslint:disable:max-line-length

/**
* The template element used for initially stamping dom-flip's DOM.
*/
const template = document.createElement('template') as HTMLTemplateElement;
template.innerHTML = `
<style>
::slotted(*) {
transition: transform var(--transition-duration, 200ms) var(--transition-easing, ease-out) var(--transition-delay, 0),
opacity var(--transition-duration, 200ms) var(--transition-easing, ease-out) var(--transition-delay, 0);
}
</style>
<slot></slot>
`;

// tslint:enable

if (window.ShadyCSS) {
window.ShadyCSS.prepareTemplate(template, 'dom-flip');
}

/**
* `dom-flip`
*
Expand All @@ -96,14 +121,7 @@ const transformRegex = /matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s
*/
export default class DomFlip extends HTMLElement {
static get observedAttributes(): string[] {
return [
AttributeNames.Active,
AttributeNames.AttrName,
AttributeNames.DelayMs,
AttributeNames.DurationMs,
AttributeNames.Easing,
AttributeNames.TransitionClassName,
];
return [AttributeNames.Active, AttributeNames.AttrName];
}

/**
Expand Down Expand Up @@ -140,85 +158,20 @@ export default class DomFlip extends HTMLElement {
this._updateListeners();
}

/**
* The CSS animation delay in milliseconds.
*
* Defaults to 0ms.
*
* @type Number
*/
get delayMs() {
return this._delayMs;
}

set delayMs(val: number) {
this._delayMs = val;
this._render();
}

/**
* The CSS animation duration in milliseconds.
*
* Defaults to 200ms.
*
* @type Number
*/
get durationMs() {
return this._durationMs;
}

set durationMs(val: number) {
this._durationMs = val;
this._render();
}

/**
* The CSS animation easing mode to use.
*
* Defaults to `ease-in-out`.
*
* @type String
*/
get easing() {
return this._easing;
}

set easing(val: string) {
this._easing = val;
this._render();
}

/**
* The class name to apply when the elements are moving. This
* only need be changed in case of conflicts.
*
* Defaults to `dom-flip-transitioning`.
*
* @type String
*/
get transitionClassName() {
return this._transitionClassName;
}

set transitionClassName(val: string) {
this._transitionClassName = val;
this._render();
}

/**
* Backing field for `active`.
*/
private _active: boolean = true;

/**
* Whether a dom change event handler is enqueued for the current animation frame.
* Backing field for `attrName`.
*/
private _animationEnqueued: boolean = false;
private _attrName: string = 'data-flip-id';

/**
* Backing field for `attrName`.
* Whether a dom change event handler is enqueued for the current animation frame.
*/
private _attrName: string = 'data-flip-id';
private _animationEnqueued: boolean = false;

/**
* The last known client rects of the children keyed by their ID.
Expand All @@ -230,21 +183,6 @@ export default class DomFlip extends HTMLElement {
*/
private _childObserver: MutationObserver;

/**
* Backing field for `delayMs`.
*/
private _delayMs: number = 0;

/**
* Backing field for `durationMs`.
*/
private _durationMs: number = 200;

/**
* Backing field for `easing`.
*/
private _easing: string = 'ease-out';

/**
* The shadow slot containing the children.
*/
Expand All @@ -255,21 +193,22 @@ export default class DomFlip extends HTMLElement {
*/
private _mutationObserverUpdateHandler;

/**
* Backing field for `transitionClassName`.
*/
private _transitionClassName: string = 'dom-flip-transitioning';

constructor() {
super();

this._childObserver = new MutationObserver(() => this._enqueueAnimateChangedElements());
this._mutationObserverUpdateHandler = () => this._updateMutationObserver();
this.attachShadow({ mode: 'open' });
}

connectedCallback() {
this._render();
if (window.ShadyCSS) {
window.ShadyCSS.styleElement(this);
}

if (!this.shadowRoot) {
this.attachShadow({ mode: 'open' });
}
this.shadowRoot!.appendChild(template.content.cloneNode(true));

this._slot = this.shadowRoot!.querySelector('slot') as HTMLSlotElement;
this._updateListeners();
Expand All @@ -283,18 +222,6 @@ export default class DomFlip extends HTMLElement {
case AttributeNames.AttrName:
this.attrName = newValue;
break;
case AttributeNames.DelayMs:
this.delayMs = Number(newValue);
break;
case AttributeNames.DurationMs:
this.durationMs = Number(newValue);
break;
case AttributeNames.Easing:
this.easing = newValue;
break;
case AttributeNames.TransitionClassName:
this.transitionClassName = newValue;
break;
}
}

Expand Down Expand Up @@ -322,23 +249,14 @@ export default class DomFlip extends HTMLElement {
continue;
}

el.classList.remove(this.transitionClassName);

// Revert new layout into old positions
el.style.opacity = String(old.opacity);
el.style.transform = generateTransformString(dL, dT, old.scaleX, old.scaleY);

requestAnimationFrame(() => {
el.classList.add(this.transitionClassName);

// Remove our reverts and let animation play
el.style.opacity = String(n.opacity);
el.style.transform = generateTransformString(0, 0, n.scaleX, n.scaleY);

setTimeout(
() => el.classList.remove(this.transitionClassName),
this.durationMs + 50,
);
});
}

Expand Down Expand Up @@ -437,20 +355,4 @@ export default class DomFlip extends HTMLElement {

this._enqueueAnimateChangedElements();
}

/**
* Render the shadow dom contents.
*/
private _render() {
this.shadowRoot!.innerHTML = `
<style>
::slotted(.${this.transitionClassName}) {
transition: transform ${this.durationMs}ms ${this.easing} ${this.delayMs}ms,
opacity ${this.durationMs}ms ${this.easing} ${this.delayMs}ms;
}
</style>
<slot></slot>
`;
}
}

0 comments on commit a920039

Please sign in to comment.