do the forced layout on next frame in transitions

This commit is contained in:
Evan You 2014-09-10 13:43:34 -04:00
parent 68c18fb868
commit 2fb9660eb9
3 changed files with 40 additions and 27 deletions

View File

@ -34,9 +34,7 @@
"karma-coverage": "^0.2.5",
"karma-firefox-launcher": "^0.1.3",
"karma-jasmine": "^0.2.2",
"karma-phantomjs-launcher": "^0.1.4"
},
"dependencies": {
"karma-phantomjs-launcher": "^0.1.4",
"uglify-js": "^2.4.15"
}
}

View File

@ -6,6 +6,7 @@ var _ = require('./util')
*/
function Batcher () {
this._preFlush = null
this.reset()
}
@ -41,9 +42,14 @@ p.push = function (job) {
/**
* Flush the queue and run the jobs.
* Will call a preFlush hook if has one.
*/
p.flush = function () {
// before flush hook
if (this._preFlush) {
this._preFlush()
}
// do not cache length because more jobs might be pushed
// as we run existing jobs
for (var i = 0; i < this.queue.length; i++) {

View File

@ -1,22 +1,16 @@
var _ = require('../util')
var Batcher = require('../batcher')
var batcher = new Batcher()
var transDurationProp = _.transitionProp + 'Duration'
var animDurationProp = _.animationProp + 'Duration'
/**
* Force layout before triggering transitions/animations.
* This function ensures we only do it once per event loop.
* Force layout before triggering transitions/animations
*/
var forcedLayout = false
function forceLayout () {
if (!forcedLayout) {
batcher._preFlush = function () {
/* jshint unused: false */
var f = document.documentElement.offsetHeight
forcedLayout = true
_.nextTick(function () {
forcedLayout = false
})
}
}
/**
@ -24,27 +18,36 @@ function forceLayout () {
* calculated styles
*
* @param {Element} el
* @param {Object} data
* @param {String} className
* @return {Number}
* 1 - transition
* 2 - animation
*/
function getTransitionType (el) {
function getTransitionType (el, data, className) {
var type = data.cache && data.cache[className]
if (type) return type
var inlineStyles = el.style
var computedStyles = window.getComputedStyle(el)
var transDuration =
inlineStyles[transDurationProp] ||
computedStyles[transDurationProp]
if (transDuration && transDuration !== '0s') {
return 1
type = 1
} else {
var animDuration =
inlineStyles[animDurationProp] ||
computedStyles[animDurationProp]
if (animDuration && animDuration !== '0s') {
return 2
type = 2
}
}
if (type) {
if (!data.cache) data.cache = {}
data.cache[className] = type
}
return type
}
/**
@ -73,10 +76,13 @@ module.exports = function (el, direction, op, data, cb) {
// Enter Transition
classList.add(enterClass)
op()
transitionType = getTransitionType(el)
transitionType = getTransitionType(el, data, enterClass)
if (transitionType === 1) {
forceLayout()
batcher.push({
run: function () {
classList.remove(enterClass)
}
})
// only listen for transition end if user has sent
// in a callback
if (cb) {
@ -114,14 +120,17 @@ module.exports = function (el, direction, op, data, cb) {
} else { // leave
// we need to add the class here before we can sniff
// the transition type, and before that we need to
// force a layout so the element picks up all transition
// css rules.
forceLayout()
classList.add(leaveClass)
transitionType = getTransitionType(el)
transitionType = getTransitionType(el, data, leaveClass)
if (transitionType) {
if (transitionType === 1) {
classList.remove(leaveClass)
batcher.push({
run: function () {
classList.add(leaveClass)
}
})
}
endEvent = data.event = transitionType === 1
? _.transitionEndEvent
: _.animationEndEvent