---
title: "IconMorph 图标形变"
description: "以弹簧物理在描边图标间形变的组件"
category: Effects
status: beta
since: 0.6.0
tags: [icon, morph, vector, animation, spring, svg, 图标, 动效]
syncStatus: reviewed
verified: true
---

## 用法

### 基础
改变 `icon` 时，以弹簧过渡到新图标。
:::TuffDemoWrapper{demo="IconMorphIconMorphDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import { ref } from 'vue'
  import { TxIconMorph } from '@talex-touch/tuffex/icon-morph'

  const isOpen = ref(false)
  </script>

  <template>
    <button @click="isOpen = !isOpen">
      <TxIconMorph :icon="isOpen ? 'close' : 'menu'" spring="snappy" :size="24" />
    </button>
  </template>
---
:::

### 受控进度
传入 `from`、`to` 与 `progress`，把形变绑定到手势、滚动或自定义过渡，此时不使用弹簧。

```vue
<template>
  <TxIconMorph from="menu" to="close" :progress="dragProgress" :size="24" />
</template>
```

### 最佳实践

- 用于有状态切换的按钮：播放 / 暂停、菜单 / 关闭、搜索 / 清除、加号 / 勾选。
- 点击反馈用 `spring="snappy"`，较大的界面切换用 `spring="smooth"`。
- 描边风格图标（Lucide、Tabler、Feather）效果最好；实心图标改用交叉淡入。

## API 参考

### 属性

| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `icon` | `IconInput` | - | 非受控模式的当前图标：预设名（`'menu'`、`'close'`、`'check'` 等）、路径 `d`、`IconNode` 或 `<svg>` 字符串。 |
| `from` | `IconInput` | - | 受控模式的起始图标。 |
| `to` | `IconInput` | - | 受控模式的目标图标。 |
| `progress` | `number` | - | 受控进度（0–1）；传入后进入受控模式，停用弹簧。 |
| `spring` | `'snappy' \| 'smooth' \| 'bouncy' \| { stiffness?: number, damping?: number }` | `'snappy'` | 非受控过渡的弹簧参数。 |
| `size` | `number \| string` | `24` | 图标宽高（px）。 |
| `strokeWidth` | `number \| string` | `2` | 描边宽度。 |
| `absoluteStrokeWidth` | `boolean` | `false` | 描边宽度不随 `size` 缩放（Lucide 约定）。 |
| `viewBox` | `string` | `'0 0 24 24'` | 根 `<svg>` 的 viewBox，默认对应引擎的 24 网格。 |
| `label` | `string` | - | 无障碍名称：设置后渲染 `role="img"` 与 `<title>`，否则为 `aria-hidden="true"`。 |
| `color` | `string` | `'currentColor'` | 描边颜色。 |
| `reducedMotion` | `'never' \| 'user' \| 'always'` | `'never'` | 减少动态效果策略：`user` 跟随系统设置，`always` 每次都直接跳到终点。 |

### 暴露方法

| 名称 | 类型 | 说明 |
|------|------|------|
| `morphTo` | `(icon: IconInput, spring?: SpringPreset \| MorphOptions) => void` | 以弹簧形变到目标图标；省略 `spring` 时沿用同名属性。 |
| `set` | `(icon: IconInput) => void` | 直接切到目标图标，不播放动画。 |
| `seek` | `(icon: IconInput, t: number) => void` | 把朝目标图标的形变定格在进度 `t`（0–1），不经弹簧。 |
| `progress` | `number` | 只读，当前形变进度；静止时为 `1`。 |
| `getMorph` | `() => Morph \| null` | 返回底层 `Morph` 驱动；尚未出现图标时为 `null`。 |

## 技术实现

- 引擎用二维 Procrustes 对齐两条路径并探测旋转，在极坐标空间插值，由阻尼弹簧驱动。
- 导出 `TxIconMorph`、`IconMorph`、`TxMorphIcon`、`MorphIcon`，可从 `@talex-touch/tuffex/icon-morph` 或 `@talex-touch/tuffex` 引入。
- 源码：`packages/tuffex/packages/components/src/icon-morph/`。

<TuffDocSourceLink />
