feat: 将动画组件改为可折叠式设计

This commit is contained in:
dmy
2026-03-03 16:17:40 +08:00
parent 07063ec638
commit c19e7b7631

View File

@@ -1,27 +1,24 @@
<template> <template>
<q-card class="shadow-2"> <q-card class="shadow-2">
<q-card-section class="bg-indigo-50"> <q-card-section class="bg-indigo-50 cursor-pointer" @click="toggleExpand">
<div class="text-h6 text-indigo-900 flex items-center gap-2"> <div class="text-h6 text-indigo-900 flex items-center gap-2">
<q-icon name="animation" /> <q-icon name="animation" />
EGM 动画可视化 EGM 动画可视化
<q-space /> <q-space />
<q-toggle <q-icon :name="expanded ? 'expand_less' : 'expand_more'" />
v-model="enabled"
label="启用动画"
color="primary"
@update:model-value="onEnableChange"
/>
</div> </div>
</q-card-section> </q-card-section>
<q-card-section> <q-slide-transition>
<canvas <q-card-section v-show="expanded">
ref="canvasRef" <canvas
:width="canvasWidth" ref="canvasRef"
:height="canvasHeight" :width="canvasWidth"
class="animation-canvas" :height="canvasHeight"
/> class="animation-canvas"
</q-card-section> />
</q-card-section>
</q-slide-transition>
</q-card> </q-card>
</template> </template>
@@ -40,12 +37,26 @@ const coordRange = {
yMax: 500 yMax: 500
} }
// 启用/禁用动画 // 展开/折叠状态
const enabled = ref(false) const expanded = ref(false)
const canvasRef = ref<HTMLCanvasElement | null>(null) const canvasRef = ref<HTMLCanvasElement | null>(null)
let ctx: CanvasRenderingContext2D | null = null let ctx: CanvasRenderingContext2D | null = null
let tick = 0 let tick = 0
// 切换展开/折叠
const toggleExpand = () => {
expanded.value = !expanded.value
if (expanded.value) {
// 展开时初始化画布
setTimeout(() => {
if (canvasRef.value) {
ctx = canvasRef.value.getContext('2d')
initFig()
}
}, 350) // 等待动画完成
}
}
// 坐标转换:数据坐标 -> Canvas 坐标 // 坐标转换:数据坐标 -> Canvas 坐标
const toCanvasX = (x: number): number => { const toCanvasX = (x: number): number => {
return ((x - coordRange.xMin) / (coordRange.xMax - coordRange.xMin)) * canvasWidth return ((x - coordRange.xMin) / (coordRange.xMax - coordRange.xMin)) * canvasWidth
@@ -58,7 +69,7 @@ const toCanvasY = (y: number): number => {
// 初始化画布 // 初始化画布
const initFig = () => { const initFig = () => {
if (!ctx || !enabled.value) return if (!ctx || !expanded.value) return
ctx.fillStyle = '#ffffff' ctx.fillStyle = '#ffffff'
ctx.fillRect(0, 0, canvasWidth, canvasHeight) ctx.fillRect(0, 0, canvasWidth, canvasHeight)
@@ -108,7 +119,7 @@ const clear = () => {
// 添加 RG 线(地面线) // 添加 RG 线(地面线)
const addRgLine = (points: [number, number][]) => { const addRgLine = (points: [number, number][]) => {
if (!ctx || !enabled.value || !points || points.length === 0) return if (!ctx || !expanded.value || !points || points.length === 0) return
ctx.strokeStyle = '#2196F3' ctx.strokeStyle = '#2196F3'
ctx.lineWidth = 2 ctx.lineWidth = 2
@@ -128,7 +139,7 @@ const addRgLine = (points: [number, number][]) => {
// 添加 RS 圆(地线保护弧)- 这是每帧第一个绘制的元素,先清除画布 // 添加 RS 圆(地线保护弧)- 这是每帧第一个绘制的元素,先清除画布
const addRs = (rs: number, rsX: number, rsY: number) => { const addRs = (rs: number, rsX: number, rsY: number) => {
if (!ctx || !enabled.value) return if (!ctx || !expanded.value) return
// 清除并重新初始化画布,准备绘制新的一帧 // 清除并重新初始化画布,准备绘制新的一帧
clear() clear()
@@ -147,7 +158,7 @@ const addRs = (rs: number, rsX: number, rsY: number) => {
// 添加 RC 圆(导线暴露弧) // 添加 RC 圆(导线暴露弧)
const addRc = (rc: number, rcX: number, rcY: number) => { const addRc = (rc: number, rcX: number, rcY: number) => {
if (!ctx || !enabled.value) return if (!ctx || !expanded.value) return
const canvasX = toCanvasX(rcX) const canvasX = toCanvasX(rcX)
const canvasY = toCanvasY(rcY) const canvasY = toCanvasY(rcY)
@@ -169,7 +180,7 @@ const addExposeArea = (
intersectionX2: number, intersectionX2: number,
intersectionY2: number intersectionY2: number
) => { ) => {
if (!ctx || !enabled.value) return if (!ctx || !expanded.value) return
ctx.strokeStyle = '#F44336' ctx.strokeStyle = '#F44336'
ctx.lineWidth = 3 ctx.lineWidth = 3
@@ -189,29 +200,23 @@ const addExposeArea = (
// 暂停并刷新 - 用于下一帧绘制前清除 // 暂停并刷新 - 用于下一帧绘制前清除
const pause = () => { const pause = () => {
if (!ctx || !enabled.value) return if (!ctx || !expanded.value) return
tick += 1 tick += 1
// 不立即清除,等待下一次绑图时清除 // 不立即清除,等待下一次绑图时清除
// 这样用户可以看到当前帧 // 这样用户可以看到当前帧
} }
// 启用状态改变
const onEnableChange = (value: boolean) => {
if (value) {
initFig()
} else {
clear()
}
}
// 暴露方法给父组件或全局调用 // 暴露方法给父组件或全局调用
const animationApi = { const animationApi = {
enable: (enable: boolean) => { enable: (enable: boolean) => {
enabled.value = enable expanded.value = enable
onEnableChange(enable) if (enable && canvasRef.value) {
ctx = canvasRef.value.getContext('2d')
initFig()
}
}, },
isEnabled: () => enabled.value, isEnabled: () => expanded.value,
initFig, initFig,
clear, clear,
addRgLine, addRgLine,
@@ -229,13 +234,6 @@ declare global {
} }
onMounted(() => { onMounted(() => {
if (canvasRef.value) {
ctx = canvasRef.value.getContext('2d')
if (enabled.value) {
initFig()
}
}
// 注册全局 API // 注册全局 API
window.animationApi = animationApi window.animationApi = animationApi
}) })