鸿蒙的动态渐变背景实现 原创 精华

iMerryou
发布于 2025-7-14 17:59
浏览
2收藏

前言

最近想搞个酷炫一点的页面,觉得渐变挺不错,决定背景采用渐变了。
但是单纯的静态的渐变还是感觉差点意思,思来想去觉得得搞个动态渐变。下面是我的实现思路
关于基础的静态渐变,这里不愿意赘述,贴一张官方的链接在这吧,链接是 ​​官方文档-渐变样式​​。简单而且详细。
说明:以下均以线性渐变举例,变量命名因为是演示所以比较随意。
最开始我的方案是用那个​​属性动画​​,如果说你想实现的效果比较简单。比方说如下,那么是很合适的。
鸿蒙的动态渐变背景实现-鸿蒙开发者社区

但如果你要实现的比较复杂,例如下面这样
鸿蒙的动态渐变背景实现-鸿蒙开发者社区
虽然用属性动画仍旧可以大致还原,但是我觉得​​关键帧动画这时候可能就更有优势了。
这里也不赘述了,点一下链接可以看到文档。

属性动画实现

先定义两个控制颜色的变量

@State gradientOptions : LinearGradientOptions = {
    angle:45,
    colors:[
      ["#f09819", 0],
      ["#edde5d", 1],
    ]
  }
  @State flag: number = 1

然后我们在onDidBuild回调里启动动画,具体就是改一下我们定义的gradientOptions的值,就能触发动画了

onDidBuild():{
     this.gradientOptions =  {
      angle:45,
      colors:[
        ["#ffee113e", 0],
        ["#ff1a3864", 1]
 
      ]
    }
}

下面是组件信息,我们可以通过变量flag来实现更多更丰富的渐变效果,这里不作演示

Column()
          .width(200)
          .height(200)
          .linearGradient(this.gradientOptions)
          .animation({duration:2000,onFinish:()=>{
            if(this.flag){
              this.flag = 0
              this.gradientOptions =
            {
                angle:45,
                colors:[
                  ["#edde5d", 0],
                  ["#f09819", 1],
 
                ]
              }
            }else {
              this.flag = 1
              this.gradientOptions = {
                angle:45,
                colors:[
                  ["#ffee113e", 0],
                  ["#ff1a3864", 1],
                ]
              }
            }
 
          }})

这样基本就可以完成我们第一个渐变的效果了。
但是很重要的一个缺点就是,换方向的话是不会有动画的
我们前面主要是两种颜色变化,并且角度都是45度,如果我们把第二个颜色的角度改成90度,也就是

this.flag = 1
              this.gradientOptions = {
                angle:90,
                colors:[
                  ["#ffee113e", 0],
                  ["#ff1a3864", 1],
                ]
              }

那么就会很不连贯了, 像下面这样,感觉就是属性动画处理不了这样的转变,也不清楚算不算bug。
鸿蒙的动态渐变背景实现-鸿蒙开发者社区
总之就是,用属性动画的话,就几乎改变不了渐变的方向了,不能提供更为多元的视觉效果。
当然,硬要用属性动画,通过很复杂的调试应该也能做到看起来连贯吧。

关键帧动画实现

实际上这个似乎才是主流的动态渐变背景的实现方案。
大致就是一个框(组件)固定,但是背景图来回移动,从而达到渐变的效果。
例如我前面那个举例的很复杂的例子,实际上是怎样运行的呢?
鸿蒙的动态渐变背景实现-鸿蒙开发者社区
这里是为了演示所以把周围的显露出来了,并且加了个border,之后加上clip属性并把border删了就可以达到之前的效果了。
具体的代码实现如下
我们定义位置变量pos

@State pos : Position = {x: "0%",y:"0%"}

组件信息

Column(){
        Column()
          .position(this.pos)
          .width("500%")
          .height("500%")
          .linearGradient({
            angle:60,
            colors:[
              ["#ffed5d8b", 0],
              ["#ffb7f019", 0.2],
              ["#ffae8215", 0.4],
              ["#ff354bb8", 0.6],
              ["#ffd3ed5d", 0.8],
              ["#ff590f86", 1],
            ]
          })
      }
      .width(200)
      .height(200)
      .clip(true)

然后最重要的是我们的关键帧动画函数ani

ani(){
    this.uiContext?.keyframeAnimateTo({iterations:-1},
      [
        {duration:1,event:()=>{
          this.pos.x = "0%"
          this.pos.y = "-400%"
 
        }
        },
        {duration:3000,event:()=>{
          this.pos.x = "0%"
          this.pos.y = "0%"
 
    }
    },
        {
      duration:3000,event:()=>{
          this.pos.x = "-400%"
          this.pos.y = "0%"
        },
      }, {
        duration:3000,event:()=>{
          this.pos.x = "-400%"
          this.pos.y = "-400%"
        },
      },
        {
          duration:3000,event:()=>{
          this.pos.x = "0%"
          this.pos.y = "-400%"
        },
        }, {
        duration:4242,event:()=>{
          this.pos.x = "-400%"
          this.pos.y = "0%"
        }
      }, {
        duration:3000,event:()=>{
          this.pos.x = "0%"
          this.pos.y = "0%"
        }
      }, {
        duration:4242,event:()=>{
          this.pos.x = "-400%"
          this.pos.y = "-400%"
        },
      }, {
        duration:3000,event:()=>{
          this.pos.x = "0%"
          this.pos.y = "-400%"
        },
      },
 
      ])
  }

这里解释一下这个函数啊,这个iteration: -1 指的是无限次播放重复播放这个动画。
然后这里的一次循环的具体的路径参考下图。
鸿蒙的动态渐变背景实现-鸿蒙开发者社区
关于duration和pos的具体设置,不展开讲了,否则偏离主题了。这部分也完全是个性化的,这里仅供参考。
最后在onDidBuild回调里执行我们的关键帧动画函数就好了。

onDidBuild():{
     this.ani()
}

后话

最初的目的是想要完全随机的背景动态变化,但是实际上用关键帧之后,看不出来是不是固定的背景的吧,而且一般估计没人盯着你的背景看是不是重复播放。效果上估计也都是差不多的,完全随机还不可控,说不定会随机出一个很难看的渐变色。虽然可以限定颜色范围。

实现的话也不是没有思路,大概就是在关键帧动画里最后的一步里加个animateTo函数,然后把组件的linearGradient属性的值改成变量,在animateTo函数里修改,应该就行了。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
4
收藏 2
回复
举报
回复
    相关推荐