各位掘友,好久不见,最近利用工作之余开源了Vue电商项目,高仿某知名O2O买菜平台,整个项目做下来收获还是蛮多的,可以扫描下方二维码体验,本篇是项目的核心知识拆解篇,主要是拆解增加商品飞入购物车的实现过程。
点我体验
项目开源地址 感谢点星+收藏
首先我先简单的介绍下本项目所用到的技术栈:
整个项目采用 vue-cli3 脚手架搭建, Vue全家桶(vue、vuex、vue-router) 、 Vant UI框架 以及很多著名好用的第三方库如: axios 、 fastclick 、 better-scroll 、 twix.js 、 pubsub.js 、 moment.js 、 vue-amap 等等。 像素单位选择 rem ,后台数据接口通过 Easy-Mock 搭建,以最接近企业开发的方式,组件化模块化,最大程度实现高内聚低耦合,大大提升各模块的可维护及可扩展性,相信读完源码和我写的系列拆解文章,无论你是哪个段位的攻城狮都会有所启发!开源不易,你的点赞就是对我最大的鼓励:tada::tada:感谢~Thanks♪(・ω・)ノ
首先先来瞅瞅要做成的样子,是不是很炫酷:airplane::airplane:随手点赞支持下作者:heartbeat:
实现思路
首先我们先来把关注点放到加入购物车这块,当我们点击购物车图标的时候,这个时候会在当前点击的商品图片的中央范围先出现个圆形的商品缩略图,其次这个商品缩略图会沿着当前位置以曲线的形式逐渐变小飞入到购物车里,当商品飞入到购物车时,购物车的数字图标会增加,同时购物车会出现弹簧动画。
通过上面大白话分析整个实现步骤可简短分为三个阶段来完成编码:
第一阶段编码:绘制一个圆形的小球到商品的中间区域 这个非常简单,就是在商品图片区域加一个 div ,设置 position:fixed 及宽度高度等,但是呢?
先埋个问题,如何让小球出现在点击当前商品的范围内呢?
起初我通过计算属性遍历了商品列表,在所有的商品视图中加入商品缩略图小球,然后,通过给每个商品列表里增加一个boolean属性 show ,通过点击购物车图标来控制我刚创建的小球的显示与隐藏,然后自己就进入了死胡同,饶了半天,计算属性的数据通过 set 方式改变后,Dom死活不听话就是不按套路出牌(因为计算属性存在数据缓存),于是不得已放弃此笨拙的办法。
上面踩坑是因为贪多,想一次性到位,提前加载所有商品的小球缩略图,然后通过点击购物车来控制当前商品缩略图的显示与隐藏.那么我们要不换一种思路,仅创建一个缩略小球怎么样,通过 boolean 来控制它的显示和隐藏,位置动态变化,点击哪个商品就让他显示到哪个商品的范围内,并且每次点击给他设置个true的属性丢到一个数组中.好,我们先在data中定义小球是否显示的属性及显示小球的数组
data () { return { showMoveDot: [], //控制下落的小圆点显示隐藏 }
然后我们在点击购物车的时候来给 showMoveDot 数组动态增加属性,然后在Dom中遍历这个数组,双向绑定,最后通过 v-if 来控制显示和隐藏,这样是不是非常妙~~
点击购物车给 showMoveDot 增加 true 的属性
methods: { addToCart (product, num) { this.showMoveDot = [...this.showMoveDot, true]; } }
Dom中遍历 showMoveDot ,并且通过 v-if 来控制商品缩略小球的显示
<div v-for="(item,index) in showMoveDot" :key="index"> <div class="move_dot" ref="ball" v-if="item"> </div> </div>
此时点击购物车图标就会在当前商品中出现商品缩略图的小球,至此,阶段一大功告成 ✿✿ヽ(°▽°)ノ✿ ~
本阶段需要用到动画知识,所以首先想到的是Vue的 transition 属性,首先给缩略图的小球包一层 transition 并且增加 appear 动画并且实现 beforeEnter 、 afterEnter 事件方法,所以此时修改Dom代码
<transition appear @before-appear="beforeEnter" @after-appear='afterEnter' v-for="(item,index) in showMoveDot" :key="index.id"> <div class="move_dot" ref="ball" v-if="item"> </div> </transition>
上面Dom代码的两个方法 beforeEnter 和 afterEnter 方法分别是动画初次渲染前和动画渲染后,那么我们就要把注意点放到这两个状态中. 在初次渲染的时候我们确定下小球的位置,那么这个时候我们就要用到一个方法 getBoundingClientRect ,这个方法返回的是一组矩形的集合,这下就好啦,可以通过这个方法来定位某个元素在屏幕中的位置啦:blush:~
那好,那我们这个时候就成热打铁,通过这个方法先来确定点击购物车图标的时候,购物车这个小图标距左边和顶部相对屏幕的距离。
定义两个 data 来接受点击增加购物车图标获取到的值.
data () { return { showMoveDot: [], //控制下落的小圆点显示隐藏 elLeft: 0, //当前点击购物车按钮在网页中的绝对top值 elTop: 0, //当前点击购物车按钮在网页中的绝对left值 }
然后我们在点击添加购物车的方法里获取位置。
methods: { addToCart () { this.showMoveDot = [...this.showMoveDot, true]; this.elLeft = event.target.getBoundingClientRect().left; this.elTop = event.target.getBoundingClientRect().top; } }
此时就获取到了点击加入购物车图标的位置啦:v:这个时候离成功进了一大半~ 获取到增加购物车图标的距离后,通过相对位置来确定商品缩略小球的位置,于是在动画渲染前我们设置下他的 transform 值,x,y的值自己可以调整,并且让他的透明度为0,暂时不显示.
beforeEnter (el) { // 设置transform值 el.style.transform = `translate3d(${this.elLeft - 30}px,${this.elTop - 100}px , 0)`; // 设置透明度 el.style.opacity = 0; },
接下来就是关键,如何让小球从当前位置移动到底部 Tabbar 的购物车中呢?同样的方法,我们通过 getBoundingClientRect 方法来确定底部Tabbar的购物车徽标的 left 和 top 值,获取到这个值后,就让小球在当前位置,以贝塞尔曲线的方式向购物车x和y的方向移动,当移动完成后将数组 showMoveDot 的属性设置为 false 且透明度为1.
在小球绘制完成后的方法中
afterEnter (el) { // 获取底部购物车徽标 const badgePosition = document .getElementById("buycar") .getBoundingClientRect(); // 设置小球移动的位移 el.style.transform = `translate3d(${badgePosition.left + 30}px,${badgePosition.top - 30}px,0)` // 增加贝塞尔曲线 el.style.transition = 'transform .88s cubic-bezier(0.3, -0.25, 0.7, -0.15)'; el.style.transition = 'transform .88s linear'; this.showMoveDot = this.showMoveDot.map(item => false); // 设置透明度 el.style.opacity = 1; }
此时大功告成!点击添加购物车按钮,小球可以曲线飞到购物车中了,来个Gif图炫耀下✿✿ヽ(°▽°)ノ✿
掘友请留步(╥╯^╰╥)你以为这样就算完成了嘛~对于Geek:monkey_face:来说,这样的效果,简直太Low啦,于是乎,咱们继续一起来做个优化吧~
优化一:把小球变成点击当前商品的图片
刚开始还真TM把我给难住了,这么多图片,鬼知道显示哪个呢?后来灵机一动,不就是个动态加载图片嘛,点击加入购物车的时候当前的商品对象已经拿到了,你怕啥,直接取就完啦!~so easy:smile:好,思路有了,那咱就上代码!
1.在data中追加个 dropImage 属性.
data () { return { showMoveDot: [], //控制下落的小圆点显示隐藏 elLeft: 0, //当前点击购物车按钮在网页中的绝对top值 elTop: 0, //当前点击购物车按钮在网页中的绝对left值 dropImage: '' // 小球图片 }
2.在Dom中通过动态绑定的方式来获取 dropImage
<transition appear @after-appear='afterEnter' @before-appear="beforeEnter" v-for="(item,index) in showMoveDot" :key="index.id"> <div class="move_dot" ref="ball" v-if="item"> <!-- 小球图片 --> <img :src="dropImage" alt=""> </div> </transition>
3.动态给 dropImage 赋值
addToCart (product) { // 取出商品的图片 this.dropImage = product.small_image; // 将商品添加到购物车中 this.ADD_TO_CART(product); // 购物车左边的 this.elLeft = event.target.getBoundingClientRect().left; this.elTop = event.target.getBoundingClientRect().top; this.showMoveDot = [...this.showMoveDot, true]; },
好啦!此时我们就完成了小球图片的动态加载,来个Gif图炫一哈✿✿ヽ(°▽°)ノ✿
但是有木有发现个问题,图片飞过去很突兀,直来直去的,不够友好,行那咱继续优化~~
哈哈~让商品飞入的时候逐渐变小,思来想去,还是用 css3 的 keyframes 来搞比较好,废话不多说直接上代码.
1.设置 keyframes 的值
@keyframes mymove { 0% { transform: scale(1); } 25% { transform: scale(0.8); } 50% { transform: scale(0.6); } 75% { transform: scale(0.4); } 100% { transform: scale(0.2); } }
img { animation: 0.88s mymove ease-in-out; width: 3rem; height: 3rem; border-radius: 50%; }
好嘞,搞定!来个Gif图炫一哈✿✿ヽ(°▽°)ノ✿
为啥我觉得还是有点突兀呢,没办法,处女座,必须让他更完美:see_no_evil:
商品缩略小球逐渐变小的落入到购物车中,此时,购物车再来个弹簧效果就更美了,还是老办法用 css3 的 keyframes 再合适不过啦~
由于Tabbar是用的 Vant UI组件,在单独的 Dashboard.vue 文件中,所以在 Dashboard.vue 文件中给购物车这个图标设置 keyframes 值.
@keyframes carmove { 0% { transform: scale(1); } 25% { transform: scale(0.8); } 50% { transform: scale(1.1); } 75% { transform: scale(0.9); } 100% { transform: scale(1); } }
并且把这个 keyframes 值设置给购物车这个图标
.moveToCart { animation: mymove 0.5s ease-in-out; }
购物车的动画是加完了,但是如何控制小球移入到购物车后让动画生效呢?于是先找到小球动画结束的方法,通过查资料找到了 transitionend 和 webkitAnimationEnd 两个方法,于是我对他们做了监听,当小球消失的时候在这两个方法中动态的增加Tabbar底部购物车的 keyframes 值.
afterEnter (el) { // 监听小球动画结束方法 el.addEventListener('transitionend', () => { el.style.display = 'none'; this.listenInCart(); }) // 监听小球动画结束方法 el.addEventListener('webkitAnimationEnd', () => { el.style.display = 'none'; this.listenInCart(); }) },
this.listenInCart() 方法是控制底部Tabbar购物车图标动画的方法,我们已经定义了一个class moveToCart ,我采用取巧的办法,当动画结束的时候,给Tabbar的购物车添加class moveToCart ,然后让他在500ms后在移除这个class,这样就会保证每次增加购物车后,底部Tabbar都会执行 keyframs 动画.
listenInCart () { // 拿到底部Tabbar购物车的DOM元素添加class document.getElementById("buycar").classList.add('moveToCart'); setTimeout(() => { // 500毫秒后移除底部Tabbar购物车的DOM元素class document.getElementById("buycar").classList.remove('moveToCart'); }, 500); }
此时算是真正的大功告成:cherry_blossom:,来个Gif图炫耀一哈✿✿ヽ(°▽°)ノ✿
都看到这里啦,还不点赞支持下:smile:,鼓励下作者~ 三、重点来了:rocket::rocket:
我知道掘友们已经迫不及待的想看源码啦~当然本篇知识点只是整个项目的冰山一角,还有很多好用好玩的新技术,如 Better-scroll 滚动使用,高德地图的集成,图片瀑布流,移动端适配等等主流技术在这个项目中几乎都有~放个GitHub连接,掘友们可不要吝啬手中的小星星哦✿✿ヽ(°▽°)ノ✿
:tada:Vue构建大型单页面电商应用 开源啦!点我看源码:rocket::rocket:
总结
以上所述是小编给大家介绍的Vue实现商品飞入购物车效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
本文向大家介绍js实现商品抛物线加入购物车特效,包括了js实现商品抛物线加入购物车特效的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了js实现商品抛物线加入购物车动画代码,供大家参考,具体内容如下 parapola.js 使用: 加入购物车实战: 以上就是本文的全部内容,希望对大家的学习有所帮助。
本文向大家介绍Android实现购物车添加商品特效,包括了Android实现购物车添加商品特效的使用技巧和注意事项,需要的朋友参考一下 一、引言 以前在饿了么上面订餐的时候,曾经看到过这么一个特效,就是将商品加入订单时,会有一个小球呈抛物线状落入购物车中,然后购物车中的数量会改变。具体的效果如下图。 效果很简单,就是一个抛物线的动画,那么我们应该用什么技术来实现呢?想了想,动画层是不个错的选择!下
本文向大家介绍Android实现添加商品到购物车动画效果,包括了Android实现添加商品到购物车动画效果的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Android添加商品到购物车的具体代码,供大家参考,具体内容如下 实现需求 在商品列表页面中,从列表item添加商品时,实现一个动画,给人感觉像是在添加商品到购物车。 思路 1、获取各个动画执行对象的起点和终点的坐标,利用Path
本文向大家介绍jQuery实现加入购物车飞入动画效果,包括了jQuery实现加入购物车飞入动画效果的使用技巧和注意事项,需要的朋友参考一下 HTML 首先载入jQuery库文件和jquery.fly.min.js插件。 接着,将商品信息html结构布置好,本例中,我们用四个商品并排布置,每个商品box中包括有商品图片、价格、名称以及加入购物车按钮等信息。 然后,我们还需要在页面的右侧加上购物车以及
本文向大家介绍Android实现购物车添加商品动画,包括了Android实现购物车添加商品动画的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Android实现购物车添加商品动画的具体代码,供大家参考,具体内容如下 实现需求: 在商品列表页面,从列表Item 添加商品的时候,需要一个动画,仿佛是是往购物车里添加商品。 实现思路: 获取起始点与终点的坐标,利用PathMeasure 绘
本文向大家介绍iOS实现电商购物车界面示例,包括了iOS实现电商购物车界面示例的使用技巧和注意事项,需要的朋友参考一下 先看界面效果图: 主要实现了商品的展示,并且可以对商品进行多选操作,以及改变商品的购买数量。与此同时,计算出,选中的总价格。 做此类型项目:要注意的:视图与数据要分离开来。视图的展现来源是数据模型层。所以我做的操作就是改变数据层的内容,在根据数据内容,去更新视图界面。 已下是具体