timed-transition
v1.5.4
Published
The simple shim for Transition Events with CSS transitions, that transparently intercepts difference between browsers.
Downloads
224
Maintainers
Readme
TimedTransition
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 thedelay
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
andtransitioncancel
Transition Events. - The animation might not start immediately even if
transition-delay
is zero, andtransitionend
event is not fired even if you make the playing direction turn at this time. This problem will be solved bytransitionstart
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, onlytransitioncancel
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
whentransition-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.
- mClassList for
classList
- CSSPrefix for CSS properties