目录

一、前置核心知识点:React Native Transform 变换体系

✅ 核心说明

表 1:React Native 鸿蒙端 2D/3D Transform 完整支持属性表(核心必看)

二、完整可运行实战源码

三、源码逐模块深度解析

3.1 初始化与常量定义

3.2 动画变量声明:useRef + Animated.Value 组合

3.3 动画核心逻辑:useEffect 中编写动画规则(鸿蒙端无兼容问题)

3.4 关键适配点:skewX 倾斜动画的鸿蒙端兼容处理

表 2:React Native 鸿蒙端 Animated 动画 useNativeDriver 支持对照表(你的代码核心适配依据)

3.5 插值器 interpolate:动画值的核心映射规则

3.6 渲染层:四大模块完整覆盖 2D/3D 变换所有场景

3.7 内存泄漏防护:组件卸载停止动画

四、鸿蒙端开发补充注意事项


一、前置核心知识点:React Native Transform 变换体系

React Native 为我们提供了一套完整的 transform 变换属性,这套属性在鸿蒙端完全兼容,也是开发动效的基础,所有变换属性均以数组形式配置,支持多属性组合叠加生效,核心分为「基础 2D 变换」和「进阶 3D 变换」两大体系。

✅ 核心说明

  1. React Native 中所有变换均写在组件的 transform 属性中,格式为:transform: [{属性名: 属性值}]
  2. 3D 变换在鸿蒙端和 RN 原生端的规则一致:必须配合 perspective 透视属性使用perspective 的值越小,3D 立体效果越强,值越大效果越平缓
  3. 所有变换属性支持静态赋值、Animated 动画动态赋值两种形式,也是我们实战开发的核心用法

表 1:React Native 鸿蒙端 2D/3D Transform 完整支持属性表(核心必看)

变换类型 具体属性 属性说明 取值规则 鸿蒙端兼容状态
2D 基础变换 translateX/translateY 平移 数值(正数右 / 下偏移,负数左 / 上偏移) ✅ 完美兼容
2D 基础变换 scale/scaleX/scaleY 缩放 数值(1 为原始大小,<1 缩小,>1 放大) ✅ 完美兼容
2D 基础变换 rotate 2D 旋转 字符串(如30deg180deg ✅ 完美兼容
2D 基础变换 skewX/skewY 倾斜形变 字符串(如20deg-15deg ✅ 兼容(动画有特殊适配要求)
3D 进阶变换 perspective 3D 透视(核心) 数值(越小立体感越强) ✅ 完美兼容
3D 进阶变换 rotateX X 轴 3D 旋转 字符串(如360deg90deg ✅ 完美兼容
3D 进阶变换 rotateY Y 轴 3D 旋转 字符串(如360deg90deg ✅ 完美兼容
3D 进阶变换 rotateZ Z 轴 3D 旋转 字符串(如45deg ✅ 完美兼容(等同于 2D rotate)

二、完整可运行实战源码

import React, { useRef, useEffect } from 'react';
import {
  View, Text, StyleSheet, Animated, Easing, ScrollView,
  Dimensions
} from 'react-native';

const { width: screenWidth } = Dimensions.get('window');
const baseW = screenWidth - 40;
const RnTransform2D3DAllDemo = () => {
  const animateScale = useRef(new Animated.Value(1)).current;
  const animateRotate2D = useRef(new Animated.Value(0)).current;
  const animateRotateX = useRef(new Animated.Value(0)).current;
  const animateRotateY = useRef(new Animated.Value(0)).current;
  const animateTranslate = useRef(new Animated.ValueXY({ x: 0, y: 0 })).current;
  const animateSkew = useRef(new Animated.Value(0)).current;

  useEffect(() => {
    // 1. 缩放过渡动画:1 → 1.2 → 1 无限呼吸
    const scaleAnim = Animated.loop(
      Animated.sequence([
        Animated.timing(animateScale, { toValue: 1.2, duration: 1500, easing: Easing.bezier(0.42,0,0.58,1), useNativeDriver: true }),
        Animated.timing(animateScale, { toValue: 1, duration: 1500, easing: Easing.bezier(0.42,0,0.58,1), useNativeDriver: true }),
      ])
    );

    // 2. 2D旋转过渡动画:0° → 360° 无限匀速旋转
    const rotate2dAnim = Animated.loop(
      Animated.timing(animateRotate2D, { toValue: 1, duration: 3000, easing: Easing.linear, useNativeDriver: true })
    );

    // 3. 3D X轴旋转过渡动画:0° → 360° 无限旋转
    const rotateXAnim = Animated.loop(
      Animated.timing(animateRotateX, { toValue: 1, duration: 4000, easing: Easing.linear, useNativeDriver: true })
    );

    // 4. 3D Y轴旋转过渡动画:0° → 360° 无限旋转
    const rotateYAnim = Animated.loop(
      Animated.timing(animateRotateY, { toValue: 1, duration: 4500, easing: Easing.linear, useNativeDriver: true })
    );

    // 5. 平移过渡动画:左右往复平移
    const translateAnim = Animated.loop(
      Animated.sequence([
        Animated.timing(animateTranslate.x, { toValue: 60, duration: 2000, easing: Easing.bezier(0.42,0,0.58,1), useNativeDriver: true }),
        Animated.timing(animateTranslate.x, { toValue: -60, duration: 4000, easing: Easing.bezier(0.42,0,0.58,1), useNativeDriver: true }),
        Animated.timing(animateTranslate.x, { toValue: 0, duration: 2000, easing: Easing.bezier(0.42,0,0.58,1), useNativeDriver: true }),
      ])
    );

    // 6. 倾斜过渡动画:左右往复倾斜
    const skewAnim = Animated.loop(
      Animated.sequence([
        Animated.timing(animateSkew, { 
          toValue: 1, 
          duration: 2000, 
          easing: Easing.bezier(0.42,0,0.58,1), 
          useNativeDriver: false  
        }),
        Animated.timing(animateSkew, { 
          toValue: 0, 
          duration: 2000, 
          easing: Easing.bezier(0.42,0,0.58,1), 
          useNativeDriver: false 
        }),
      ])
    );

    // 启动所有动画
    scaleAnim.start();
    rotate2dAnim.start();
    rotateXAnim.start();
    rotateYAnim.start();
    translateAnim.start();
    skewAnim.start();

    // 组件卸载停止动画,防止内存泄漏(生产级标准)
    return () => {
      scaleAnim.stop(); rotate2dAnim.stop(); rotateXAnim.stop();
      rotateYAnim.stop(); translateAnim.stop(); skewAnim.stop();
    };
  }, []);

  const rotate2dInterpolate = animateRotate2D.interpolate({ inputRange: [0,1], outputRange: ['0deg', '360deg'] });
  const rotateXInterpolate = animateRotateX.interpolate({ inputRange: [0,1], outputRange: ['0deg', '360deg'] });
  const rotateYInterpolate = animateRotateY.interpolate({ inputRange: [0,1], outputRange: ['0deg', '360deg'] });
  const skewXInterpolate = animateSkew.interpolate({ inputRange: [0,1], outputRange: ['0deg', '30deg'] });

  return (
    <ScrollView style={styles.pageContainer} showsVerticalScrollIndicator={false}>
      <View style={styles.moduleBox}>
        <Text style={styles.moduleTitle}>✨ 一、基础2D变换</Text>
        <View style={styles.contentWrap}>
          {/* 2D平移 translateX+translateY:修改组件位置 */}
          <View style={[styles.transformItem, {transform: [{translateX: 40}, {translateY: -20}]}]}>
            <Text style={styles.itemText}>平移 (40,-20)</Text>
          </View>
          {/* 2D缩放 scale/scaleX/scaleY:修改组件大小 */}
          <View style={[styles.transformItem, {transform: [{scale: 0.8}]}]}>
            <Text style={styles.itemText}>缩放 0.8倍</Text>
          </View>
          {/* 2D旋转 rotate:修改组件角度 */}
          <View style={[styles.transformItem, {transform: [{rotate: '30deg'}]}]}>
            <Text style={styles.itemText}>旋转 30°</Text>
          </View>
          {/* 2D倾斜 skewX/skewY:修改组件倾斜度 */}
          <View style={[styles.transformItem, {transform: [{skewX: '20deg'}]}]}>
            <Text style={styles.itemText}>倾斜X 20°</Text>
          </View>
        </View>
      </View>

      <View style={styles.moduleBox}>
        <Text style={styles.moduleTitle}>✨ 二、进阶2D变换</Text>
        <View style={styles.contentWrap}>
          {/* 带动画的缩放变换:呼吸效果 */}
          <Animated.View style={[styles.transformItem, {transform: [{scale: animateScale}]}]}>
            <Text style={styles.itemText}>动画缩放</Text>
          </Animated.View>
          {/* 带动画的2D旋转:无限转圈 */}
          <Animated.View style={[styles.transformItem, {transform: [{rotate: rotate2dInterpolate}]}]}>
            <Text style={styles.itemText}>动画旋转</Text>
          </Animated.View>
          {/* 带动画的平移:左右往复移动 */}
          <Animated.View style={[styles.transformItem, {transform: [{translateX: animateTranslate.x}]}]}>
            <Text style={styles.itemText}>动画平移</Text>
          </Animated.View>
          {/* 带动画的倾斜:左右往复倾斜 */}
          <Animated.View style={[styles.transformItem, {transform: [{skewX: skewXInterpolate}]}]}>
            <Text style={styles.itemText}>动画倾斜</Text>
          </Animated.View>
          {/* 组合2D变换【实战高频】:平移+缩放+旋转 同时生效 */}
          <View style={[styles.transformItem, {transform: [{translateX: 20}, {scale: 1.1}, {rotate: '15deg'}]}]}>
            <Text style={styles.itemText}>组合变换</Text>
          </View>
        </View>
      </View>

      <View style={styles.moduleBox}>
        <Text style={styles.moduleTitle}>✨ 三、核心3D变换</Text>
        <Text style={styles.tipsText}>RN中3D变换必须配合perspective(透视),值越小立体感越强</Text>
        <View style={styles.contentWrap}>
          {/* 3D基础:透视 + X轴旋转 【最常用3D效果】 */}
          <Animated.View style={[styles.transformItem, {transform: [{perspective: 200}, {rotateX: rotateXInterpolate}]}]}>
            <Text style={styles.itemText}>3D旋转X轴</Text>
          </Animated.View>
          {/* 3D基础:透视 + Y轴旋转 【卡片翻转核心】 */}
          <Animated.View style={[styles.transformItem, {transform: [{perspective: 200}, {rotateY: rotateYInterpolate}]}]}>
            <Text style={styles.itemText}>3D旋转Y轴</Text>
          </Animated.View>
          {/* 3D基础:透视 + Z轴旋转 (等同于2D旋转,Z轴是垂直屏幕方向) */}
          <View style={[styles.transformItem, {transform: [{perspective: 200}, {rotateZ: '45deg'}]}]}>
            <Text style={styles.itemText}>3D旋转Z轴</Text>
          </View>
        </View>
      </View>

      <View style={styles.moduleBox}>
        <Text style={styles.moduleTitle}>✨ 四、实战3D组合变换</Text>
        <View style={styles.contentWrap}>
          {/* 实战1:3D立体翻转 【详情页/卡片翻转核心】perspective+rotateY+scale */}
          <View style={[styles.transformItem, styles.cardItem, {transform: [{perspective: 300}, {rotateY: '60deg'}, {scale: 1.05}]}]}>
            <Text style={styles.itemText}>3D卡片翻转</Text>
          </View>
          {/* 实战1:终极组合 2D+3D混合变换 【最常用】平移+缩放+3D旋转+透视 */}
          <View style={[styles.transformItem, styles.cardItem, {transform: [{perspective: 250}, {translateX: 10}, {scale: 1.1}, {rotateY: '30deg'}]}]}>
            <Text style={styles.itemText}>2D+3D混合</Text>
          </View>
        </View>
      </View>
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  pageContainer: {
    flex: 1,
    backgroundColor: '#F5F7FA',
    padding: 15,
    paddingTop: 20,
  },
  moduleBox: {
    width: '100%',
    marginBottom: 30,
    backgroundColor: '#FFFFFF',
    borderRadius: 10,
    padding: 15,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.08,
    shadowRadius: 6,
    elevation: 3,
  },
  moduleTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#1D2129',
    marginBottom: 15,
    lineHeight: 24,
  },
  tipsText: {
    fontSize: 12,
    color: '#86909C',
    marginBottom: 15,
    paddingLeft: 5,
  },
  contentWrap: {
    width: '100%',
    flexDirection: 'row',
    flexWrap: 'wrap',
    gap: 12,
    justifyContent: 'flex-start',
    alignItems: 'center',
  },
  transformItem: {
    width: (baseW - 36) / 4,
    height: (baseW - 36) / 4,
    backgroundColor: '#007DFF',
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
  },
  cardItem: {
    backgroundColor: '#00C160',
    shadowColor: '#00C160',
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.2,
    shadowRadius: 8,
  },
  itemText: {
    color: '#FFFFFF',
    fontSize: 11,
    fontWeight: '500',
    textAlign: 'center',
    lineHeight: 16,
  },
});

export default RnTransform2D3DAllDemo;

三、源码逐模块深度解析

3.1 初始化与常量定义

源码开头通过 Dimensions.get('window') 获取鸿蒙设备的屏幕宽度,定义了 baseW 作为布局的基准宽度,这种写法是 RN 鸿蒙端自适应布局的最佳实践,可以保证在不同尺寸的鸿蒙设备上,变换的组件大小统一、布局美观,不会出现拉伸或挤压的问题。

3.2 动画变量声明:useRef + Animated.Value 组合

你的代码中使用了 useRef(new Animated.Value(xxx)).current 的方式声明所有动画变量,这是绝对正确的生产级写法,也是鸿蒙端开发的必用规范:

  • Animated.Value(1):基础动画值,用于单维度的动画控制(缩放、旋转、倾斜)
  • Animated.ValueXY({x:0,y:0}):二维动画值,专门用于平移(x/y 轴)控制
  • useRef 包裹的核心原因:防止组件重渲染时,动画变量被重新初始化,导致动画中断、闪烁,保证动画的连续性和稳定性

3.3 动画核心逻辑:useEffect 中编写动画规则(鸿蒙端无兼容问题)

你的代码在 useEffect 中完成了6 类核心动画的编写,覆盖了 RN 动画的所有高频用法,且全部在鸿蒙端完美运行,所有动画均采用 Animated.loop + Animated.sequence 组合实现无限循环动画,这也是开发中最常用的动画编排方式:

  1. 呼吸缩放动画:缩放值 1 → 1.2 → 1 循环,搭配贝塞尔曲线缓动,动效柔和自然
  2. 2D 无限旋转动画:0-360 度匀速旋转,使用 Easing.linear 保证无卡顿
  3. 3D X/Y 轴旋转动画:3D 立体无限旋转,是鸿蒙端卡片、商品展示的核心动效
  4. 左右往复平移动画:X 轴 0→60→-60→0 循环,实现平滑的左右移动
  5. 倾斜往复动画:0→30deg→0 循环,实现组件的左右倾斜形变

3.4 关键适配点:skewX 倾斜动画的鸿蒙端兼容处理

这是你代码中最核心的鸿蒙端适配技巧,也是开发中最容易踩坑的点:skewX/skewY 倾斜属性不支持 React Native 的原生驱动(useNativeDriver: true),如果强行开启会直接报错,导致整个页面崩溃。你的代码中精准的将倾斜动画的 useNativeDriver 设置为 false,其他所有动画均开启 true,这是最优的性能写法:开启原生驱动的动画由鸿蒙原生引擎执行,性能更高、更流畅;倾斜动画关闭原生驱动后,在鸿蒙端依然能完美运行,无任何卡顿。

表 2:React Native 鸿蒙端 Animated 动画 useNativeDriver 支持对照表(你的代码核心适配依据)

动画关联变换属性 useNativeDriver 支持 鸿蒙端性能表现 你的代码配置
scale 缩放 ✅ 支持 极高(原生引擎渲染) true
rotate/rotateX/rotateY 旋转 ✅ 支持 极高(原生引擎渲染) true
translateX/translateY 平移 ✅ 支持 极高(原生引擎渲染) true
skewX/skewY 倾斜 ❌ 不支持 良好(JS 线程渲染,无卡顿) false

3.5 插值器 interpolate:动画值的核心映射规则

你的代码中使用了 animateXX.interpolate() 方法,这是 RN 动画的核心能力,作用是将 Animated.Value 的 0-1 区间值,映射为我们需要的具体变换值(比如 0deg-360deg),语法简单且鸿蒙端无任何兼容问题,是实现角度、尺寸、位置映射的唯一方式。

3.6 渲染层:四大模块完整覆盖 2D/3D 变换所有场景

你的代码的 return 部分,将变换能力分为「基础 2D 静态变换」「进阶 2D 动画变换」「核心 3D 变换」「实战 3D 组合变换」四大模块,这是最清晰的学习和开发逻辑,每个模块的知识点层层递进,从基础到实战,完全贴合开发需求:

  • 基础 2D 变换:静态演示平移、缩放、旋转、倾斜的效果,是入门的核心
  • 进阶 2D 动画变换:动态演示所有 2D 变换的动画效果,包含高频的「组合变换」
  • 核心 3D 变换:讲解 3D 的核心规则(必须加 perspective),演示 X/Y/Z 轴的 3D 旋转
  • 实战 3D 组合变换:结合 2D+3D 变换,实现鸿蒙端最常用的「卡片 3D 翻转」「混合变换」,直接复用即可落地项目开发

3.7 内存泄漏防护:组件卸载停止动画

你的代码在 useEffect 的返回函数中,调用了所有动画的 .stop() 方法,这是鸿蒙端开发的必做优化,也是生产级代码的标配:当组件被卸载时,所有循环动画会被立即停止,避免动画在后台持续运行导致的内存泄漏、性能损耗,在鸿蒙的低功耗设备上,这种优化能大幅提升应用的流畅度和续航表现。

四、鸿蒙端开发补充注意事项

  1. 3D 变换的 perspective 属性,必须写在 transform 数组的第一个位置,否则 3D 效果在鸿蒙端不生效,你的代码中完全遵循了这个规则,是正确的写法。
  2. 组合变换的执行顺序:RN 的 transform 数组中,属性的顺序会影响最终效果,比如 [{translateX:20}, {rotate:'15deg'}][{rotate:'15deg'}, {translateX:20}] 的效果完全不同,你的代码中给出的组合变换顺序是实战最优解。
  3. 鸿蒙端的阴影属性 shadowXXXelevation 可以和变换动画完美共存,你的代码中给组件添加了阴影,让变换的动效更具层次感,这是鸿蒙端 UI 设计的加分项。

欢迎加入开源鸿蒙跨平台开发社区:https://openharmonycrossplatform.csdn.net

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐