Shiki Magic Move
Magic Move 让代码块之间的变化像 Keynote 一样平滑过渡:同一段代码的两次形态自动计算差异,旧形态飞移到新形态。讲重构、优化、演进最合适。
magic 代码块
在代码块语言后加 {magic} 启用:
markdown
```ts {magic}
// 第一次点击:原始版本
function sum(n: number) {
let total = 0
for (let i = 0; i < n; i++) {
total += i
}
return total
}
```配合 v-click 显示下一形态:
markdown
```ts {magic}
// 第二次点击:优化版本
function sum(n: number) {
return n * (n - 1) / 2
}
```两次点击之间,代码自动做平滑变形动画:保留的元素移动、变化的字符过渡、新增/删除淡入淡出。
工作原理
| 步骤 | 说明 |
|---|---|
| 分词 | Shiki 对两段代码做语法分析 |
| 计算差异 | 找出相同/新增/删除的片段 |
| 匹配元素 | 相似片段建立映射关系 |
| 过渡动画 | 对应元素平滑移动,其余淡入淡出 |
使用者只需提供两段代码,动画由引擎自动完成。
与 TwoSlash 集成
TwoSlash 为 TypeScript 代码生成行内类型提示(// ^? 显示类型),与 Magic Move 组合:
markdown
```ts {magic}
const user = { name: 'slidev', age: 2 }
user.age.toFixed(2)
// ^?
```- TwoSlash 在代码中渲染类型气泡
// ^?注释让上一行表达式显示推断类型- 与 magic 组合:讲类型演变时同时有类型提示与过渡动画
代码演变展示
逐步重构
markdown
```ts {magic}
// 步骤一:命名不清晰
function calc(a: number, b: number) {
return a + b
}ts
// 步骤二:语义化命名
function addPrices(priceA: number, priceB: number) {
return priceA + priceB
}ts
// 步骤三:类型收窄
function addPrices(priceA: number, priceB: number): number {
return Number((priceA + priceB).toFixed(2))
}
三次点击演示逐步重构,观众直观看到代码如何一步步演化。
## 使用速查
| 能力 | 写法 |
|------|------|
| 启用 Magic Move | `` ```ts {magic} `` |
| 多段演进 | 多个 `{magic}` 代码块 + v-click |
| 类型提示 | `// ^?` 注释(TwoSlash) |
| 语言支持 | 任意 Shiki 支持语言 |
## 使用建议
| 场景 | 推荐 |
|------|------|
| 讲重构 | magic 逐步对比 |
| 讲算法优化 | magic 前后两版 |
| 讲类型推断 | magic + TwoSlash |
| 纯静态代码 | 普通代码块 |
## 注意点
| 注意 | 说明 |
|------|------|
| 代码结构差异 | 大幅改动时过渡可能不完全平滑 |
| 长代码 | 短小代码块的过渡效果最佳 |
| 导出格式 | 动画仅在浏览器演示中体现 |
Magic Move 把"前后对比两张图"变成"一处平滑动画",是技术演示中最具表现力的代码呈现方式,与 Monaco 的运行能力互补:一个展示演进,一个体验运行。