今天在vue2源码发现了一个有意思的小动画,挺有趣的,用 svg 和 Dynamics.js 动画库完成,啥也不说,先看看效果
一、看效果
二、看代码
基本也是源码中拿过来的,逻辑也不复杂,就不一步步讲解了,想看效果直接复制到编辑器就可以了。
<template>
<div>
<h3>一个有趣的小动画</h3>
<div class="ani_box">
<div class="mid_box" >
<svg width="320" class="svg_box" height="300">
<path :d="headerPath" fill="#3F51B5"></path>
</svg>
<div class="draggable_box" :style="contentPosition"
@mousedown="startDrag" @touchstart="startDrag"
@mousemove="onDrag" @touchmove="onDrag"
@mouseup="stopDrag" @touchend="stopDrag" @mouseleave="stopDrag">
<ul>
<li v-for="item of 6" :key="item" >
{{`这是第${item}`}}
</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<script>
import { addDyna } from '../utils/add_dynamics';
addDyna()
export default {
name: 'someAnimation',
data() {
return {
c: { x: 160, y: 160 },
start: { x: 0, y: 0 },
dragging: false
}
},
created() {},
computed: {
headerPath() {
return 'M0,0 L320,0 320,160' +
'Q' + this.c.x + ',' + this.c.y +
' 0,160'
},
contentPosition({c}) {
let dy = c.y - 160
let dampen = dy > 0 ? 2 : 4
return {
transform: 'translate3d(0,' + dy / dampen + 'px,0)'
}
}
},
methods: {
startDrag(e) {
e = e.changedTouches ? e.changedTouches[0]: e;
this.dragging = true;
this.start.x = e.pageX;
this.start.y = e.pageY;
},
onDrag(e) {
e = e.changedTouches ? e.changedTouches[0]: e;
if(this.dragging) {
this.c.x = 160 + ( e.pageX - this.start.x );
// 计算一个阻力因素
let dy = e.pageY - this.start.y;
let dampen = dy > 0 ? 2 : 4;
this.c.y = 160 + dy / dampen;
}
},
stopDrag(e) {
let self = this;
if(this.dragging) {
// this.dragging = false
dynamics.animate(this.c, {
x: 160,
y: 160
}, {
type: dynamics.spring,
duration: 700,
friction: 280,
complete: self.dragging = false
})
}
},
}
}
</script>
<style lang='scss' >
h3,ul{
margin: 0;
padding: 0;
}
.svg_box{
position: absolute;
top: 0;
left: 0;
right: 0;
}
.ani_box{
min-height: 300px;
.mid_box{
width: 320px;
border: 1px solid #ccc;
margin: 0 auto;
position: relative;
}
}
.draggable_box{
position: absolute;
top: 160px;
left: 0;
right: 0;
li{
height: 40px;
list-style: none;
}
}
</style>
三、简单解释
Dynamics.js
Dynamics.js 是一个用于创建物理动画 JavaScript 库。你只需要把 dynamics.js 引入你的页面,然后就可以激活任何 DOM 元素的 CSS 属性动画,也可以结合 SVG 使用。 gif看到的效果就是由它完成
dynamics.animate(this.c, {
x: 160,
y: 160
}, {
type: dynamics.spring,
duration: 700,
friction: 280,
complete: self.dragging = false
})
这里可以看到接收三个参数,第一个参数也可以传入 dom节点。 具体了解可以去看文档,这里不瞎逼逼。
我是动态加载的在线js addDyna
export const addDyna = () => {
let script = document.createElement('script');
script.src = 'http://dynamicsjs.com/lib/dynamics.js';
let t = document.getElementsByTagName('script')[0];
t.parentNode.insertBefore(script, t)
script.onload = () => {
console.log('加载成功')
script = null;
}
script.onerror = (err) => {
console.log('加载失败',JSON.stringify(err))
}
}