Skip to content

Commit 8fff82e

Browse files
yyx990803Evan You
authored andcommitted
v-animation first pass
1 parent c8533b8 commit 8fff82e

File tree

5 files changed

+131
-24
lines changed

5 files changed

+131
-24
lines changed

src/compiler.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,9 @@ CompilerProto.compile = function (node, root) {
340340

341341
} else {
342342

343-
// check transition property
343+
// check transition & animation properties
344344
node.vue_trans = utils.attr(node, 'transition')
345+
node.vue_anim = utils.attr(node, 'animation')
345346

346347
// replace innerHTML with partial
347348
partialId = utils.attr(node, 'partial')

src/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ var prefix = 'v',
77
'repeat',
88
'partial',
99
'component',
10+
'animation',
1011
'transition'
1112
],
1213
config = module.exports = {

src/directives/repeat.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ module.exports = {
275275
el = this.el.cloneNode(true)
276276
// process transition info before appending
277277
el.vue_trans = utils.attr(el, 'transition', true)
278+
el.vue_anim = utils.attr(el, 'animation', true)
278279
// wrap primitive element in an object
279280
if (utils.typeOf(data) !== 'Object') {
280281
primitive = true

src/transition.js

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var endEvent = sniffTransitionEndEvent(),
1+
var endEvents = sniffEndEvents(),
22
config = require('./config'),
33
// exit codes for testing
44
codes = {
@@ -31,7 +31,8 @@ var transition = module.exports = function (el, stage, cb, compiler) {
3131
return codes.INIT
3232
}
3333

34-
var transitionId = el.vue_trans
34+
var transitionId = el.vue_trans,
35+
animation = el.vue_anim
3536

3637
if (transitionId) {
3738
return applyTransitionFunctions(
@@ -41,11 +42,12 @@ var transition = module.exports = function (el, stage, cb, compiler) {
4142
transitionId,
4243
compiler
4344
)
44-
} else if (transitionId === '') {
45+
} else if (transitionId === '' || animation === '') {
4546
return applyTransitionClass(
4647
el,
4748
stage,
48-
changeState
49+
changeState,
50+
animation
4951
)
5052
} else {
5153
changeState()
@@ -59,50 +61,73 @@ transition.codes = codes
5961
/**
6062
* Togggle a CSS class to trigger transition
6163
*/
62-
function applyTransitionClass (el, stage, changeState) {
64+
function applyTransitionClass (el, stage, changeState, animation) {
6365

64-
if (!endEvent) {
66+
if (!endEvents.trans) {
6567
changeState()
6668
return codes.CSS_SKIP
6769
}
6870

6971
// if the browser supports transition,
7072
// it must have classList...
71-
var classList = el.classList,
72-
lastLeaveCallback = el.vue_trans_cb
73+
var onEnd,
74+
classList = el.classList,
75+
lastLeaveCallback = el.vue_trans_cb,
76+
enterClass = config.enterClass,
77+
leaveClass = config.leaveClass,
78+
isAnimation = animation === '',
79+
endEvent = isAnimation
80+
? endEvents.anim
81+
: endEvents.trans
82+
83+
// cancel unfinished leave transition
84+
if (lastLeaveCallback) {
85+
el.removeEventListener(endEvent, lastLeaveCallback)
86+
classList.remove(enterClass)
87+
classList.remove(leaveClass)
88+
el.vue_trans_cb = null
89+
}
7390

7491
if (stage > 0) { // enter
7592

76-
// cancel unfinished leave transition
77-
if (lastLeaveCallback) {
78-
el.removeEventListener(endEvent, lastLeaveCallback)
79-
classList.remove(config.leaveClass)
80-
el.vue_trans_cb = null
81-
}
82-
8393
// set to hidden state before appending
84-
classList.add(config.enterClass)
94+
if (!isAnimation) {
95+
classList.add(enterClass)
96+
}
8597
// append
8698
changeState()
8799
// force a layout so transition can be triggered
88100
/* jshint unused: false */
89101
var forceLayout = el.clientHeight
90102
// trigger transition
91-
classList.remove(config.enterClass)
103+
if (!isAnimation) {
104+
classList.remove(enterClass)
105+
} else {
106+
classList.add(enterClass)
107+
onEnd = function (e) {
108+
if (e.target === el) {
109+
el.removeEventListener(endEvent, onEnd)
110+
el.vue_trans_cb = null
111+
classList.remove(enterClass)
112+
}
113+
}
114+
el.addEventListener(endEvent, onEnd)
115+
el.vue_trans_cb = onEnd
116+
}
92117
return codes.CSS_E
93118

94119
} else { // leave
95120

96121
if (el.offsetWidth || el.offsetHeight) {
97122
// trigger hide transition
98-
classList.add(config.leaveClass)
99-
var onEnd = function (e) {
123+
classList.add(leaveClass)
124+
onEnd = function (e) {
100125
if (e.target === el) {
101126
el.removeEventListener(endEvent, onEnd)
102127
el.vue_trans_cb = null
103128
// actually remove node here
104129
changeState()
105-
classList.remove(config.leaveClass)
130+
classList.remove(leaveClass)
106131
}
107132
}
108133
// attach transition end listener
@@ -150,17 +175,23 @@ function applyTransitionFunctions (el, stage, changeState, functionId, compiler)
150175
/**
151176
* Sniff proper transition end event name
152177
*/
153-
function sniffTransitionEndEvent () {
178+
function sniffEndEvents () {
154179
var el = document.createElement('vue'),
155180
defaultEvent = 'transitionend',
156181
events = {
157182
'transition' : defaultEvent,
158183
'mozTransition' : defaultEvent,
159184
'webkitTransition' : 'webkitTransitionEnd'
160-
}
185+
},
186+
ret = {}
161187
for (var name in events) {
162188
if (el.style[name] !== undefined) {
163-
return events[name]
189+
ret.trans = events[name]
190+
break
164191
}
165192
}
193+
ret.anim = el.style.animation === ''
194+
? 'animationend'
195+
: 'webkitAnimationEnd'
196+
return ret
166197
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<script src="../dist/vue.js"></script>
2+
<style type="text/css">
3+
h1 {
4+
display: inline-block;
5+
}
6+
.v-enter {
7+
-webkit-animation: fadein .5s;
8+
animation: fadein .5s;
9+
}
10+
.v-leave {
11+
-webkit-animation: fadeout .5s;
12+
animation: fadeout .5s;
13+
}
14+
@keyframes fadein {
15+
0% {
16+
transform: scale(0);
17+
}
18+
50% {
19+
transform: scale(1.5);
20+
}
21+
100% {
22+
transform: scale(1);
23+
}
24+
}
25+
@keyframes fadeout {
26+
0% {
27+
transform: scale(1);
28+
}
29+
50% {
30+
transform: scale(1.5);
31+
}
32+
100% {
33+
transform: scale(0);
34+
}
35+
}
36+
@-webkit-keyframes fadein {
37+
0% {
38+
-webkit-transform: scale(0);
39+
}
40+
50% {
41+
-webkit-transform: scale(1.5);
42+
}
43+
100% {
44+
-webkit-transform: scale(1);
45+
}
46+
}
47+
@-webkit-keyframes fadeout {
48+
0% {
49+
-webkit-transform: scale(1);
50+
}
51+
50% {
52+
-webkit-transform: scale(1.5);
53+
}
54+
100% {
55+
-webkit-transform: scale(0);
56+
}
57+
}
58+
</style>
59+
60+
<div id="test">
61+
<h1 v-animation v-if="ok">Hahahah</h1>
62+
<br>
63+
<button v-on="click: ok = !ok">toggle</button>
64+
</div>
65+
66+
<script>
67+
var test = new Vue({
68+
el: '#test',
69+
data: {
70+
ok: true
71+
}
72+
})
73+
</script>

0 commit comments

Comments
 (0)