09 | 动画:Vue中如何实现动画效果?
该思维导图由 AI 生成,仅供参考
前端过渡和动效
- 深入了解
- 翻译
- 解释
- 总结
Vue 中实现动画效果的方法和实践是本文的重点内容。文章首先介绍了使用 CSS 属性 transition 和 animation 实现元素属性的缓慢变化和动画效果的方法。接着详细介绍了在 Vue 3 中使用内置的 transition 组件来控制组件的动画,并给出了一个简单的例子。然后,通过优化清单应用的交互场景,展示了如何在 Vue 中使用 transition 包裹元素,并设置相应的 CSS 过渡效果,实现了弹窗的动画效果。此外,还介绍了使用 transition-group 实现列表元素的动画和在 vue-router 中实现页面切换动画的方法。最后,通过引入 JavaScript 实现更复杂的动画效果,如购物车中商品飞入的效果。总结指出,动画的设计需要系统地设计效果,不宜过多,而实现更复杂的动画效果需要借助 JavaScript 和第三方库的支持。整体而言,本文通过实际案例和代码示例生动地展示了在 Vue 中实现动画效果的方法和实践。
《玩转 Vue 3 全家桶》,新⼈⾸单¥68
全部留言(39)
- 最新
- 精选
- ll边看回顾学过和用过的动画知识,总结下: 1. 为什么要用动画? 首先肯定不是为了“炫技”,从产品的角度,个人觉得是为了“降低用户理解难度”,因为 “动” 意味着有“生气”,比较“自然”。回想下日常生活中,碰到的人或事,如果比较“自 然”是不是意味着比较“好搞”,比较“容易相处”。而我们用动画就是为了实现这样的效果。 当然用户体验这种事,大公司应该专门有个UX部门,我们前端主要还是要以实现为主, 工程师还是要“多、快、好、省”的把事情做成,这就涉及到动画的具体实现。 2. 动画的实现 个人觉得动画的实现就是CSS的事,JS实现动画也是动态改变某个元素的CSS属性。这个 过程可以看下隔壁李兵老师的《浏览器工作原理与实践》其中的渲染流水线的论述,这 里强调下,如果较关注的动画性能问题,还是从动画的本质理解起: 动画的本质:“从哪里来,到哪里去,中间过程是怎么样的”。 以本节第一段代码来说,从哪里来"from",就是 box.width=100px;去哪"to", 就是 box.width += 100px;后面为了“动起来”,加了个中间过程,是用"transition"实现的, 当然还有其他实现,深究还涉及到贝叶斯曲线函数,“弹簧函数”之类的技术实现。 提下动画的性能问题,简单说就是,改变有些 CSS 属性会影响渲染流程,就是常说的 “重排,重绘,合成”。提供两个资源,可以具体看下,改变哪些属性会触发。 – https://csstriggers.com/ – https://gist.github.com/paulirish/5d52fb081b3570c81e3a 3. Vue 组件化实现 Vue 提供了<transition>, <transition-group>两个组件来帮助我们实现业务中的动画 需求,大大的提高了我们的开发效率。 很神奇,有需求的同学可以看看源码,看看怎么实现的,应该能学到不少知识。
作者回复: 太用心啦!
2021-11-05660 - 我叫兽儿…动手实现清单删除动画的时候,踩了一个小坑,在此记录一下,代码如下: <ul v-if="todolist.length"> <transition-group name="list" tag="ul"> <li v-for="(item, index) in todolist" :key="index"> <input type="checkbox" v-model="item.checked" /> <span>{{ item.title }}</span> <span @click="deleteItem($event, index)" class="delete">x</span> </li> </transition-group> </ul> 这里for循环我使用了index作为key,导致删除某一个li时,动画总是作用到最后一个li上。看了半天发现index会随着li的删除而变化,比如:我删除了第三个li,但是第四个会立马补上变成第三个,后面的li会依次向前补位,导致动画错乱。解决方式就是使用唯一的不会变的值作为key,比如id. 愿共同学习,共同进步!
作者回复: 很棒的总结和体验 第一部分实战代码在这里呀,欢迎遇见bug了提pr呀 https://github.com/shengxinjing/geektime-vue-course
2021-11-07318 - Justin想請問一下 function enter(el,done){ document.body.offsetHeight el.style.transform = `translate(0,0)` el.addEventListener('transitionend', done) } document.body.offsetHeight 這一行的作用是什麼? 感謝
作者回复: 手动触发一次重绘,开始动画
2021-11-05511 - Geek_0c8aff// bug, 删除todo的最后一项,加入垃圾桶的动画位置不对(0,0),以下是我的修改。 function removeTodo(e: any, i: number) { animate.el = e.target animate.show = true setTimeout(()=>{ todos.value.splice(i, 1) },100) }
作者回复: 赞,nextTick也可以
2021-11-2158 - 柒月页面切换动画的时候,要求路由组件必须要有个根元素包裹,不然动画不生效的。 https://stackoverflow.com/questions/65553121/vue-3-transition-renders-non-element-root-node-that-cannot-be-animated
作者回复: 很赞的提醒,第一部分实战代码在这里呀,欢迎遇见bug了提pr呀 https://github.com/shengxinjing/geektime-vue-course
2021-11-0978 - 雪狼课程非常棒,在学习过程中提几个建议 1、部分代码能加点注释更方便理解,比如enter函数 2、css没有写全,比如垃圾筐的,这倒也不是大问题 3、如果每讲,最后能有一个本讲完整的实例代码贴到最后,更方便查看 4、动画需要一个root节点包裹才能生效,课程中没有体现出来的
作者回复: 感谢建议,我尽快改进
2021-12-206 - bugu问一个问题:列表动画那一部分transition-group ,设置 tag 的作用是什么呢?我尝试去掉tag,没有看出什么差异。 还有下面move的动画设定 .flip-list-move { transition: transform 2s ease; } 我尝试修改和删除,也没有看出什么差异。 请帮忙指定一下,谢谢老师和各位同学
作者回复: tag的目的是给li渲染一个ul父元素,倒是不会影响实际功能,不过会让html更语义化一些
2021-11-0556 - Zachy// 强迫症下把删除动画精准还原到垃圾桶位置,暂时没加抛物线,否则效果更佳。 const {animate,beforeEnter, enter, afterEnter,removeTodo} = useAnimation(); function useAnimation(){ let animate = reactive({ show: false, el: null, }); const dustbin ={ el:null, pos:[], init(queryStr){ this.el = document.querySelector(queryStr); this.getPos(); }, getPos(){ const { left, top} = this.el.getBoundingClientRect(); this.pos[0] = left; this.pos[1] = top; } } function beforeEnter(el) { let dom = animate.el; let rect = dom.getBoundingClientRect(); const aniEl= document.querySelector('.animate'); //动画元素 调整到dustbin的位置,也可以css直接写精准位置 aniEl.style.left = `${dustbin.pos[0]}px`; aniEl.style.top= `${dustbin.pos[1]}px`; //计算并赋值偏移量 let dx = dustbin.pos[0] - rect.left; let dy = dustbin.pos[1] - rect.top; el.style.transform = `translate(-${dx}px, ${dy*-1}px)`; } function enter(el, done) { document.body.offsetHeight; el.style.transform = `translate(0,0)`; el.addEventListener("transitionend", done); } function afterEnter(el) { animate.show = false; el.style.display = "none"; } function removeTodo(e,i){ animate.el = e.target animate.show = true todos.value.splice(i, 1); dustbin.init('.dustbin'); } return {animate,beforeEnter,enter,afterEnter,removeTodo} }
作者回复: very geliable!!!
2021-11-2825 - 微妙el.style.transform = `translate(-${x}px, ${y}px)` 模板字符串中当x为负数时会被识别为 --xpx,导致transform识别不出而变为 translate(0px, 0px); 应先计算好x、y的值,然后在模板字符串内赋值
作者回复: 给你点个赞,这里演示我确实没考虑到负数的情况,囧 第一部分实战代码在这里呀,欢迎遇见bug了提pr呀 https://github.com/shengxinjing/geektime-vue-course
2021-11-084 - Geek_1ecc87为什么要在v-for li中指定key添加任务的时候动画才会生效?
作者回复: key是vue内部识别一个dom是否可以重用的标志 没有key的话dom很难复用
2022-01-1423