vue实现浮窗游动
Vue实现浮窗游动效果
核心实现思路
使用Vue的响应式数据绑定和CSS动画结合,通过修改元素的transform属性实现游动效果。需要计算随机运动路径并平滑过渡。
基础实现代码
<template>
<div class="floating-window" :style="windowStyle">
<!-- 浮窗内容 -->
</div>
</template>
<script>
export default {
data() {
return {
posX: 0,
posY: 0,
windowWidth: 200,
windowHeight: 150
}
},
computed: {
windowStyle() {
return {
transform: `translate(${this.posX}px, ${this.posY}px)`,
width: `${this.windowWidth}px`,
height: `${this.height}px`
}
}
},
mounted() {
this.startAnimation()
},
methods: {
getRandomPosition() {
const maxX = window.innerWidth - this.windowWidth
const maxY = window.innerHeight - this.windowHeight
return {
x: Math.random() * maxX,
y: Math.random() * maxY
}
},
startAnimation() {
const duration = 3000 + Math.random() * 4000
const newPos = this.getRandomPosition()
this.posX = newPos.x
this.posY = newPos.y
setTimeout(() => {
this.startAnimation()
}, duration)
}
}
}
</script>
<style>
.floating-window {
position: fixed;
background: white;
box-shadow: 0 0 10px rgba(0,0,0,0.2);
transition: transform 3s ease-in-out;
z-index: 1000;
}
</style>
高级优化方案
增加贝塞尔曲线路径运动,使移动轨迹更自然。使用requestAnimationFrame实现平滑动画。
methods: {
animate() {
const start = { x: this.posX, y: this.posY }
const end = this.getRandomPosition()
const control1 = this.getRandomControlPoint(start, end)
const control2 = this.getRandomControlPoint(start, end)
const startTime = performance.now()
const duration = 3000
const step = (currentTime) => {
const elapsed = currentTime - startTime
const progress = Math.min(elapsed / duration, 1)
// 三次贝塞尔曲线计算
this.posX = this.cubicBezier(
start.x, control1.x, control2.x, end.x, progress
)
this.posY = this.cubicBezier(
start.y, control1.y, control2.y, end.y, progress
)
if (progress < 1) {
requestAnimationFrame(step)
} else {
this.animate()
}
}
requestAnimationFrame(step)
},
cubicBezier(p0, p1, p2, p3, t) {
const mt = 1 - t
return mt*mt*mt*p0 + 3*mt*mt*t*p1 + 3*mt*t*t*p2 + t*t*t*p3
}
}
边界检测处理
防止浮窗移出可视区域,在随机位置生成时增加边界检查。
getRandomPosition() {
const padding = 20
const maxX = window.innerWidth - this.windowWidth - padding
const maxY = window.innerHeight - this.windowHeight - padding
return {
x: padding + Math.random() * maxX,
y: padding + Math.random() * maxY
}
}
性能优化建议
- 使用
will-change: transform提升动画性能 - 适当降低动画频率,避免过度消耗资源
- 在组件销毁时清除动画循环
beforeDestroy() {
cancelAnimationFrame(this.animationId)
}






