前几天在好朋友楼上小黑的介绍下,看到了某个平台的官网,里面有一个人物介绍的模块,里面的动画感觉不错,于是就自己动手写了一个。
1.0 原官网示例
当然这里去掉了具体信息,原网站是里面圆圈中是人物的头像,旁边是介绍信息,每个人物就沿着圆弧移动到指定位置
2.0 我们实现的结果
当点击中间开始时,几个小球一次转动到固定角度
3.0 简单分析下
要让小圆在圆弧上动,我们只需要知道圆心在圆弧上的坐标(x,y)就行了 所以当我们知道外圆的半径,小圆的半径,以及角度再利用三角函数就可以计算出 小圆在圆弧上定位的位置 top right
4.0 代码实现
这里是将 移动的小圆封装成一个组件 moveRound,只需要将 大圆半径,小圆半径,转动的角度,剩下的就可以按自己需要添加
<template>
<div>
<h3>围绕圆弧移动动画</h3>
<div class="arc_bo" >
<move-round :minR="25" :bigR="150" :angle="30" ref="mRound1" > </move-round>
<span class="start" @click="toMove" >开始</span>
</div>
</div>
</template>
<script>
import moveRound from './components/moveRound.vue'
export default {
name: 'arcMoveAni',
components: {
moveRound
},
methods: {
toMove() {
this.$refs.mRound1.toMove()
}
}
}
</script>
<style scoped>
.arc_bo{
margin: 0 auto;
width: 6rem;
height: 6rem;
border-radius: 50%;
border: 1px solid #ccc;
position: relative;
margin-top: 2rem;
}
.start{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
color: #f40;
width: 1rem;
height: 1rem;
border-radius: 50%;
border: 1px solid #ccc;
text-align: center;
line-height: 1rem;
}
</style>
moveRound组件, 角度的动态改变计算 top,right的值,其中 raf,caf是 requestAnimationFrame的兼容处理,不明白的可以看往期文章或者百度。
<template>
<div>
<div class="round" :style="setPosition" ></div>
</div>
</template>
<script>
let timer = 0
import { raf,caf } from '../../utils/raf'
export default {
name: 'moveRound',
props: {
angle: { // 需要转动的角度
type: Number,
default: 0
},
bigR: { // 外层大圆半径
type: Number,
default: 0
},
minR: { //移动小圆半径
type: Number,
default: 0
},
backgroundColor: {
type: String,
default: '#7fffd4'
}
},
data() {
return {
top: '',
right: '',
setAngle: 0
}
},
mounted() {
},
computed: {
/**
* sin 对应 y 的值,转换为定位中距离顶部top等于 圆的半径 - y - 小圆半径(让圆心在圆弧上)
* cos 对应 x 的值,转换为定位中距离右边right等于 圆的半径 - x - 小圆半径
* **/
setPosition( { top, right ,setAngle, bigR, minR, backgroundColor} ) {
let size = minR*2 + 'px'
let x = bigR * ( 1 - Math.cos(setAngle * Math.PI/180)) - minR
let y = bigR * ( 1 - Math.sin(setAngle * Math.PI/180)) - minR
right = x + 'px'
top = y + 'px'
return {
top,
right,
width: size,
height: size,
backgroundColor
}
}
},
methods: {
toMove() {
// 调整 累加值,改变速度
this.setAngle += 1
timer = raf(this.toMove)
// 结束动画
if(this.setAngle > this.angle) {
caf(timer)
// 也可以根据需要重复执行
// this.setAngle = 0
}
}
}
}
</script>
<style>
.round{
position: absolute;
will-change: top,right;
border-radius: 50%;
}
</style>
5.0 总结
主要的点就是根据角度计算位置,只要思路正确,应该可以少走弯路。