用途
layout-morph 用于在 Vue 3 + Quasar 项目中实现共享元素形变:一个较小的界面元素(卡片、列表行或 chip)在同一屏幕内扩展为对应的详情面板,而不是通过硬切换直接替换。形变动画由 Quasar 的 v-morph 指令承担,悬停、按压和对话框入场等弹性效果由 @motion-physics 负责。
适用与不适用场景
适用:卡片、列表行或 chip 与其展开面板位于同一视图中;用户明确要求共享元素或布局过渡。
不适用:不要对每次路由切换都做形变;不要把数据表形变到自身。若形变只是装饰性效果,应优先使用路由过渡或 @motion-physics 的 modalEnter。
主要能力
- 基于 Quasar v-morph 的同屏共享元素形变,无需额外安装包(Quasar 已内置 v-morph)。
- 通过组名(group name)关联紧凑态与展开态两个元素,切换组名即切换视图。
- 颜色使用 @aura-design-tokens 提供的变量(如 --app-surface-card、--app-border、--app-text-main)。
使用方式
- 在由 @primevue-aura 管理的 bootstrap 中注册 Morph 插件:
import { Quasar, Dialog, Notify, Morph } from 'quasar';
app.use(Quasar, { plugins: { Dialog, Notify, Morph } });
- 让两个状态共享同一个组名,示例如下:
<script setup>
import { ref } from 'vue';
const morphGroup = ref('card');
function toggleView() {
morphGroup.value = morphGroup.value === 'card' ? 'expanded' : 'card';
}
</script>
<template>
<div>
<div
v-morph:card:step-group="morphGroup"
class="compact-card"
@click="toggleView"
>
<div class="card-title">Performance metrics</div>
</div>
<div v-morph:expanded:step-group="morphGroup" class="expanded-panel">
<h3>Performance metrics</h3>
<button type="button" @click="toggleView">Close</button>
</div>
</div>
</template>
<style scoped>
.compact-card,
.expanded-panel {
background: var(--app-surface-card);
border: 1px solid var(--app-border);
color: var(--app-text-main);
}
.compact-card {
width: 280px;
padding: 16px;
border-radius: 12px;
cursor: pointer;
}
.expanded-panel {
width: min(600px, 100%);
padding: 24px;
border-radius: 16px;
}
</style>
- GSAP Flip 仅在紧凑态与展开态无法共存于同一组件时使用(例如列表在一个路由、详情页在另一个路由),此时才安装 gsap;其他情况优先使用路由过渡或 @motion-physics 的 modalEnter。
减弱动效
当 prefers-reduced-motion: reduce 匹配时,应直接切换组名而不执行形变,立即显示展开面板。
后续
形变实现后,仅当该界面还需要层次感时才使用 @fancy-ui-craft,否则进入 @visual-verification。