slidev-magic-move

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Shiki Magic Move

Shiki Magic Move

This skill covers Shiki Magic Move, a powerful feature that creates smooth animated transitions between different code states, similar to Keynote's Magic Move effect.
本技能介绍Shiki Magic Move,这是一个强大的功能,可在不同代码状态间创建流畅的动画过渡效果,类似Keynote的Magic Move效果。

When to Use This Skill

何时使用本技能

  • Showing code evolution step by step
  • Refactoring demonstrations
  • Before/after code comparisons
  • Tutorial walkthroughs
  • Animated code transformations
  • 逐步展示代码演进过程
  • 重构演示
  • 代码前后对比
  • 教程步骤讲解
  • 代码转换动画

How Magic Move Works

Magic Move的工作原理

Magic Move analyzes two code blocks and:
  1. Identifies unchanged tokens
  2. Finds moved/renamed tokens
  3. Detects added/removed tokens
  4. Animates the transition smoothly
Magic Move会分析两段代码块并:
  1. 识别未更改的代码标记
  2. 查找移动/重命名的代码标记
  3. 检测新增/删除的代码标记
  4. 流畅地为过渡过程添加动画

Basic Syntax

基本语法

Use 4 backticks with
md magic-move
:
markdown
````md magic-move
```js
console.log('Hello')
```
```js
console.log('Hello, World!')
```
````
Each code block represents a step, animated on click.
使用4个反引号并加上
md magic-move
markdown
````md magic-move
```js
console.log('Hello')
```
```js
console.log('Hello, World!')
```
````
每个代码块代表一个步骤,点击时会播放动画。

Step-by-Step Example

分步示例

Refactoring Journey

重构过程演示

markdown
````md magic-move
```js
// Step 1: Original code
function add(a, b) {
  return a + b
}
```

```js
// Step 2: Add types
function add(a: number, b: number) {
  return a + b
}
```

```js
// Step 3: Add return type
function add(a: number, b: number): number {
  return a + b
}
```

```ts
// Step 4: Convert to arrow function
const add = (a: number, b: number): number => a + b
```
````
markdown
````md magic-move
```js
// Step 1: 原始代码
function add(a, b) {
  return a + b
}
```

```js
// Step 2: 添加类型注解
function add(a: number, b: number) {
  return a + b
}
```

```js
// Step 3: 添加返回值类型
function add(a: number, b: number): number {
  return a + b
}
```

```ts
// Step 4: 转换为箭头函数
const add = (a: number, b: number): number => a + b
```
````

Multiple Steps

多步骤演示

markdown
````md magic-move
```js
const name = 'world'
```
```js
const name = 'world'
const greeting = 'Hello'
```
```js
const name = 'world'
const greeting = 'Hello'
console.log(`${greeting}, ${name}!`)
```
```js
const name = 'world'
const greeting = 'Hello'
console.log(`${greeting}, ${name}!`)
// Output: Hello, world!
```
````
markdown
````md magic-move
```js
const name = 'world'
```
```js
const name = 'world'
const greeting = 'Hello'
```
```js
const name = 'world'
const greeting = 'Hello'
console.log(`${greeting}, ${name}!`)
```
```js
const name = 'world'
const greeting = 'Hello'
console.log(`${greeting}, ${name}!`)
// Output: Hello, world!
```
````

Combining with Line Highlighting

结合行高亮功能

Add highlights within Magic Move:
markdown
````md magic-move {lines: true}
```js {*|1|2|3}
const a = 1
const b = 2
const c = 3
```
```js {*}
const sum = 1 + 2 + 3
```
````
在Magic Move中添加高亮效果:
markdown
````md magic-move {lines: true}
```js {*|1|2|3}
const a = 1
const b = 2
const c = 3
```
```js {*}
const sum = 1 + 2 + 3
```
````

Advanced Options

高级选项

Control Animation Timing

控制动画触发时机

markdown
````md magic-move {at: 3}
```js
// Starts at click 3
const x = 1
```
```js
const x = 1
const y = 2
```
````
markdown
````md magic-move {at: 3}
```js
// 第3次点击时开始
const x = 1
```
```js
const x = 1
const y = 2
```
````

Disable Line Numbers

禁用行号

markdown
````md magic-move {lines: false}
```js
const x = 1
```
```js
const x = 2
```
````
markdown
````md magic-move {lines: false}
```js
const x = 1
```
```js
const x = 2
```
````

Combined Options

组合选项

markdown
````md magic-move {at: 2, lines: true}
```js {*|1|2}
const first = 1
const second = 2
```
```js {*}
const result = first + second
```
````
markdown
````md magic-move {at: 2, lines: true}
```js {*|1|2}
const first = 1
const second = 2
```
```js {*}
const result = first + second
```
````

Real-World Examples

实际场景示例

React Hook Evolution

React Hook演进

markdown
````md magic-move
```jsx
// Class component state
class Counter extends React.Component {
  state = { count: 0 }

  increment = () => {
    this.setState({ count: this.state.count + 1 })
  }

  render() {
    return (
      <button onClick={this.increment}>
        {this.state.count}
      </button>
    )
  }
}
```

```jsx
// Function component with useState
function Counter() {
  const [count, setCount] = useState(0)

  const increment = () => {
    setCount(count + 1)
  }

  return (
    <button onClick={increment}>
      {count}
    </button>
  )
}
```

```jsx
// Simplified with inline handler
function Counter() {
  const [count, setCount] = useState(0)

  return (
    <button onClick={() => setCount(c => c + 1)}>
      {count}
    </button>
  )
}
```
````
markdown
````md magic-move
```jsx
// 类组件状态
class Counter extends React.Component {
  state = { count: 0 }

  increment = () => {
    this.setState({ count: this.state.count + 1 })
  }

  render() {
    return (
      <button onClick={this.increment}>
        {this.state.count}
      </button>
    )
  }
}
```

```jsx
// 函数组件结合useState
function Counter() {
  const [count, setCount] = useState(0)

  const increment = () => {
    setCount(count + 1)
  }

  return (
    <button onClick={increment}>
      {count}
    </button>
  )
}
```

```jsx
// 内联处理函数简化版
function Counter() {
  const [count, setCount] = useState(0)

  return (
    <button onClick={() => setCount(c => c + 1)}>
      {count}
    </button>
  )
}
```
````

API Evolution

API演进

markdown
````md magic-move
```js
// Callbacks
function fetchUser(id, callback) {
  fetch(`/api/users/${id}`)
    .then(res => res.json())
    .then(data => callback(null, data))
    .catch(err => callback(err, null))
}

fetchUser(1, (err, user) => {
  if (err) console.error(err)
  else console.log(user)
})
```

```js
// Promises
function fetchUser(id) {
  return fetch(`/api/users/${id}`)
    .then(res => res.json())
}

fetchUser(1)
  .then(user => console.log(user))
  .catch(err => console.error(err))
```

```js
// Async/Await
async function fetchUser(id) {
  const res = await fetch(`/api/users/${id}`)
  return res.json()
}

try {
  const user = await fetchUser(1)
  console.log(user)
} catch (err) {
  console.error(err)
}
```
````
markdown
````md magic-move
```js
// 回调函数方式
function fetchUser(id, callback) {
  fetch(`/api/users/${id}`)
    .then(res => res.json())
    .then(data => callback(null, data))
    .catch(err => callback(err, null))
}

fetchUser(1, (err, user) => {
  if (err) console.error(err)
  else console.log(user)
})
```

```js
// Promise方式
function fetchUser(id) {
  return fetch(`/api/users/${id}`)
    .then(res => res.json())
}

fetchUser(1)
  .then(user => console.log(user))
  .catch(err => console.error(err))
```

```js
// Async/Await方式
async function fetchUser(id) {
  const res = await fetch(`/api/users/${id}`)
  return res.json()
}

try {
  const user = await fetchUser(1)
  console.log(user)
} catch (err) {
  console.error(err)
}
```
````

Building a Function

函数构建过程

markdown
````md magic-move
```typescript
function processData() {

}
```

```typescript
function processData(data) {

}
```

```typescript
function processData(data: string[]) {

}
```

```typescript
function processData(data: string[]): string[] {
  return data
}
```

```typescript
function processData(data: string[]): string[] {
  return data
    .filter(item => item.length > 0)
}
```

```typescript
function processData(data: string[]): string[] {
  return data
    .filter(item => item.length > 0)
    .map(item => item.trim())
}
```

```typescript
function processData(data: string[]): string[] {
  return data
    .filter(item => item.length > 0)
    .map(item => item.trim())
    .sort((a, b) => a.localeCompare(b))
}
```
````
markdown
````md magic-move
```typescript
function processData() {

}
```

```typescript
function processData(data) {

}
```

```typescript
function processData(data: string[]) {

}
```

```typescript
function processData(data: string[]): string[] {
  return data
}
```

```typescript
function processData(data: string[]): string[] {
  return data
    .filter(item => item.length > 0)
}
```

```typescript
function processData(data: string[]): string[] {
  return data
    .filter(item => item.length > 0)
    .map(item => item.trim())
}
```

```typescript
function processData(data: string[]): string[] {
  return data
    .filter(item => item.length > 0)
    .map(item => item.trim())
    .sort((a, b) => a.localeCompare(b))
}
```
````

SQL Query Building

SQL查询构建

markdown
````md magic-move
```sql
SELECT * FROM users
```

```sql
SELECT id, name, email FROM users
```

```sql
SELECT id, name, email FROM users
WHERE active = true
```

```sql
SELECT id, name, email FROM users
WHERE active = true
ORDER BY created_at DESC
```

```sql
SELECT id, name, email FROM users
WHERE active = true
ORDER BY created_at DESC
LIMIT 10
```
````
markdown
````md magic-move
```sql
SELECT * FROM users
```

```sql
SELECT id, name, email FROM users
```

```sql
SELECT id, name, email FROM users
WHERE active = true
```

```sql
SELECT id, name, email FROM users
WHERE active = true
ORDER BY created_at DESC
```

```sql
SELECT id, name, email FROM users
WHERE active = true
ORDER BY created_at DESC
LIMIT 10
```
````

Patterns and Tips

模式与技巧

Start Simple, Add Complexity

从简到繁,逐步添加复杂度

markdown
````md magic-move
```js
// Start with the goal
const result = processData(input)
```

```js
// Show the implementation
function processData(input) {
  return input
}

const result = processData(input)
```

```js
// Add details
function processData(input) {
  return input
    .filter(x => x != null)
    .map(x => transform(x))
}

const result = processData(input)
```
````
markdown
````md magic-move
```js
// 先展示最终目标
const result = processData(input)
```

```js
// 展示实现过程
function processData(input) {
  return input
}

const result = processData(input)
```

```js
// 添加细节
function processData(input) {
  return input
    .filter(x => x != null)
    .map(x => transform(x))
}

const result = processData(input)
```
````

Show Problem Then Solution

先展示问题,再给出解决方案

markdown
````md magic-move
```js
// Problem: Callback hell
getData(function(a) {
  getMoreData(a, function(b) {
    getMoreData(b, function(c) {
      getMoreData(c, function(d) {
        // Finally done
      })
    })
  })
})
```

```js
// Solution: Promises
getData()
  .then(a => getMoreData(a))
  .then(b => getMoreData(b))
  .then(c => getMoreData(c))
  .then(d => {
    // Clean and flat!
  })
```
````
markdown
````md magic-move
```js
// 问题:回调地狱
getData(function(a) {
  getMoreData(a, function(b) {
    getMoreData(b, function(c) {
      getMoreData(c, function(d) {
        // 终于完成了
      })
    })
  })
})
```

```js
// 解决方案:Promise
getData()
  .then(a => getMoreData(a))
  .then(b => getMoreData(b))
  .then(c => getMoreData(c))
  .then(d => {
    // 简洁又清晰!
  })
```
````

Highlight Changes with Comments

用注释高亮变更点

markdown
````md magic-move
```js
const config = {
  debug: true,
  timeout: 1000
}
```

```js
const config = {
  debug: false,    // Changed!
  timeout: 1000
}
```

```js
const config = {
  debug: false,
  timeout: 5000    // Increased!
}
```
````
markdown
````md magic-move
```js
const config = {
  debug: true,
  timeout: 1000
}
```

```js
const config = {
  debug: false,    // 已修改!
  timeout: 1000
}
```

```js
const config = {
  debug: false,
  timeout: 5000    // 已延长!
}
```
````

Best Practices

最佳实践

  1. Small Steps: Each transition should show one logical change
  2. Maintain Context: Keep surrounding code visible when possible
  3. Use Comments: Add comments to explain what's changing
  4. Consistent Style: Keep formatting consistent across steps
  5. Test the Animation: Verify smooth transitions before presenting
  1. 小步迭代:每次过渡只展示一个逻辑变更
  2. 保留上下文:尽可能保留周边代码的可见性
  3. 使用注释:添加注释解释变更内容
  4. 风格一致:确保各步骤的代码格式一致
  5. 测试动画:在展示前验证过渡效果是否流畅

Common Mistakes

常见错误

Too many changes at once
Step 1: Original code
Step 2: Completely different code
Incremental changes
Step 1: Original
Step 2: Add one feature
Step 3: Add another feature
Step 4: Refactor
Lost context
Step 1: function foo() { ... }
Step 2: const bar = ...  // Where did foo go?
Preserved context
Step 1: function foo() { ... }
Step 2: function foo() { const bar = ... }
单次变更过多
步骤1:原始代码
步骤2:完全不同的代码
增量式变更
步骤1:原始代码
步骤2:添加一个功能
步骤3:添加另一个功能
步骤4:重构代码
丢失上下文
步骤1:function foo() { ... }
步骤2:const bar = ...  // foo去哪了?
保留上下文
步骤1:function foo() { ... }
步骤2:function foo() { const bar = ... }

Interactive Playground

交互式体验 playground

访问以下地址体验Magic Move:https://shiki-magic-move.netlify.app/

Output Format

输出格式

When creating Magic Move animations:
ANIMATION GOAL: [What transformation are you showing?]

STEPS:
1. [Initial state - describe]
2. [Change 1 - describe]
3. [Change 2 - describe]
...

CODE:
````md magic-move {[options]}
```[lang]
[Step 1 code]
[Step 2 code]
...

SPEAKER NOTES:
- Step 1: [What to say]
- Step 2: [What to say]
```
创建Magic Move动画时的参考格式:
ANIMATION GOAL: [你要展示的转换效果是什么?]

STEPS:
1. [初始状态 - 描述]
2. [变更1 - 描述]
3. [变更2 - 描述]
...

CODE:
````md magic-move {[选项]}
```[语言]
[步骤1代码]
[步骤2代码]
...

SPEAKER NOTES:
- Step 1: [讲解内容]
- Step 2: [讲解内容]
```