HarmonyOS鸿蒙Next中关于perspective

HarmonyOS鸿蒙Next中关于perspective arkts 没有类似 css属性 perspective 这种 给某个容器设置统一的视距的属性吗

9 回复

ArkUI(ArkTS)目前没有完全对应 CSS perspective 属性的容器级透视投影能力

你在 Web 里习惯这样写:

.container {
    perspective: 1000px;
}

.card {
    transform: rotateY(45deg);
}

这里的特点是:

父容器设置 perspective
↓
所有子元素共享同一个观察点
↓
形成统一3D空间

而在 ArkUI 里面,目前提供的是:

.rotate({
  x: 1,
  y: 0,
  z: 0,
  angle: 30
})

.scale()

.translate()

.transform()

以及:

.matrix4()

相关能力。

但没有:

.perspective(1000)

或者:

Container {
   ...
}
.perspective(...)

这种容器级 API。


ArkUI 当前的实现方式

一般是通过:

import matrix4 from '@ohos.matrix4'

自己构造投影矩阵。

例如:

let mat = matrix4.identity()

mat.perspective(
  45,
  1.0,
  0.1,
  1000
)

然后:

.transform({
  matrix: mat
})

或者:

.matrix4(mat)

实现透视效果。


与 CSS perspective 的区别

CSS:

Container
  perspective
      ↓
所有子元素共享

ArkUI:

Component A
  自己一套 Matrix4

Component B
  自己一套 Matrix4

每个组件独立。

所以如果你做:

3D轮播
CoverFlow
卡片翻转
3D菜单

会发现:

每个元素都要自己计算透视矩阵

而不能像 Web 一样:

.parent {
    perspective: 1000px;
}

一劳永逸。


如果你想实现统一视距

目前比较常见的做法是封装:

class PerspectiveManager {
    static create(angle: number): Matrix4 {
        ...
    }
}

所有子组件:

.transform({
    matrix: PerspectiveManager.create(...)
})

统一使用同一个:

fov
near
far
cameraZ

参数。

这样视觉上看起来就像:

perspective: 1000px

一样。


如果是做卡片翻转

例如:

transform: rotateY(60deg);
perspective: 1000px;

对应 ArkUI 一般写法:

Column()
  .rotate({
      x: 0,
      y: 1,
      z: 0,
      angle: 60
  })

再配合:

.matrix4(...)

增加透视分量。

否则会变成:

正交旋转

看起来很假。


HarmonyOS 6.1 当前结论

截至 API 23:

❌ 没有类似 CSS 的 perspective 属性

❌ 没有父容器统一透视空间

✅ 支持 Matrix4 投影矩阵

✅ 支持 rotate/translate/scale

✅ 可以手动构建透视矩阵实现相同效果

所以你如果是从前端转过来的,想找:

perspective: 1000px;
transform-style: preserve-3d;

对应物,目前 ArkUI 还没有直接等价的高级封装,只能通过 Matrix4 自己实现透视投影。

更多关于HarmonyOS鸿蒙Next中关于perspective的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


开发者您好,支持给外层容器组件添加统一视距,可以参考我的实战文章:

鸿蒙应用开发实战:透视变换perspective让2D组件拥有3D立体感

你好,可以看看 [@ohos.matrix4 (矩阵变换)](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-matrix4#matrix4copydeprecated) ,用于对组件进行图形变换的各种操作,为组件提供矩阵变换能力,支持对图形进行平移、旋转和缩放等。使用场景包括:

图形变换中的transform接口通过使用图形变换矩阵Matrix4对象显示二维变换时的矩阵变换,transform3D接口通过使用图形变换矩阵Matrix4对象设置组件的三维变换矩阵

// xxx.ets
import { matrix4 } from '@kit.ArkUI';

@Entry
@Component
struct Test {
  private matrix1 = matrix4.identity().skew(2, 3);

  build() {
    Column() {
      // $r("app.media.bg1")需要替换为开发者所需的图像资源文件。
      Image($r("app.media.bg1")).transform(this.matrix1)
        .height(100)
        .margin({
          top: 300
        })
    }
    .width("100%")
    .height("100%")
  }
}

运行效果:

cke_2962.png

没有的,ArkUI 没有容器通用.perspective(val)样式属性,不存在父容器统一设置、子元素全部共用透视的原生写法

我第一次知道 css 还有这个属性, 查了一下 确实很好玩, 但是遗憾的告诉你 Ho 中没有这个属性, 3d 模型 你得自己创建归一化数据 来实现相关效果, 目前没有统一的封装方法

有的,ArkUI 完全支持类似 CSS perspective 的效果,只不过它的入口在 transform 属性里,而不是一个独立属性。

你可以直接在任意容器组件(比如 ColumnRowStack)上使用:

.transform({ perspective: 50 })

这样,这个容器内所有子组件的 3D 变换(如 rotate 都会共享这个统一的透视距离,效果和 CSS 给父元素设置 perspective: 50px 几乎一致。

cke_687.png


完整示例:给容器统一设置视距

@Entry
@Component
struct PerspectiveDemo {
  build() {
    Column({ space: 40 }) {
      // 容器统一设置透视距离
      Row({ space: 20 }) {
        // 子元素做 3D 旋转时,会共享父容器的透视
        Text('A')
          .width(80)
          .height(80)
          .backgroundColor(Color.Orange)
          .fontSize(24)
          .textAlign(TextAlign.Center)
          .rotate({
            x: 0,
            y: 1,   // 绕 Y 轴旋转
            angle: 45
          })

        Text('B')
          .width(80)
          .height(80)
          .backgroundColor(Color.Blue)
          .fontSize(24)
          .textAlign(TextAlign.Center)
          .rotate({
            x: 1,
            y: 0,   // 绕 X 轴旋转
            angle: -30
          })
      }
      .width('100%')
      .justifyContent(FlexAlign.Center)
      .transform({ perspective: 100 })   // 统一透视距离
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

你会发现两个块在旋转时带有明显的近大远小透视感,而且透视线是统一的,不会各转各的。


为什么写在 transform 里就管用?

  • ArkUI 的 transform 属性可以同时接受 perspectiverotatescaletranslate 等。
  • 如果 perspective 写在 父容器 上,它会把透视效果“传递”给子元素的所有 3D 变换,相当于建立了一个 3D 场景。
  • 如果写在 子元素自己的 rotate 里(如 rotate({..., perspective: 100})),那只是这个元素自己独立使用那个透视值,多个元素之间透视会不统一,看起来就怪怪的。

还想控制透视原点?

CSS 里还有个 perspective-origin 控制“消失点”的位置。在 ArkUI 中,可以用 transformOrigin 属性来达到类似目的:

.transform({ perspective: 200 })
.transformOrigin({ x: '50%', y: '50%' })  // 透视中心在组件正中央

transformOrigin 可以理解为“变形基准点”,对于 3D 透视来说,它实际上就决定了观察点的聚焦位置。


最后提醒

  • perspective 值越小,透视感越强(像广角镜头);值越大,透视感越弱。
  • 尽量不要在子组件的 rotate 里再单独加 perspective,否则会覆盖掉容器的统一设置,导致透视混乱。

ArkUI 里没有完全等同 CSS 那种“父容器 perspective 后所有子元素自动继承同一视距”的用法。常见做法是把 3D 变换写在具体需要旋转/翻转的组件上,在 rotate/transform 参数里统一配置 perspective,或者封装一个 Builder/自定义组件,把 perspective 数值作为公共参数传给子项。

如果你要做卡片翻转、轮播 3D 效果,建议把每个子项的 rotateY/rotateX、中心点和 perspective 放在同一个状态计算里,这样视觉上仍然能保持统一视距。更复杂的 3D 矩阵效果可以考虑 transform/matrix4,但可维护性会比直接 rotate 差一些。

HarmonyOS鸿蒙Next中,perspective属性用于定义3D透视变换的视距,单位为px。在组件的transform样式内设置,例如transform: perspective(1000px),值越小透视效果越强烈。该属性配合rotateX/Y/Z可实现立体翻转效果。

HarmonyOS ArkUI 提供了 perspective 属性,可以直接为容器设置统一的透视视距,效果类似 CSS 的 perspective。例如:

Column()
  .perspective(800) // 设置统一视距
  .width('100%')
  .height('100%')

这样容器内的子组件执行 3D 变换时(如 rotateXrotateY)就会共享这个透视距离,无需单独在每个子组件上重复定义。

回到顶部