# 动画效果

在 Lynx 中实现动画和过渡效果。

## 过渡动画

### 基础过渡

```css
.element {
  transition: all 0.3s ease;
  opacity: 1;
  transform: scale(1);
}

.element:hover {
  opacity: 0.8;
  transform: scale(1.05);
}
```

### 属性特定过渡

```css
.button {
  background-color: #ff351a;
  transition: background-color 0.3s ease, transform 0.2s ease;
}

.button:active {
  background-color: #e63016;
  transform: scale(0.98);
}
```

## 关键帧动画

### 淡入

```css
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.fade-in {
  animation: fadeIn 0.3s ease-out;
}
```

### 滑入

```css
@keyframes slideIn {
  from {
    transform: translateX(-100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

.slide-in {
  animation: slideIn 0.3s ease-out;
}
```

### 弹跳

```css
@keyframes bounce {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}

.bounce {
  animation: bounce 0.6s ease infinite;
}
```

### 旋转

```css
@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.spin {
  animation: spin 1s linear infinite;
}
```

### 脉冲

```css
@keyframes pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.05);
    opacity: 0.8;
  }
}

.pulse {
  animation: pulse 1.5s ease-in-out infinite;
}
```

## 使用示例

### 列表项进入动画

```jsx
function List({ items }) {
  return (
    <view className="list">
      {items.map((item, index) => (
        <view
          key={item.id}
          className="list-item"
          style={{ animationDelay: `${index * 0.1}s` }}
        >
          <text>{item.name}</text>
        </view>
      ))}
    </view>
  );
}
```

```css
.list-item {
  opacity: 0;
  animation: slideIn 0.3s ease-out forwards;
}

@keyframes slideIn {
  from {
    transform: translateX(-20px);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}
```

### 加载动画

```css
.loading-spinner {
  width: 40px;
  height: 40px;
  border: 3px solid #f0f0f0;
  border-top-color: #ff351a;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
```

### 骨架屏闪烁

```css
.skeleton {
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}
```

## 性能优化

### 使用 transform 和 opacity

```css
/* ✅ 性能友好 */
.optimized {
  transition: transform 0.3s ease, opacity 0.3s ease;
  will-change: transform, opacity;
}

/* ❌ 避免动画这些属性 */
.slow {
  transition: width 0.3s, height 0.3s, margin 0.3s;
}
```

### 硬件加速

```css
.gpu-accelerated {
  transform: translateZ(0);
  /* 或 */
  transform: translate3d(0, 0, 0);
}
```

### 移除 will-change

```css
.animation-complete {
  will-change: auto;
}
```

## 动画最佳实践

1. **使用 transform 和 opacity**: 性能最好的动画属性
2. **限制动画数量**: 避免同时运行太多动画
3. **使用 will-change**: 提前告知浏览器优化
4. **动画完成后清理**: 移除 will-change 和动画类
5. **减少重排**: 避免动画 width、height、margin 等属性
6. **合理使用 requestAnimationFrame**: 复杂动画使用 JS 控制
