ArkUI 动画曲线:同样是移动,手感差很多

举报
蓝瘦的蜕变 发表于 2026/10/31 22:08:49 2026/10/31
【摘要】 今天我们只改一个参数:curve。 动画距离一样,时长也一样,曲线不同,用户感受到的速度就不一样。这个 Demo 用三条轨道对比 Curve.Linear、Curve.EaseInOut 和 Curve.Friction,你点一次按钮就能看出差别。 这个 Demo 看什么 我们定义 CurvePreviewItem,每

ArkUI 动画曲线:同样是移动,手感差很多

今天我们只改一个参数:curve。

动画距离一样,时长也一样,曲线不同,用户感受到的速度就不一样。这个 Demo 用三条轨道对比 Curve.Linear、Curve.EaseInOut 和 Curve.Friction,你点一次按钮就能看出差别。

这个 Demo 看什么

我们定义 CurvePreviewItem,每条轨道保存一个曲线和一种颜色。点击按钮时只切换 moved,三个圆点的位移距离完全相同。

差别来自这里:

  • Linear:从头到尾一样快,适合机械感强的变化。
  • EaseInOut:起步和收尾都柔和,普通 UI 反馈很常用。
  • Friction:有一点阻尼感,适合需要“收住”的移动。

你自己写动效时,可以先用 EaseInOut,然后再根据页面气质微调。不要每个地方都随手用默认值。

完整代码

class CurvePreviewItem {
  name: string;
  curveValue: Curve;
  color: string;

  constructor(name: string, curveValue: Curve, color: string) {
    this.name = name;
    this.curveValue = curveValue;
    this.color = color;
  }
}

@Entry
@Component
struct ArkUIAnimationCurveDemo {
  @State moved: boolean = false;

  private curveItems: CurvePreviewItem[] = [
    new CurvePreviewItem('Linear', Curve.Linear, '#2563EB'),
    new CurvePreviewItem('EaseInOut', Curve.EaseInOut, '#0F766E'),
    new CurvePreviewItem('Friction', Curve.Friction, '#B45309')
  ];

  @Builder
  HeaderBlock() {
    Column({ space: 8 }) {
      Text('ArkUI 动画曲线')
        .fontSize(28)
        .fontWeight(700)
        .fontColor('#111827')
      Text('同样是移动,手感差很多')
        .fontSize(16)
        .fontColor('#4B5563')
      Text('同一块色条,距离和时长都一样,只换 curve。你会很快感觉到:曲线才是动画手感的关键。')
        .fontSize(14)
        .fontColor('#6B7280')
        .lineHeight(22)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  @Builder
  CurveRow(item: CurvePreviewItem) {
    Column({ space: 8 }) {
      Text(item.name)
        .fontSize(15)
        .fontWeight(700)
        .fontColor('#111827')

      Stack({ alignContent: Alignment.Start }) {
        Text('')
          .width('100%')
          .height(8)
          .borderRadius(4)
          .backgroundColor('#E5E7EB')
        Text('')
          .width(44)
          .height(44)
          .borderRadius(22)
          .backgroundColor(item.color)
          .translate({ x: this.moved ? 230 : 0, y: -18 })
          .animation({ duration: 760, curve: item.curveValue })
      }
      .width('100%')
      .height(52)
    }
    .width('100%')
    .padding(14)
    .borderRadius(16)
    .backgroundColor('#FFFFFF')
    .border({ width: 1, color: '#E5E7EB' })
    .alignItems(HorizontalAlign.Start)
  }

  build() {
    Scroll() {
      Column({ space: 20 }) {
        this.HeaderBlock()

        Column({ space: 12 }) {
          ForEach(this.curveItems, (item: CurvePreviewItem) => {
            this.CurveRow(item)
          }, (item: CurvePreviewItem) => item.name)
        }
        .width('100%')

        Button(this.moved ? '回到起点' : '开始移动')
          .height(42)
          .fontSize(14)
          .fontColor('#FFFFFF')
          .backgroundColor('#111827')
          .borderRadius(21)
          .padding({ left: 18, right: 18 })
          .onClick(() => {
            this.moved = !this.moved;
          })

        Text('如果你不确定选哪个,普通页面反馈先从 EaseInOut 开始。Linear 很机械,Friction 更像带一点阻尼的收尾。')
          .width('100%')
          .padding(16)
          .borderRadius(16)
          .backgroundColor('#F8FAFC')
          .fontSize(14)
          .fontColor('#4B5563')
          .lineHeight(22)
      }
      .width('100%')
      .padding(24)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FFFFFF')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。