在视图中,过渡效果是常见的场景。平滑的过渡动画能够给用户更好的感官体验。san 提供了基础的过渡机制,你可以基于此开发丰富的过渡效果。
版本
:>= 3.3.0
s-transition
在元素上通过 s-transition 指令,可以声明过渡动画控制器。
1
| <button s-transition="opacityTransition">click</button>
|
这个对象是元素 owner 的成员。
1 2 3 4 5 6 7 8
| san.defineComponent({ template: '<div><button s-transition="opacityTransition">click</button></div>',
opacityTransition: { } });
|
我们通常把 s-transition 和条件或循环指令一起使用。
1 2
| <button s-transition="opacityTransition" s-if="allowEdit">Edit</button> <b s-transition="opacityTransition" s-else>Edit not allow</b>
|
s-transition 声明的过渡动画控制器可以是 owner 组件的深层成员。
1 2 3 4 5 6 7 8 9 10
| san.defineComponent({ template: '<div><button s-transition="trans.opacity">click</button></div>',
trans: { opacity: { } } });
|
注意
:s-transition 只能应用在具体的元素中。template 这种没有具体元素的标签上应用 s-transition 将没有效果。
动画控制器
过渡动画控制器是一个包含 enter 和 leave 方法的对象。
enter 和 leave 方法的签名为 **function({HTMLElement}el, {Function}done)**。san 会把要过渡的元素传给过渡动画控制器,控制器在完成动画后调用 done 回调函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| san.defineComponent({ template: ` <div> <button on-click="toggle">toggle</button> <button s-if="isShow" s-transition="opacityTrans">Hello San!</button> <button s-else s-transition="opacityTrans">Hello ER!</button> </div> `,
toggle: function () { this.data.set('isShow', !this.data.get('isShow')); },
opacityTrans: { enter: function (el, done) { var steps = 20; var currentStep = 0;
function goStep() { if (currentStep >= steps) { el.style.opacity = 1; done(); return; }
el.style.opacity = 1 / steps * currentStep++; requestAnimationFrame(goStep); }
goStep(); },
leave: function (el, done) { var steps = 20; var currentStep = 0;
function goStep() { if (currentStep >= steps) { el.style.opacity = 0; done(); return; }
el.style.opacity = 1 - 1 / steps * currentStep++; requestAnimationFrame(goStep); }
goStep(); } } });
|
提示
:
san 把动画控制器留给应用方实现,框架本身不内置动画控制效果。应用方可以:
- 使用 css 动画,在 transitionend 或 animationend 事件监听中回调 done
- 使用 requestAnimationFrame 控制动画,完成后回调 done
- 在老旧浏览器使用 setTimeout / setInterval 控制动画,完成后回调 done
- 发挥想象力
动画控制器 Creator
s-transition 指令声明对应的对象如果是一个 function,san 将把它当成 过渡动画控制器 Creator。
每次触发过渡动画前,san 会调用过渡动画控制器 Creator,用其返回的对象作为过渡动画控制器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| san.defineComponent({ template: ` <div> <button on-click="toggle">toggle</button> <button s-if="isShow" s-transition="opacityTrans">Hello San!</button> <button s-else s-transition="opacityTrans">Hello ER!</button> </div> `,
toggle: function () { this.data.set('isShow', !this.data.get('isShow')); },
opacityTrans: function () { return { enter: function (el, done) { var steps = 20; var currentStep = 0;
function goStep() { if (currentStep >= steps) { el.style.opacity = 1; done(); return; }
el.style.opacity = 1 / steps * currentStep++; requestAnimationFrame(goStep); }
goStep(); },
leave: function (el, done) { var steps = 20; var currentStep = 0;
function goStep() { if (currentStep >= steps) { el.style.opacity = 0; done(); return; }
el.style.opacity = 1 - 1 / steps * currentStep++; requestAnimationFrame(goStep); }
goStep(); } } } });
|
和事件声明类似,过渡动画控制器 Creator调用支持传入参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| san.defineComponent({ template: ` <div> <button on-click="toggle">toggle</button> <button on-click="toggleTrans">toggle transition</button> <button s-if="isShow" s-transition="opacityTrans(noTransition)">Hello San!</button> <button s-else s-transition="opacityTrans(noTransition)">Hello ER!</button> </div> `,
toggle: function () { this.data.set('isShow', !this.data.get('isShow')); },
toggleTrans: function () { this.data.set('noTransition', !this.data.get('noTransition')); },
initData: function () { return { noTransition: false }; },
opacityTrans: function (disabled) { return { enter: function (el, done) { if (disabled) { done(); return; }
var steps = 20; var currentStep = 0;
function goStep() { if (currentStep >= steps) { el.style.opacity = 1; done(); return; }
el.style.opacity = 1 / steps * currentStep++; requestAnimationFrame(goStep); }
goStep(); },
leave: function (el, done) { if (disabled) { done(); return; }
var steps = 20; var currentStep = 0;
function goStep() { if (currentStep >= steps) { el.style.opacity = 0; done(); return; }
el.style.opacity = 1 - 1 / steps * currentStep++; requestAnimationFrame(goStep); }
goStep(); } } } });
|