CSS动画与变换

48 阅读5分钟

第9章: CSS动画与变换

🎯 本章重点

  • CSS变换(Transforms)2D和3D
  • CSS动画(Animations)关键帧和属性
  • 性能优化和硬件加速
  • 现代动画技术和最佳实践

📖 内容概述

9.1 CSS变换基础

9.1.1 2D变换
.transform-2d {
  transform: 
    translate(50px, 100px)  /* 移动 */
    rotate(45deg)           /* 旋转 */
    scale(1.5)             /* 缩放 */
    skew(30deg, 20deg);     /* 倾斜 */
}

/* 单独变换属性 */
.separate-transforms {
  translate: 50px 100px;
  rotate: 45deg;
  scale: 1.5;
  skew: 30deg 20deg;
}
9.1.2 变换原点
.transform-origin-example {
  transform: rotate(45deg);
  transform-origin: top left;  /* 左上角 */
  /* 其他值: center, bottom right, 50% 50%, 100px 200px */
}

9.2 3D变换

9.2.1 3D变换基础
.container-3d {
  perspective: 1000px;        /* 透视距离 */
  transform-style: preserve-3d; /* 保持3D空间 */
}

.card-3d {
  transform: 
    rotateX(45deg)           /* X轴旋转 */
    rotateY(30deg)           /* Y轴旋转 */
    rotateZ(15deg)           /* Z轴旋转 */
    translate3d(50px, 0, 100px); /* 3D移动 */
}

/* 背面可见性 */
.card-3d {
  backface-visibility: hidden; /* 隐藏背面 */
}
9.2.2 3D变换函数
.advanced-3d {
  transform: 
    matrix3d( /* 3D矩阵变换 */
      1, 0, 0, 0,
      0, 1, 0, 0, 
      0, 0, 1, 0,
      50, 100, 0, 1
    )
    perspective(500px)       /* 单独透视 */
    rotate3d(1, 1, 1, 45deg); /* 自定义轴旋转 */
}

9.3 CSS过渡

9.3.1 过渡基础
.transition-basic {
  transition: all 0.3s ease-in-out;
}

/* 详细配置 */
.transition-detailed {
  transition-property: transform, opacity, background-color;
  transition-duration: 0.3s, 0.5s, 0.2s;
  transition-timing-function: ease-in, ease-out, linear;
  transition-delay: 0s, 0.1s, 0.2s;
}
9.3.2 缓动函数
/* 内置缓动函数 */
.easing-examples {
  transition-timing-function: 
    ease,           /* 默认 */
    ease-in,        /* 加速 */
    ease-out,       /* 减速 */
    ease-in-out,    /* 加速然后减速 */
    linear,         /* 匀速 */
    step-start,     /* 步进开始 */
    step-end,       /* 步进结束 */
    steps(4, jump-start); /* 4步进 */
}

/* 自定义三次贝塞尔 */
.custom-easing {
  transition-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
}

9.4 CSS动画

9.4.1 关键帧动画
@keyframes slide-in {
  from {
    transform: translateX(-100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

@keyframes bounce {
  0%, 20%, 53%, 80%, 100% {
    transform: translate3d(0, 0, 0);
  }
  40%, 43% {
    transform: translate3d(0, -30px, 0);
  }
  70% {
    transform: translate3d(0, -15px, 0);
  }
  90% {
    transform: translate3d(0, -4px, 0);
  }
}

.animated-element {
  animation: slide-in 0.6s ease-out, bounce 1s ease-in-out 0.6s;
}
9.4.2 动画属性控制
.animation-controls {
  animation-name: slide-in, fade-in;
  animation-duration: 0.6s, 0.8s;
  animation-timing-function: ease-out, ease-in;
  animation-delay: 0s, 0.3s;
  animation-iteration-count: 1, infinite;
  animation-direction: normal, alternate;
  animation-fill-mode: both, none;
  animation-play-state: running, paused;
}

/* 简写形式 */
.animation-shorthand {
  animation: 
    slide-in 0.6s ease-out,
    fade-in 0.8s ease-in 0.3s infinite alternate;
}

9.5 性能优化

9.5.1 硬件加速
.performance-optimized {
  /* 触发GPU加速的属性 */
  transform: translateZ(0);
  will-change: transform, opacity;
  
  /* 避免重排的属性 */
  opacity: 0.9;
  filter: blur(5px);
}

/* 仅对需要动画的元素使用will-change */
.animating-element {
  will-change: transform;
}

/* 动画结束后移除will-change */
.animating-element.animation-ended {
  will-change: auto;
}
9.5.2 合成层优化
.composite-layer {
  /* 创建独立的合成层 */
  transform: translateZ(0);
  backface-visibility: hidden;
  -webkit-font-smoothing: subpixel-antialiased;
}

/* 避免不必要的重绘 */
.no-repaint {
  /* 使用transform代替top/left */
  transform: translate(100px, 50px);
  
  /* 使用opacity代替visibility */
  opacity: 0;
}

9.6 现代动画技术

9.6.1 滚动触发动画
.scroll-animation {
  animation: fade-in-up 1s ease-out;
  animation-timeline: view();
  animation-range: entry 0% cover 50%;
}

@keyframes fade-in-up {
  from {
    opacity: 0;
    transform: translateY(100px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
9.6.2 视图时间线动画
.view-timeline-animation {
  animation: 
    reveal linear,
    fade-in linear;
  
  animation-timeline: 
    view(block),
    scroll(root block);
  
  animation-range: 
    contain 0% contain 100%,
    entry 0% cover 50%;
}

@keyframes reveal {
  from { 
    transform: scaleX(0); 
  }
  to { 
    transform: scaleX(1); 
  }
}

9.7 交互式动画

9.7.1 鼠标悬停动画
.hover-card {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.hover-card:hover {
  transform: 
    translateY(-8px) 
    scale(1.02);
  box-shadow: 
    0 20px 25px -5px rgba(0, 0, 0, 0.1),
    0 10px 10px -5px rgba(0, 0, 0, 0.04);
}

/* 悬停子元素动画父元素 */
.parent:hover .child {
  animation: bounce 0.5s ease-in-out;
}
9.7.2 焦点和活动状态
.input-animation {
  transition: all 0.2s ease-out;
}

.input-animation:focus {
  transform: scale(1.02);
  box-shadow: 
    0 0 0 3px rgba(59, 130, 246, 0.1),
    0 0 0 1px rgba(59, 130, 246, 0.5);
}

.button-press:active {
  transform: scale(0.95);
  transition: transform 0.1s ease-out;
}

9.8 高级动画模式

9.8.1 交错动画
.stagger-animation > * {
  animation: fade-in-up 0.6s ease-out both;
}

.stagger-animation > *:nth-child(1) { animation-delay: 0.1s; }
.stagger-animation > *:nth-child(2) { animation-delay: 0.2s; }
.stagger-animation > *:nth-child(3) { animation-delay: 0.3s; }
.stagger-animation > *:nth-child(4) { animation-delay: 0.4s; }

/* 使用CSS变量 */
.stagger-vars > * {
  --delay: calc(var(--index) * 0.1s);
  animation-delay: var(--delay);
}
9.8.2 无限循环动画
.pulse {
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

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

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

9.9 动画性能监控

9.9.1 性能检测
// 检测动画性能
function measureAnimationPerformance() {
  const element = document.querySelector('.animated-element');
  const startTime = performance.now();
  
  element.addEventListener('animationend', () => {
    const duration = performance.now() - startTime;
    console.log(`Animation took ${duration}ms`);
    
    // 检查帧率
    const frameRate = calculateFrameRate();
    console.log(`Average frame rate: ${frameRate}fps`);
  });
}

// 使用Performance API
const observer = new PerformanceObserver((list) => {
  list.getEntries().forEach(entry => {
    console.log('Animation frame time:', entry.duration);
  });
});

observer.observe({ entryTypes: ['animation'] });
9.9.2 降级策略
/* 检测减少运动偏好 */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  
  .reduced-motion {
    animation: none;
    transition: none;
  }
}

/* JavaScript检测 */
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
  document.documentElement.classList.add('reduced-motion');
}

9.10 实用动画库模式

9.10.1 动画工具类
/* 淡入动画 */
.fade-in {
  animation: fadeIn 0.6s ease-out;
}

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

/* 滑入动画 */
.slide-in-left {
  animation: slideInLeft 0.6s ease-out;
}

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

/* 弹跳动画 */
.bounce-in {
  animation: bounceIn 0.6s ease-out;
}

@keyframes bounceIn {
  0% { 
    transform: scale(0.3); 
    opacity: 0; 
  }
  50% { 
    transform: scale(1.05); 
  }
  70% { 
    transform: scale(0.9); 
  }
  100% { 
    transform: scale(1); 
    opacity: 1; 
  }
}
9.10.2 动画状态管理
.animation-states {
  /* 初始状态 */
  opacity: 0;
  transform: translateY(50px);
}

.animation-states.animate-in {
  animation: fadeInUp 0.6s ease-out forwards;
}

.animation-states.animate-out {
  animation: fadeOutDown 0.6s ease-in forwards;
}

@keyframes fadeInUp {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeOutDown {
  to {
    opacity: 0;
    transform: translateY(50px);
  }
}

💡 动画最佳实践总结

  1. 性能优先: 使用transform和opacity实现动画
  2. 硬件加速: 合理使用will-change和translateZ(0)
  3. 可访问性: 尊重减少运动偏好
  4. 渐进增强: 提供适当的降级方案
  5. 状态管理: 使用CSS类控制动画状态

🎯 下一章预览

下一章将探讨现代CSS布局技术,包括容器查询、层叠上下文和CSS嵌套等高级特性。


最后更新: 2024年12月