vue实现爆炸图效果
实现爆炸图效果的方法
爆炸图(Exploded View)常用于展示物体的拆解或分层结构。在Vue中可以通过CSS动画、过渡效果或第三方库实现。
使用CSS过渡和动画
通过Vue的过渡系统结合CSS实现基础爆炸效果:
<template>
<div class="exploded-view">
<div
v-for="(part, index) in parts"
:key="index"
class="part"
:style="{ transform: `translate(${offsets[index].x}px, ${offsets[index].y}px)` }"
>
{{ part.name }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
parts: [
{ name: '部件A' },
{ name: '部件B' },
{ name: '部件C' }
],
offsets: [
{ x: 0, y: 0 },
{ x: 50, y: -30 },
{ x: -40, y: 20 }
]
}
}
}
</script>
<style>
.part {
position: absolute;
transition: transform 0.5s ease-out;
background: #fff;
padding: 10px;
border: 1px solid #ddd;
}
</style>
使用GSAP动画库
对于更复杂的动画效果,可以引入GSAP库:
<template>
<div ref="container" class="exploded-view">
<div
v-for="(part, index) in parts"
:key="index"
:ref="`part${index}`"
class="part"
>
{{ part.name }}
</div>
</div>
</template>
<script>
import { gsap } from 'gsap'
export default {
data() {
return {
parts: [
{ name: '部件A' },
{ name: '部件B' },
{ name: '部件C' }
]
}
},
mounted() {
this.animateParts()
},
methods: {
animateParts() {
const tl = gsap.timeline()
tl.to(this.$refs.part0, { x: 0, y: 0, duration: 0.5 })
tl.to(this.$refs.part1, { x: 80, y: -40, duration: 0.5 }, 0)
tl.to(this.$refs.part2, { x: -60, y: 30, duration: 0.5 }, 0)
}
}
}
</script>
使用Three.js实现3D爆炸图
对于3D场景,可以结合Three.js:
<template>
<div ref="container" class="three-container"></div>
</template>
<script>
import * as THREE from 'three'
export default {
mounted() {
this.initThree()
},
methods: {
initThree() {
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000)
const renderer = new THREE.WebGLRenderer()
renderer.setSize(this.$refs.container.clientWidth, this.$refs.container.clientHeight)
this.$refs.container.appendChild(renderer.domElement)
// 创建多个部件
const parts = []
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
for(let i=0; i<5; i++) {
const part = new THREE.Mesh(geometry, material)
part.position.x = i * 1.5
scene.add(part)
parts.push(part)
}
camera.position.z = 5
// 动画循环
const animate = () => {
requestAnimationFrame(animate)
// 爆炸效果
parts.forEach((part, i) => {
part.position.x += Math.sin(Date.now() * 0.001 + i) * 0.01
part.position.y += Math.cos(Date.now() * 0.001 + i) * 0.01
})
renderer.render(scene, camera)
}
animate()
}
}
}
</script>
<style>
.three-container {
width: 100%;
height: 400px;
}
</style>
使用SVG和动态组件
对于2D矢量图形,可以使用SVG结合动态组件:
<template>
<svg width="400" height="400" viewBox="0 0 400 400">
<g v-for="(part, index) in parts" :key="index"
:transform="`translate(${part.x}, ${part.y})`"
@click="explode(index)">
<circle cx="0" cy="0" r="30" :fill="part.color" />
<text x="0" y="0" text-anchor="middle" fill="white">{{ part.name }}</text>
</g>
</svg>
</template>
<script>
export default {
data() {
return {
parts: [
{ name: 'A', x: 100, y: 100, color: 'red', exploded: false },
{ name: 'B', x: 200, y: 100, color: 'blue', exploded: false },
{ name: 'C', x: 150, y: 200, color: 'green', exploded: false }
]
}
},
methods: {
explode(index) {
this.parts[index].exploded = !this.parts[index].exploded
if(this.parts[index].exploded) {
this.parts[index].x += Math.random() * 50 - 25
this.parts[index].y += Math.random() * 50 - 25
} else {
// 恢复原始位置
this.parts[index].x = index === 0 ? 100 : index === 1 ? 200 : 150
this.parts[index].y = index === 2 ? 200 : 100
}
}
}
}
</script>
以上方法可根据实际需求选择或组合使用,CSS过渡适合简单效果,GSAP提供更丰富的动画控制,Three.js适用于3D场景,SVG则适合矢量图形展示。







