timed-transition

1.5.4 • Public • Published

TimedTransition

npm GitHub issues dependencies license

The simple shim for Transition Events with CSS transitions, that transparently intercepts difference between browsers.

The CSS transitions are very useful and easy, to style web pages for dynamic visual design.
However, when you use that with JavaScript to control its behavior or doing something, you will meet various nasty problems. For example, there are some problems with Transition Events, CSS opacity property, etc.
Those are caused by wrong implementation in web browsers. Unfortunately, the worst one is Google Chrome that is most popular one. On the other hand, Mozilla Firefox is almost perfect. See "Browsers and Problems".

This shim fires the Transition Events correctly according to standard specification with timer driven.

Usage

A simple case without TimedTransition is here:

#target {
  width: 100px;
  height: 100px;
  background-color: blue;

  transition-property: margin-left;
  transition-duration: 3s;
}
// Event Listener
function printLog(event) {
  console.log('[%s] <%s> propertyName: %s elapsedTime: %f pseudoElement: %s',
    Date.now(),
    event.type,
    event.propertyName,
    event.elapsedTime,
    event.pseudoElement);
}

var element = document.getElementById('target');

// Prepare
['transitionrun', 'transitionstart',
    'transitionend', 'transitioncancel'].forEach(function(type) {
  element.addEventListener(type, printLog, true);
});

// START Transition
element.style.marginLeft = '600px';

// REVERSE Transition
setTimeout(function() {
  element.style.marginLeft = '0';
}, 4000);

The code above doesn't work correctly in many web browsers.
Then, it is solved by using TimedTransition:

Load TimedTransition into your web page.

<script src="timed-transition.min.js"></script>

And replace the code above with:

// Prepare

// Create new instance
var transition = new TimedTransition(element, {
  // This is called by `transition.on()`.
  procToOn: function() { element.style.marginLeft = '600px'; },
  // This is called by `transition.off()`.
  procToOff: function() { element.style.marginLeft = '0'; }
});

// Event types are prefixed with `timed`.
['timedTransitionRun', 'timedTransitionStart',
    'timedTransitionEnd', 'timedTransitionCancel'].forEach(function(type) {
  element.addEventListener(type, printLog, true);
});

// START Transition
transition.on();

// REVERSE Transition
setTimeout(function() {
  transition.off();
}, 4000);

Result in the console:

[20:40:15] <timedTransitionRun> propertyName: margin-left elapsedTime: 0.000000 pseudoElement:
[20:40:15] <timedTransitionStart> propertyName: margin-left elapsedTime: 0.000000 pseudoElement:
[20:40:18] <timedTransitionEnd> propertyName: margin-left elapsedTime: 3.001000 pseudoElement:
[20:40:19] <timedTransitionRun> propertyName: margin-left elapsedTime: 0.000000 pseudoElement:
[20:40:19] <timedTransitionStart> propertyName: margin-left elapsedTime: 0.000000 pseudoElement:
[20:40:22] <timedTransitionEnd> propertyName: margin-left elapsedTime: 3.020060 pseudoElement:

Note that you should consider cross-browser compatibility if you will use CSS transition-* properties or element.classList. See "Cross-Browser".

Constructor

transition = new TimedTransition(element[, options[, initOn]])

The element argument is an element that transitions are applied and events are dispatched.

The options argument is an Object that can have properties as options (and window option). You can also change the options by setOptions method, on method, off method or properties of the TimedTransition instance.
For example, construct new TimedTransition instance with duration option:

var transition = new TimedTransition(document.getElementById('target'), {duration: '400ms'});

By default, a CSS property that is animated is regarded as an initial value that is not changed at this time. If true is specified for the initOn argument, it is regarded as a changed value.
For example, in the example code at the beginning of this document, the margin-left property of the element that will be animated is initially 0. If you want to construct new TimedTransition instance after changing the property, specify true for the initOn argument.

element.style.marginLeft = '600px';
var transition = new TimedTransition(element, null, true);
// TimedTransition regards current value as a changed value, not an initial value.

window option

By default, TimedTransition tries to get a window that contains target element. If it couldn't get a window (e.g. you specified SVG element that is not added to the document yet), it gets the current window.
Therefore, you usually don't have to specify a window.
If another window is specified for window option of the constructor, it uses that instead.

Note that this is an option for constructor, that is, you can not change this after.

Methods

on

self = transition.on([force][, options][, arg1, arg2...])

Make the transition run to become the changed CSS property.
If a function is specified for the procToOn option, it is called. Then, a timer is started for events.

If true is specified for force argument, change the state immediately without the transition. For example, this is used to show something immediately.
The procToOn function is called with force argument. Then, timedTransitionCancel event is fired if the transition is running now, and other events are not fired.

If options argument is specified, call setOptions method and make the transition run. It works the same as:

transition.setOptions(options).on();

You can specify one or more additional arguments as arg1, arg2..., and these are passed to the procToOn function.
If you specify these, you must specify force and options arguments even if those are undefine or null. For example:

transition.on(false, null, 'ARG-1', 'ARG-2');

See procToOn option for these arguments.

off

self = transition.off([force][, options][, arg1, arg2...])

Make the transition run to become the initial CSS property.
If a function is specified for the procToOff option, it is called. Then, a timer is started for events.

If true is specified for force argument, change the state immediately without the transition. For example, this is used to hide something immediately.
The procToOff function is called with force argument. Then, timedTransitionCancel event is fired if the transition is running now, and other events are not fired.

If options argument is specified, call setOptions method and make the transition run. It works the same as:

transition.setOptions(options).off();

You can specify one or more additional arguments as arg1, arg2..., and these are passed to the procToOff function.
If you specify these, you must specify force and options arguments even if those are undefine or null. For example:

transition.off(false, null, 'ARG-1', 'ARG-2');

See procToOff option for these arguments.

setOptions

self = transition.setOptions(options)

Set one or more options.
The options argument is an Object that can have properties as options.

remove

transition.remove()

Remove the current TimedTransition instance.
Never use the removed instance.

Options

property

Type: number or string
Default: A value that is got by 0 when constructing instance

A value that is set to propertyName property of Event object that is passed to event listeners.

If a number is specified, a value is got from current CSS transition-property property of the element. The number indicates an index of the list that is the CSS value.
For example:

#target {
  transition-property: margin-left, opacity, color;
}
var transition = new TimedTransition(element);
// Initially `margin-left` (index: 0) is got, by default.
// Specify `{property: 1}` for second argument if `opacity` is required.

transition.property = 1; // `opacity` is got and set.
transition.property = 2; // `color` is got and set.

If a string is specified, the string itself is set regardless of current CSS transition-property property of the element. For example, this is used to set something to the Event object, or specify a value when the CSS transition-property property is all that can not be resolved.

duration

Type: number or string
Default: A value that is got by 0 when constructing instance

A value as CSS transition-duration property. This is used to control timing for events.
This can be a number or a string and it is parsed by the same way as property option.

delay

Type: number or string
Default: A value that is got by 0 when constructing instance

A value as CSS transition-delay property. This is used to control timing for events. This might be a negative value.
This can be a number or a string and it is parsed by the same way as property option.

procToOn, procToOff

Type: function or undefined
Default: undefined

Functions to change a CSS property that is animated (or, it add or remove class-name). The procToOn function is called by on method, and the procToOff function is called by off method.
These are used to get the timing of the events right with the transition. Therefore, changing the CSS property in these functions is better than changing it at other point.

These functions might be passed true for force argument that is first argument. That is force argument that is passed to on or off method. The true means that changing the CSS property immediately without the transition is required.

In the functions, this refers to the current TimedTransition instance.

For example:

transition.setOptions({
  procToOn: function(force) {
    this.element.style.transitionProperty = force ? 'none' : 'margin-left';
    // Or, this.element.style.transitionDuration = force ? '0' : '3s';
    this.element.style.marginLeft = '600px';
  },
  procToOff: function(force) {
    this.element.style.transitionProperty = force ? 'none' : 'margin-left';
    this.element.style.marginLeft = '0';
  }
});

If you passed one or more additional arguments to on or off method, these also are passed as third argument or more. You can use these to do something with variable parameters.

For example:

transition.procToOn = function(force, left, top) {
  // ...
  this.element.style.left = left + 'px';
  this.element.style.top = top + 'px';
};

// START Transition
transition.on(false, null, 200, 300); // Move to (left: 200, top: 300)

Note that you should consider cross-browser compatibility if you will use CSS transition-* properties or element.classList. See "Cross-Browser".

pseudoElement

Type: string
Default: ''

A string that is set to pseudoElement property of Event object that is passed to event listeners.
It starting with '::', containing the name of the pseudo-element the animation runs on.

Properties

state

Type: number
Read-only

A number to indicate current state of the TimedTransition instance.
It is one of the following static constant values:

  • TimedTransition.STATE_STOPPED (0): The transition is not running.
  • TimedTransition.STATE_DELAYING (1): The transition is waiting until the delay elapses.
  • TimedTransition.STATE_PLAYING (2): The transition is playing, to the forward or the reverse.

For example:

startButton.addEventListener('click', function() {
  if (transition.state === TimedTransition.STATE_STOPPED) {
    transition.on();
  }
}, false);

isReversing

Type: boolean
Read-only

When the transition is playing, indicate that the animation runs to the reverse.
Note that It's meaningless when the transition is not playing.

element

Type: Element
Read-only

Reference to the element that is passed to the constructor.

property

Get or set property option.

duration

Get or set duration option.

delay

Get or set delay option.

procToOn, procToOff

Get or set procToOn, procToOff options.

pseudoElement

Get or set pseudoElement option.

Supported Transition Events

TimedTransition fires the Transition Events correctly according to standard specification, and each event type is prefixed with timed.

  • timedTransitionRun
  • timedTransitionStart
  • timedTransitionEnd
  • timedTransitionCancel

Also, an Event object that is passed to event listeners has properties according to standard specification, in addition, it has timedTransition property that refers to the current TimedTransition instance.

  • propertyName
  • pseudoElement
  • elapsedTime
  • bubbles
  • cancelable
  • timedTransition

For example:

element.addEventListener('timedTransitionStart', function(event) {
  if (event.propertyName === 'margin-left') {
    console.log('I am moving to the ' +
      (event.timedTransition.isReversing ? 'left' : 'right') + '!');
  }
}, true);

Browsers and Problems

  • Blink (Google Chrome and others) doesn't support any Transition Events except transitionend.
  • Webkit (Apple Safari and others) doesn't support any Transition Events except transitionend.
  • Microsoft Edge and Trident (Microsoft Internet Explorer) don't support transitionrun and transitioncancel Transition Events.
  • The animation might not start immediately even if transition-delay is zero, and transitionend event is not fired even if you make the playing direction turn at this time. This problem will be solved by transitionstart event but Blink doesn't support it, and any event is not fired.
  • In Gecko (Mozilla Firefox and others), if the playing direction that is the forward or the reverse is turned when CSS opacity property is being animated, only transitioncancel event is fired and the transition is aborted (opacity property is changed immediately).
  • In Microsoft Edge and Trident, transitionstart event is not fired when the playing direction is turned.
  • In Microsoft Edge and Trident, transition-delay is ignored when the playing direction is turned.
  • In Microsoft Edge and Trident, incorrect value is set to event.elapsedTime when transition-delay has a negative value.
  • In Microsoft Edge and Trident, the playing direction is not turned correctly when transition-delay has a negative value.
  • In Trident, the playing direction is not turned correctly when CSS opacity property is being animated.
  • And more...

Cross-Browser

These may help you for cross-browser compatibility.

Package Sidebar

Install

npm i timed-transition

Weekly Downloads

7

Version

1.5.4

License

MIT

Unpacked Size

62.5 kB

Total Files

7

Last publish

Collaborators

  • anseki