vue购物车动画效果
使用动画的三个函数
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
将动画函数easy改成贝塞尔曲线的
效果:
直接上代码:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <!-- import CSS -->
- <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
- <style type="text/css">
- html,body{margin:0;padding:0}
- body{
- position:fixed;
- width:100%;
- height:100%
- }
- #app,#app>div{
- width:100%;
- height:100%
- }
- .car{
- width:100%;
- height:40px;
- line-height:30px;
- position:absolute;
- bottom:0;
- border:1px solid #ddd;
- display:flex;
- justify-content:flex-end;
- }
- .car-content{
- margin-right:30px;
- background-color:#eee;
- padding:0 8px;
- display:flex;
- align-items:center;
- }
- .compute{
- position:absolute;
- width:300px;
- text-align:center;
- height:30px;
- line-height:27px;
- top:0;
- left:0;bottom:0;right:0;
- margin:auto;
- border:1px solid #ddd
- }
- .compute span,.compute button{
- vertical-align:middle
- }
- .ball{
- position:absolute;
- top: 448px;
- left: 743px;
- width:17px;
- height:17px;
- background-color:red;
- border-radius:50%;
- z-index:999;
- }
- </style>
- </head>
- <body>
- <div id="app">
- <div>
- <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter">
- <div class="ball" v-if="ballFlag"></div>
- </transition>
- <div class="compute">
- <span>{{num}}</span>
- <button @click="add">+</button>
- <button @click="sub">-</button>
- <button @click="addToshowCar" >加入购物车</button>
- </div>
- <div class="car">
- <span class="car-content">购物车</span>
- </div>
- </div>
- </div>
- </body>
- <!-- import Vue before Element -->
- <script src="https://unpkg.com/vue/dist/vue.js"></script>
- <!-- import JavaScript -->
- <script src="https://unpkg.com/element-ui/lib/index.js"></script>
- <script>
- new Vue({
- el: '#app',
- data: function() {
- return {
- num:0,
- ballFlag:false
- }
- },
- methods:{
- add(){
- this.num++
- },
- sub(){
- if(this.num>1){
- this.num--
- }else{
- return false
- }
- },
- addToshowCar(){
- this.ballFlag = !this.ballFlag
- },
- // 动画钩子函数
- // 进入前状态
- beforeEnter (el) {
- el.style.transform = 'translate(0,0)'
- },
- // 进入中
- enter (el, done) {
- // 需要调用元素的offset操作,才有过渡的效果,否则会马上实现过渡
- el.offsetWidth
- el.style.transform = 'translate(569px,437px)'
- el.style.transition = "all 2s cubic-bezier(.4,-0.3,1,.68)"
- done()
- },
- // 进入后
- afterEnter () {
- this.ballFlag = !this.ballFlag
- },
- }
- })
- </script>
- </html>
问题:
发现此种方法不适应于不同屏幕的分辨率,如果换了一个尺寸的小球的位置会发生变化
解决思路:
1、首先在页面进行resize的时候重新设置小球的top值left值
2、算出小球初始停下来的位置相对于页面的左边和顶部x,y getBoundingClientRect()可以获取
3、算出小球最终停下来的位置相对于页面的左边的顶部x1,y1
4、所以不管是多大的分辨率,将x1-x,y1-y算出来的结果值就是页面在动画之间移动的距离
5、将算出来的结果值放进动画进入中的translate里面
用到的知识点,使用v-if的时候会出现屏幕闪烁,可以添加v-cloak属性,然后再在样式中添加
- [v-cloak] { display: none }
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <!-- import CSS -->
- <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
- <style type="text/css">
- html,body{margin:0;padding:0}
- body{
- position:fixed;
- width:100%;
- height:100%
- }
- #app,#app>div{
- width:100%;
- height:100%
- }
- .car{
- width:100%;
- height:40px;
- line-height:30px;
- position:absolute;
- bottom:0;
- border:1px solid #ddd;
- display:flex;
- justify-content:flex-end;
- }
- .car-content{
- margin-right:30px;
- background-color:#eee;
- padding:0 8px;
- display:flex;
- align-items:center;
- position:relative
- }
- .car-content>.smallball{
- position:absolute;
- top:-8px;
- right:-8px;
- width:17px;
- height:17px;
- text-align:center;
- color:#fff;
- font-size:12px;
- line-height:17px;
- background-color:red;
- border-radius:50%;
- z-index:999;
- }
- .compute{
- position:absolute;
- width:300px;
- text-align:center;
- height:30px;
- line-height:27px;
- top:0;
- left:0;bottom:0;right:0;
- margin:auto;
- border:1px solid #ddd
- }
- .compute span,.compute button{
- vertical-align:middle
- }
- .ball{
- position:absolute;
- top: 294px;
- left: 548px;
- width:17px;
- height:17px;
- background-color:red;
- border-radius:50%;
- z-index:999;
- /*transform:translate(569px,437px)*/
- }
- [v-cloak] { display: none }
- </style>
- </head>
- <body>
- <div id="app">
- <div>
- <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter">
- <div class="ball" v-if="ballFlag" v-cloak ref="ball" :style="{top: `${tt}px`,left:`${ll}px`}"></div>
- </transition>
- <div class="compute">
- <button @click="sub">-</button>
- <span v-cloak ref="num">{{num}}</span>
- <button @click="add">+</button>
- <button @click="addToshowCar" ref="btn">加入购物车</button>
- </div>
- <div class="car">
- <div class="car-content">
- 购物车
- <span class="smallball" id="smallball">{{carNum}}</span>
- </div>
- </div>
- </div>
- </div>
- </body>
- <!-- import Vue before Element -->
- <script src="https://unpkg.com/vue/dist/vue.js"></script>
- <!-- import JavaScript -->
- <script src="https://unpkg.com/element-ui/lib/index.js"></script>
- <script>
- new Vue({
- el: '#app',
- data: function() {
- return {
- num:0,
- ballFlag:false,
- tt:0,//小球因为自适应需要重新设置top值
- ll:0,
- carNum:0
- }
- },
- mounted(){
- this.initTopLeft()
- window.addEventListener(
- "resize",this.initTopLeft,false
- );
- },
- methods:{
- initTopLeft(){
- let t = this.$refs.btn.getBoundingClientRect().top;
- let l = this.$refs.btn.getBoundingClientRect().left;
- this.tt = t
- this.ll = l
- },
- add(){
- this.num++
- },
- sub(){
- if(this.num>1){
- this.num--
- }else{
- return false
- }
- },
- addToshowCar(){
- this.ballFlag = !this.ballFlag
- },
- // 动画钩子函数
- // 进入前状态
- beforeEnter (el) {
- el.style.transform = 'translate(0,0)'
- },
- // 进入中
- enter (el, done) {
- // 需要调用元素的offset操作,才有过渡的效果,否则会马上实现过渡
- el.offsetWidth
- //获取小球相对于页面顶部或者
- const ball = this.$refs.ball.getBoundingClientRect()
- //方法二:获取徽标相对于页面顶部和底部的距离,
- //也可以用document.getElementById获取dom
- const badgePosition = document.getElementById("smallball").getBoundingClientRect()
- const xDist = badgePosition.left - ball.left
- const yDist = badgePosition.top - ball.top
- el.style.transform = `translate(${xDist}px,${yDist}px)`
- el.style.transition = "all .5s cubic-bezier(.4,-0.3,1,.68)"
- done()
- },
- // 进入后
- afterEnter () {
- this.ballFlag = !this.ballFlag
- this.carNum = this.num
- },
- }
- })
- </script>
- </html>
方法二:
github中看到,可以借鉴,没有使用getBoundingClientRect,代码量相对较多
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8" />
- <title></title>
- <style type="text/css">
- .shop {
- position: fixed;
- top: 300px;
- left: 400px;
- }
- .ball {
- position: fixed;
- left: 32px;
- bottom: 22px;
- z-index: 200;
- transition: all 0.4s cubic-bezier(0.49, -0.29, 0.75, 0.41);
- /*贝塞尔曲线*/
- }
- .inner {
- width: 16px;
- height: 16px;
- border-radius: 50%;
- background-color: rgb(0, 160, 220);
- transition: all 0.4s linear;
- }
- .cart {
- position: fixed;
- bottom: 22px;
- left: 32px;
- width: 30px;
- height: 30px;
- background-color: rgb(0, 160, 220);
- color: rgb(255, 255, 255);
- }
- </style>
- </head>
- <body>
- <div id="app">
- <ul class="shop">
- <li v-for="item in items">
- <span>{{item.text}}</span>
- <span>{{item.price}}</span>
- <button @click="additem">添加</button>
- </li>
- </ul>
- <div class="cart" style="">{{count}}</div>
- <div class="ball-container">
- <!--小球-->
- <div v-for="ball in balls">
- <transition name="drop" @before-enter="beforeDrop" @enter="dropping" @after-enter="afterDrop">
- <div class="ball" v-show="ball.show">
- <div class="inner inner-hook"></div>
- </div>
- </transition>
- </div>
- </div>
- </div>
- <script src="https://cdn.jsdelivr.net/npm/vue"></script>
- <script>
- new Vue({
- el: "#app",
- data: {
- count: 0,
- items: [{
- text: "苹果",
- price: 15
- },
- {
- text: "香蕉",
- price: 15
- }
- ],
- balls: [ //小球 设为3个
- {
- show: false
- },
- {
- show: false
- },
- {
- show: false
- },
- ],
- dropBalls: [],
- },
- methods: {
- additem(event) {
- this.drop(event.target);
- this.count++;
- },
- drop(el) { //抛物
- for(let i = 0; i < this.balls.length; i++) {
- let ball = this.balls[i];
- if(!ball.show) {
- ball.show = true;
- ball.el = el;
- this.dropBalls.push(ball);
- return;
- }
- }
- },
- beforeDrop(el) { /* 购物车小球动画实现 */
- let count = this.balls.length;
- while(count--) {
- let ball = this.balls[count];
- if(ball.show) {
- let rect = ball.el.getBoundingClientRect(); //元素相对于视口的位置
- let x = rect.left - 32;
- let y = -(window.innerHeight - rect.top - 22); //获取y
- el.style.display = '';
- el.style.webkitTransform = 'translateY(' + y + 'px)'; //translateY
- el.style.transform = 'translateY(' + y + 'px)';
- let inner = el.getElementsByClassName('inner-hook')[0];
- inner.style.webkitTransform = 'translateX(' + x + 'px)';
- inner.style.transform = 'translateX(' + x + 'px)';
- }
- }
- },
- dropping(el, done) { /*重置小球数量 样式重置*/
- let rf = el.offsetHeight;
- el.style.webkitTransform = 'translate3d(0,0,0)';
- el.style.transform = 'translate3d(0,0,0)';
- let inner = el.getElementsByClassName('inner-hook')[0];
- inner.style.webkitTransform = 'translate3d(0,0,0)';
- inner.style.transform = 'translate3d(0,0,0)';
- el.addEventListener('transitionend', done);
- },
- afterDrop(el) { /*初始化小球*/
- let ball = this.dropBalls.shift();
- if(ball) {
- ball.show = false;
- el.style.display = 'none';
- }
- }
- }
- })
- </script>
- </body>
- </html>
效果图
vue购物车动画效果的更多相关文章
- javascript仿天猫加入购物车动画效果
javascript仿天猫加入购物车动画效果 注意:首先需要声明的是:代码原思路不是我写的,是在网上找的这种效果,自己使用代码封装了下而已:代码中都有注释,我们最主要的是理解抛物线的思路及在工作中 ...
- 【转】Android 实现蘑菇街购物车动画效果
原文出处:http://blog.csdn.net/wangjinyu501/article/details/38400479 1.思路 目前想到两种方式实现这种效果,一是使用Tween动画,直截 ...
- Android 实现蘑菇街购物车动画效果
版本号:1.0 日期:2014.8.6 版权:© 2014 kince 转载注明出处 使用过蘑菇街的用户基本上都知道有一个增加购物车的动画效果,此处不详细描写叙述想知道的能够去下载体验一下. 1 ...
- 049——VUE中使用animation与transform实现vue的动画效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- JQuery模拟实现天猫购物车动画效果
测试程序源代码下载地址:源码 一.功能描述: 1.点击购买按钮,模拟抛物线将物品弹到购物车里: 2.购物车添加物品后,显示+1动画: 效果图如下: 实现如下: 1.导入jquery相关的包: < ...
- router使用以及vue的动画效果
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- vue过渡动画效果
1 过渡基础 1.1 过渡的方式 Vue 在插入.更新或者移除 DOM 时,提供多种不同方式的应用过渡效果. 包括以下工具: 在 CSS 过渡和动画中自动应用 class 可以配合使用第三方 CSS ...
- jquery商城购物车右侧悬浮加入购物车动画效果
<script type="text/javascript" src="js/jquery-1.7.min.js"></script> ...
- 基于jquery fly插件实现加入购物车抛物线动画效果,jquery.fly.js
在购物网站中,加入购物车的功能是必须的功能,有的网站在用户点击加入购物车按钮时,就会出现该商品从点击出以抛物线的动画相似加入购物车,这个功能看起来非常炫,对用户体验也有一定的提高.下面介绍基于jque ...
随机推荐
- 清空Redis缓存
Redis缓存清理 1.访问redis根目录 cd /usr/local/redis-2.8.19 2.登录redis:redis-cli -h 127.0.0.1 -p 6379 3.查 ...
- APP手工测试01-app专项测试要点-测试、开发环境-敏捷开发
APP专项测试要点 兼容性测试 安装,卸载,升级 交叉事件 PUSH消息推送测试 性能测试 其他类型 兼容性测试 手机型号 系统版本 安卓 (版本4.4开始兼容) IOS(版本9.x开始兼容) 屏幕尺 ...
- Ubuntu 14.04 apache安装配置
http://jingyan.baidu.com/article/6d704a130c8a0d28da51ca5f.html Ubuntu 14.04 apache安装配置 1.安装 ~# apt-g ...
- Windows .net服务器系列 wmic命令使用示例--Examples of WMIC commands for Windows .NET SERVER Family
1.0 Method execution: NICCONFIG (Win32_NetworkAdapterConfiguration) WMIC NICCONFIG WHERE Index=1 CAL ...
- laravel原生sql
转自:https://www.cnblogs.com/zouzhe0/p/6307077.html DB::insert(, ']); $user = DB::]); //我们还 可以看到在执行查询的 ...
- mysql正则替换某个字段值里面的某个字符串
sql语句如下: UPDATE `ccvms_video` SET title=REPLACE(title, "最", "相对") WHERE title LI ...
- Flutter 流式布局列表实例+上拉加载
页面变化的几种方式: 一.StatefulWidget的setState形式 先声明两个变量. ; List<Map> list = []; 写了一个方法,获取数据: void _getH ...
- 【数据库开发】 C连接mysql——常用的函数
转载:http://blog.chinaunix.net/uid-26758020-id-3288633.html 1.MYSQL *mysql_init(MYSQL *mysql) 为mysq ...
- 【VS开发】TCP服务端如何判断客户端断开连接
原文出自:http://www.cnblogs.com/youxin/p/4056041.html 一篇文章: 最近在做一个服务器端程序,C/S结构.功能方面比较简单就是client端与serve ...
- Java基础系列-substring的原理
原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755235.html JDK 6和JDK 7中substring的原理及区别 substring(i ...