今天在vue2源码发现了一个有意思的小动画,挺有趣的,用 svg 和 Dynamics.js 动画库完成,啥也不说,先看看效果
一、看效果

二、看代码
基本也是源码中拿过来的,逻辑也不复杂,就不一步步讲解了,想看效果直接复制到编辑器就可以了。
1<template> 2 <div> 3 <h3>一个有趣的小动画</h3> 4 <div class="ani_box"> 5 <div class="mid_box" > 6 <svg width="320" class="svg_box" height="300"> 7 <path :d="headerPath" fill="#3F51B5"></path> 8 </svg> 9 <div class="draggable_box" :style="contentPosition" 10 @mousedown="startDrag" @touchstart="startDrag" 11 @mousemove="onDrag" @touchmove="onDrag" 12 @mouseup="stopDrag" @touchend="stopDrag" @mouseleave="stopDrag"> 13 <ul> 14 <li v-for="item of 6" :key="item" > 15 {{`这是第${item}`}} 16 </li> 17 </ul> 18 </div> 19 </div> 20 </div> 21 </div> 22</template> 23 24<script> 25 import { addDyna } from '../utils/add_dynamics'; 26 addDyna() 27 export default { 28 name: 'someAnimation', 29 data() { 30 return { 31 c: { x: 160, y: 160 }, 32 start: { x: 0, y: 0 }, 33 dragging: false 34 } 35 }, 36 created() {}, 37 computed: { 38 headerPath() { 39 return 'M0,0 L320,0 320,160' + 40 'Q' + this.c.x + ',' + this.c.y + 41 ' 0,160' 42 }, 43 contentPosition({c}) { 44 let dy = c.y - 160 45 let dampen = dy > 0 ? 2 : 4 46 return { 47 transform: 'translate3d(0,' + dy / dampen + 'px,0)' 48 } 49 } 50 }, 51 methods: { 52 startDrag(e) { 53 e = e.changedTouches ? e.changedTouches[0]: e; 54 this.dragging = true; 55 this.start.x = e.pageX; 56 this.start.y = e.pageY; 57 }, 58 onDrag(e) { 59 e = e.changedTouches ? e.changedTouches[0]: e; 60 if(this.dragging) { 61 this.c.x = 160 + ( e.pageX - this.start.x ); 62 // 计算一个阻力因素 63 let dy = e.pageY - this.start.y; 64 let dampen = dy > 0 ? 2 : 4; 65 this.c.y = 160 + dy / dampen; 66 } 67 }, 68 stopDrag(e) { 69 let self = this; 70 if(this.dragging) { 71 // this.dragging = false 72 dynamics.animate(this.c, { 73 x: 160, 74 y: 160 75 }, { 76 type: dynamics.spring, 77 duration: 700, 78 friction: 280, 79 complete: self.dragging = false 80 }) 81 } 82 }, 83 } 84 85 } 86</script> 87 88<style lang='scss' > 89 h3,ul{ 90 margin: 0; 91 padding: 0; 92 } 93 .svg_box{ 94 position: absolute; 95 top: 0; 96 left: 0; 97 right: 0; 98 } 99 .ani_box{ 100 min-height: 300px; 101 .mid_box{ 102 width: 320px; 103 border: 1px solid #ccc; 104 margin: 0 auto; 105 position: relative; 106 } 107 } 108 .draggable_box{ 109 position: absolute; 110 top: 160px; 111 left: 0; 112 right: 0; 113 li{ 114 height: 40px; 115 list-style: none; 116 } 117 } 118</style>
三、简单解释
Dynamics.js
Dynamics.js 是一个用于创建物理动画 JavaScript 库。你只需要把 dynamics.js 引入你的页面,然后就可以激活任何 DOM 元素的 CSS 属性动画,也可以结合 SVG 使用。 gif看到的效果就是由它完成
1dynamics.animate(this.c, { 2 x: 160, 3 y: 160 4 }, { 5 type: dynamics.spring, 6 duration: 700, 7 friction: 280, 8 complete: self.dragging = false 9})
这里可以看到接收三个参数,第一个参数也可以传入 dom节点。 具体了解可以去看文档,这里不瞎逼逼。
我是动态加载的在线js addDyna
1 2export const addDyna = () => { 3 let script = document.createElement('script'); 4 script.src = 'http://dynamicsjs.com/lib/dynamics.js'; 5 6 let t = document.getElementsByTagName('script')[0]; 7 t.parentNode.insertBefore(script, t) 8 9 script.onload = () => { 10 console.log('加载成功') 11 script = null; 12 } 13 script.onerror = (err) => { 14 console.log('加载失败',JSON.stringify(err)) 15 } 16 17}
