使用动画的三个函数

v-on:before-enter="beforeEnter"

v-on:enter="enter"

v-on:after-enter="afterEnter"

将动画函数easy改成贝塞尔曲线的

效果:

直接上代码:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <!-- import CSS -->
  6. <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  7. <style type="text/css">
  8. html,body{margin:0;padding:0}
  9. body{
  10. position:fixed;
  11. width:100%;
  12. height:100%
  13. }
  14. #app,#app>div{
  15. width:100%;
  16. height:100%
  17. }
  18. .car{
  19. width:100%;
  20. height:40px;
  21. line-height:30px;
  22. position:absolute;
  23. bottom:0;
  24. border:1px solid #ddd;
  25. display:flex;
  26. justify-content:flex-end;
  27. }
  28. .car-content{
  29. margin-right:30px;
  30. background-color:#eee;
  31. padding:0 8px;
  32. display:flex;
  33. align-items:center;
  34. }
  35. .compute{
  36. position:absolute;
  37. width:300px;
  38. text-align:center;
  39. height:30px;
  40. line-height:27px;
  41. top:0;
  42. left:0;bottom:0;right:0;
  43. margin:auto;
  44. border:1px solid #ddd
  45. }
  46. .compute span,.compute button{
  47. vertical-align:middle
  48. }
  49. .ball{
  50. position:absolute;
  51. top: 448px;
  52. left: 743px;
  53. width:17px;
  54. height:17px;
  55. background-color:red;
  56. border-radius:50%;
  57. z-index:999;
  58. }
  59. </style>
  60. </head>
  61. <body>
  62. <div id="app">
  63. <div>
  64. <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter">
  65. <div class="ball" v-if="ballFlag"></div>
  66. </transition>
  67.  
  68. <div class="compute">
  69. <span>{{num}}</span>
  70. <button @click="add">+</button>
  71. <button @click="sub">-</button>
  72. <button @click="addToshowCar" >加入购物车</button>
  73. </div>
  74. <div class="car">
  75. <span class="car-content">购物车</span>
  76. </div>
  77. </div>
  78. </div>
  79. </body>
  80. <!-- import Vue before Element -->
  81. <script src="https://unpkg.com/vue/dist/vue.js"></script>
  82. <!-- import JavaScript -->
  83. <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  84. <script>
  85. new Vue({
  86. el: '#app',
  87. data: function() {
  88. return {
  89. num:0,
  90. ballFlag:false
  91. }
  92. },
  93. methods:{
  94. add(){
  95. this.num++
  96. },
  97. sub(){
  98. if(this.num>1){
  99. this.num--
  100. }else{
  101. return false
  102. }
  103. },
  104. addToshowCar(){
  105. this.ballFlag = !this.ballFlag
  106. },
  107. // 动画钩子函数
  108. // 进入前状态
  109. beforeEnter (el) {
  110. el.style.transform = 'translate(0,0)'
  111. },
  112. // 进入中
  113. enter (el, done) {
  114. // 需要调用元素的offset操作,才有过渡的效果,否则会马上实现过渡
  115. el.offsetWidth
  116. el.style.transform = 'translate(569px,437px)'
  117. el.style.transition = "all 2s cubic-bezier(.4,-0.3,1,.68)"
  118. done()
  119. },
  120. // 进入后
  121. afterEnter () {
  122. this.ballFlag = !this.ballFlag
  123. },
  124. }
  125. })
  126. </script>
  127. </html>

问题:

发现此种方法不适应于不同屏幕的分辨率,如果换了一个尺寸的小球的位置会发生变化

解决思路:

1、首先在页面进行resize的时候重新设置小球的top值left值

2、算出小球初始停下来的位置相对于页面的左边和顶部x,y     getBoundingClientRect()可以获取

3、算出小球最终停下来的位置相对于页面的左边的顶部x1,y1

4、所以不管是多大的分辨率,将x1-x,y1-y算出来的结果值就是页面在动画之间移动的距离

5、将算出来的结果值放进动画进入中的translate里面

用到的知识点,使用v-if的时候会出现屏幕闪烁,可以添加v-cloak属性,然后再在样式中添加

  1. [v-cloak] { display: none }
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <!-- import CSS -->
  6. <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  7.  
  8. <style type="text/css">
  9. html,body{margin:0;padding:0}
  10. body{
  11. position:fixed;
  12. width:100%;
  13. height:100%
  14. }
  15. #app,#app>div{
  16. width:100%;
  17. height:100%
  18. }
  19. .car{
  20. width:100%;
  21. height:40px;
  22. line-height:30px;
  23. position:absolute;
  24. bottom:0;
  25. border:1px solid #ddd;
  26. display:flex;
  27. justify-content:flex-end;
  28. }
  29. .car-content{
  30. margin-right:30px;
  31. background-color:#eee;
  32. padding:0 8px;
  33. display:flex;
  34. align-items:center;
  35. position:relative
  36. }
  37. .car-content>.smallball{
  38. position:absolute;
  39. top:-8px;
  40. right:-8px;
  41. width:17px;
  42. height:17px;
  43. text-align:center;
  44. color:#fff;
  45. font-size:12px;
  46. line-height:17px;
  47. background-color:red;
  48. border-radius:50%;
  49. z-index:999;
  50. }
  51. .compute{
  52. position:absolute;
  53. width:300px;
  54. text-align:center;
  55. height:30px;
  56. line-height:27px;
  57. top:0;
  58. left:0;bottom:0;right:0;
  59. margin:auto;
  60. border:1px solid #ddd
  61. }
  62. .compute span,.compute button{
  63. vertical-align:middle
  64. }
  65. .ball{
  66. position:absolute;
  67. top: 294px;
  68. left: 548px;
  69. width:17px;
  70. height:17px;
  71. background-color:red;
  72. border-radius:50%;
  73. z-index:999;
  74. /*transform:translate(569px,437px)*/
  75. }
  76. [v-cloak] { display: none }
  77. </style>
  78. </head>
  79. <body>
  80. <div id="app">
  81. <div>
  82. <transition v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter">
  83. <div class="ball" v-if="ballFlag" v-cloak ref="ball" :style="{top: `${tt}px`,left:`${ll}px`}"></div>
  84. </transition>
  85.  
  86. <div class="compute">
  87. <button @click="sub">-</button>
  88. <span v-cloak ref="num">{{num}}</span>
  89. <button @click="add">+</button>
  90. <button @click="addToshowCar" ref="btn">加入购物车</button>
  91. </div>
  92. <div class="car">
  93. <div class="car-content">
  94. 购物车
  95. <span class="smallball" id="smallball">{{carNum}}</span>
  96. </div>
  97. </div>
  98. </div>
  99. </div>
  100. </body>
  101. <!-- import Vue before Element -->
  102. <script src="https://unpkg.com/vue/dist/vue.js"></script>
  103. <!-- import JavaScript -->
  104. <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  105. <script>
  106. new Vue({
  107. el: '#app',
  108. data: function() {
  109. return {
  110. num:0,
  111. ballFlag:false,
  112. tt:0,//小球因为自适应需要重新设置top值
  113. ll:0,
  114. carNum:0
  115. }
  116. },
  117. mounted(){
  118. this.initTopLeft()
  119. window.addEventListener(
  120. "resize",this.initTopLeft,false
  121. );
  122. },
  123. methods:{
  124. initTopLeft(){
  125. let t = this.$refs.btn.getBoundingClientRect().top;
  126. let l = this.$refs.btn.getBoundingClientRect().left;
  127. this.tt = t
  128. this.ll = l
  129. },
  130. add(){
  131. this.num++
  132. },
  133. sub(){
  134. if(this.num>1){
  135. this.num--
  136. }else{
  137. return false
  138. }
  139. },
  140. addToshowCar(){
  141. this.ballFlag = !this.ballFlag
  142. },
  143. // 动画钩子函数
  144. // 进入前状态
  145. beforeEnter (el) {
  146. el.style.transform = 'translate(0,0)'
  147. },
  148. // 进入中
  149. enter (el, done) {
  150. // 需要调用元素的offset操作,才有过渡的效果,否则会马上实现过渡
  151. el.offsetWidth
  152. //获取小球相对于页面顶部或者
  153. const ball = this.$refs.ball.getBoundingClientRect()
  154. //方法二:获取徽标相对于页面顶部和底部的距离,
  155. //也可以用document.getElementById获取dom
  156. const badgePosition = document.getElementById("smallball").getBoundingClientRect()
  157. const xDist = badgePosition.left - ball.left
  158. const yDist = badgePosition.top - ball.top
  159. el.style.transform = `translate(${xDist}px,${yDist}px)`
  160. el.style.transition = "all .5s cubic-bezier(.4,-0.3,1,.68)"
  161. done()
  162. },
  163. // 进入后
  164. afterEnter () {
  165. this.ballFlag = !this.ballFlag
  166. this.carNum = this.num
  167. },
  168. }
  169. })
  170. </script>
  171. </html>

方法二:

github中看到,可以借鉴,没有使用getBoundingClientRect,代码量相对较多

  1. <!DOCTYPE html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="utf-8" />
  6. <title></title>
  7. <style type="text/css">
  8. .shop {
  9. position: fixed;
  10. top: 300px;
  11. left: 400px;
  12. }
  13.  
  14. .ball {
  15. position: fixed;
  16. left: 32px;
  17. bottom: 22px;
  18. z-index: 200;
  19. transition: all 0.4s cubic-bezier(0.49, -0.29, 0.75, 0.41);
  20. /*贝塞尔曲线*/
  21. }
  22.  
  23. .inner {
  24. width: 16px;
  25. height: 16px;
  26. border-radius: 50%;
  27. background-color: rgb(0, 160, 220);
  28. transition: all 0.4s linear;
  29. }
  30.  
  31. .cart {
  32. position: fixed;
  33. bottom: 22px;
  34. left: 32px;
  35. width: 30px;
  36. height: 30px;
  37. background-color: rgb(0, 160, 220);
  38. color: rgb(255, 255, 255);
  39. }
  40. </style>
  41. </head>
  42.  
  43. <body>
  44. <div id="app">
  45. <ul class="shop">
  46. <li v-for="item in items">
  47. <span>{{item.text}}</span>
  48. <span>{{item.price}}</span>
  49. <button @click="additem">添加</button>
  50. </li>
  51. </ul>
  52. <div class="cart" style="">{{count}}</div>
  53. <div class="ball-container">
  54. <!--小球-->
  55. <div v-for="ball in balls">
  56. <transition name="drop" @before-enter="beforeDrop" @enter="dropping" @after-enter="afterDrop">
  57. <div class="ball" v-show="ball.show">
  58. <div class="inner inner-hook"></div>
  59. </div>
  60. </transition>
  61. </div>
  62. </div>
  63. </div>
  64. <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  65. <script>
  66. new Vue({
  67. el: "#app",
  68. data: {
  69. count: 0,
  70. items: [{
  71. text: "苹果",
  72. price: 15
  73. },
  74. {
  75. text: "香蕉",
  76. price: 15
  77. }
  78. ],
  79. balls: [ //小球 设为3个
  80. {
  81. show: false
  82. },
  83. {
  84. show: false
  85. },
  86. {
  87. show: false
  88. },
  89. ],
  90. dropBalls: [],
  91. },
  92. methods: {
  93. additem(event) {
  94. this.drop(event.target);
  95. this.count++;
  96. },
  97. drop(el) { //抛物
  98. for(let i = 0; i < this.balls.length; i++) {
  99. let ball = this.balls[i];
  100. if(!ball.show) {
  101. ball.show = true;
  102. ball.el = el;
  103. this.dropBalls.push(ball);
  104. return;
  105. }
  106. }
  107. },
  108. beforeDrop(el) { /* 购物车小球动画实现 */
  109. let count = this.balls.length;
  110. while(count--) {
  111. let ball = this.balls[count];
  112. if(ball.show) {
  113. let rect = ball.el.getBoundingClientRect(); //元素相对于视口的位置
  114. let x = rect.left - 32;
  115. let y = -(window.innerHeight - rect.top - 22); //获取y
  116. el.style.display = '';
  117. el.style.webkitTransform = 'translateY(' + y + 'px)'; //translateY
  118. el.style.transform = 'translateY(' + y + 'px)';
  119. let inner = el.getElementsByClassName('inner-hook')[0];
  120. inner.style.webkitTransform = 'translateX(' + x + 'px)';
  121. inner.style.transform = 'translateX(' + x + 'px)';
  122. }
  123. }
  124. },
  125. dropping(el, done) { /*重置小球数量 样式重置*/
  126. let rf = el.offsetHeight;
  127. el.style.webkitTransform = 'translate3d(0,0,0)';
  128. el.style.transform = 'translate3d(0,0,0)';
  129. let inner = el.getElementsByClassName('inner-hook')[0];
  130. inner.style.webkitTransform = 'translate3d(0,0,0)';
  131. inner.style.transform = 'translate3d(0,0,0)';
  132. el.addEventListener('transitionend', done);
  133. },
  134. afterDrop(el) { /*初始化小球*/
  135. let ball = this.dropBalls.shift();
  136. if(ball) {
  137. ball.show = false;
  138. el.style.display = 'none';
  139. }
  140. }
  141. }
  142. })
  143. </script>
  144. </body>
  145.  
  146. </html>

效果图

vue购物车动画效果的更多相关文章

  1. javascript仿天猫加入购物车动画效果

    javascript仿天猫加入购物车动画效果   注意:首先需要声明的是:代码原思路不是我写的,是在网上找的这种效果,自己使用代码封装了下而已:代码中都有注释,我们最主要的是理解抛物线的思路及在工作中 ...

  2. 【转】Android 实现蘑菇街购物车动画效果

    原文出处:http://blog.csdn.net/wangjinyu501/article/details/38400479 1.思路   目前想到两种方式实现这种效果,一是使用Tween动画,直截 ...

  3. Android 实现蘑菇街购物车动画效果

    版本号:1.0  日期:2014.8.6 版权:© 2014 kince 转载注明出处   使用过蘑菇街的用户基本上都知道有一个增加购物车的动画效果,此处不详细描写叙述想知道的能够去下载体验一下. 1 ...

  4. 049——VUE中使用animation与transform实现vue的动画效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. JQuery模拟实现天猫购物车动画效果

    测试程序源代码下载地址:源码 一.功能描述: 1.点击购买按钮,模拟抛物线将物品弹到购物车里: 2.购物车添加物品后,显示+1动画: 效果图如下: 实现如下: 1.导入jquery相关的包: < ...

  6. router使用以及vue的动画效果

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  7. vue过渡动画效果

    1 过渡基础 1.1 过渡的方式 Vue 在插入.更新或者移除 DOM 时,提供多种不同方式的应用过渡效果. 包括以下工具: 在 CSS 过渡和动画中自动应用 class 可以配合使用第三方 CSS ...

  8. jquery商城购物车右侧悬浮加入购物车动画效果

    <script type="text/javascript" src="js/jquery-1.7.min.js"></script> ...

  9. 基于jquery fly插件实现加入购物车抛物线动画效果,jquery.fly.js

    在购物网站中,加入购物车的功能是必须的功能,有的网站在用户点击加入购物车按钮时,就会出现该商品从点击出以抛物线的动画相似加入购物车,这个功能看起来非常炫,对用户体验也有一定的提高.下面介绍基于jque ...

随机推荐

  1. 清空Redis缓存

    Redis缓存清理   1.访问redis根目录    cd  /usr/local/redis-2.8.19 2.登录redis:redis-cli -h 127.0.0.1 -p 6379 3.查 ...

  2. APP手工测试01-app专项测试要点-测试、开发环境-敏捷开发

    APP专项测试要点 兼容性测试 安装,卸载,升级 交叉事件 PUSH消息推送测试 性能测试 其他类型 兼容性测试 手机型号 系统版本 安卓 (版本4.4开始兼容) IOS(版本9.x开始兼容) 屏幕尺 ...

  3. Ubuntu 14.04 apache安装配置

    http://jingyan.baidu.com/article/6d704a130c8a0d28da51ca5f.html Ubuntu 14.04 apache安装配置 1.安装 ~# apt-g ...

  4. 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 ...

  5. laravel原生sql

    转自:https://www.cnblogs.com/zouzhe0/p/6307077.html DB::insert(, ']); $user = DB::]); //我们还 可以看到在执行查询的 ...

  6. mysql正则替换某个字段值里面的某个字符串

    sql语句如下: UPDATE `ccvms_video` SET title=REPLACE(title, "最", "相对") WHERE title LI ...

  7. Flutter 流式布局列表实例+上拉加载

    页面变化的几种方式: 一.StatefulWidget的setState形式 先声明两个变量. ; List<Map> list = []; 写了一个方法,获取数据: void _getH ...

  8. 【数据库开发】 C连接mysql——常用的函数

    转载:http://blog.chinaunix.net/uid-26758020-id-3288633.html 1.MYSQL *mysql_init(MYSQL *mysql)    为mysq ...

  9. 【VS开发】TCP服务端如何判断客户端断开连接

    原文出自:http://www.cnblogs.com/youxin/p/4056041.html 一篇文章:   最近在做一个服务器端程序,C/S结构.功能方面比较简单就是client端与serve ...

  10. Java基础系列-substring的原理

    原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755235.html JDK 6和JDK 7中substring的原理及区别 substring(i ...