纯血鸿蒙Next 渐变与动画拾遗

471 阅读4分钟

下面是对渐变与动画的一个经验记录。

一.如何实现一个类似心跳的动画效果。

这其实有两个注意点,类似心跳的效果,需要动画变换到一定尺寸后,又从当前尺寸变换回之前的尺寸,如此循环往复。

  private imageAnimator: AnimatorResult | undefined = undefined
  
  @State strokeWidth: number = 3
  
  /// 在fill属性和direction属性的同时配合下,就可以实现
  createImageAnimation() {
    this.imageAnimator = Animator.create({
      duration: 700,
      easing: "linear",
      delay: 0,
      fill: "forwards",/// 在动画结束后,目标将保留动画结束时的状态,在最后一个关键帧中定义(也就是每次动画结束后,保留当时的状态和尺寸)
      direction: "alternate",/// 动画交替循环播放,奇数次正向播放,偶数次反向播放。
      iterations: -1,/// 无限次循环播放.
      begin: 7,///从7开始播放
      end: 15, ///播到15结束
    })
    this.imageAnimator!.onFrame = (value: number) => {
      this.strokeWidth = value
    }
  }
  

运行效果就是一个圆环的曲线宽度在不断的向外扩大或者缩小.

二.如何实现一个从上到下渐变的圆环

我为什么说是一个从上到下渐变的圆环呢?我了解到现在鸿蒙的情况是,要实现一个渐变的圆环效果,在鸿蒙中是需要取巧去实现的,有一个叫做"DataPanel"的组件可以取巧实现,要不最快的你找UI要一张圆环图片。

好的,话说回来,实现一个从上到下或者说从下到上,或者说从左到右,或者说从右到左的圆环渐变.

   private settings: RenderingContextSettings = new RenderingContextSettings(true)
   /// 我们使用Canvas来绘制圆环.
   private circleContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
   /// 设置圆环画笔的宽度.
   private circleContextLineWidth:number = 7

   build() {
     Stack(){
       /// 使用Canvas绘制
       Canvas(this.circleContext)
         .width(110)
         .height(110)
         .onReady(() => {
         /**
         * 1.在此生命周期中,宽高已经确定,可以使用this.circleContext.width和
         this.circleContext.width / 2等值.
           2.这里使用线性渐变createLinearGradient,在整个Canvas中,它是一个矩形。
           所以不管你怎么做,它只可能从四个方向上进行渐变,不可能从圆的0角度开始到第360度进行渐变,可以使用另外一种角度渐变的方式。
           3.createLinearGradient线性渐变的四个参数就是:前两个参数是开始渐变的位置坐标,后两个参数是结束渐变的位置坐标。
           4.这里是从正中间的上方渐变到正中间的下方。
         */
         let gradient =
           this.circleContext.createLinearGradient(this.circleContext.width / 2, 0, this.circleContext.width / 2,
             this.circleContext.height)
         gradient.addColorStop(0, 'rgba(54, 119, 242, 0.4)')
         gradient.addColorStop(0.4, 'rgba(54, 119, 242, 0.5)')
         gradient.addColorStop(0.5, 'rgba(54, 119, 242, 0.6)')
         gradient.addColorStop(0.6, 'rgba(54, 119, 242, 0.7)')
         gradient.addColorStop(0.7, 'rgba(54, 119, 242, 0.8)')
         gradient.addColorStop(0.8, 'rgba(54, 119, 242, 0.9)')
         gradient.addColorStop(0.9, 'rgba(54, 119, 242, 0.95)')
         gradient.addColorStop(1, 'rgba(54, 119, 242, 1)')
         this.circleContext.strokeStyle = gradient
         /// 线条宽度
         this.circleContext.lineWidth = this.circleContextLineWidth
         /// 使用arc函数进行绘制圆形路径,需要注意的是对于圆形半径的计算!
         /// 需要减去的是线条宽度的一半,如果不相减this.circleContext.width / 2是整个Canvas绘图组件的一半,以它为半径会超出。
         /// 在有线条宽度的情况下,计算机认为的半径是:从线条宽度的中心点到圆心的距离,即为半径。
         this.circleContext.arc(this.circleContext.width / 2, this.circleContext.height / 2,
           this.circleContext.width / 2 - this.circleContextLineWidth / 2, 0, Math.PI*2 )
         this.circleContext.stroke()
       })
       Column(){
         Text('58')
           .fontColor(Color.Black)
           .fontSize(30)
           .fontWeight(FontWeight.Bold)
         Text('次/秒')
           .fontColor(Color.Black)
           .fontSize(20)
           .fontWeight(FontWeight.Regular)
       }
       .justifyContent(FlexAlign.Start)
     }
     .align(Alignment.Center)
     .width(118)
     .height(118)
     .borderRadius(118/2)
     .backgroundColor(Color.White)
     .shadow({ radius: 10, color: 'rgba(154, 154, 154, 0.55)' })
   }

运行的效果图如下:

WechatIMG273.jpg

三.实现圆环从角度上的渐变

1.找UI要一张圆环图片,快捷、高效、无Bug.

2.使用数据组件“DataPanel”,在其中只设置一个数据值,并且该数据占满它的整个max,然后设置它的 valueColors属性为LinearGradient类型的颜色数组,即可实现单一的渐变圆环,但是当它出现的时候,它会有一个动画在那里.

   /// 需要渐变的颜色数组.
   public gradientColors: LinearGradient = new LinearGradient(
     [
       { color: "rgba(45, 152, 248, 0)", offset: 0 },
       { color: "rgba(45, 152, 248, 1)", offset: 0.5 },
       { color: "rgba(82, 65, 230, 1)", offset: 1 },
     ],
   )
   @State colorArray: Array<LinearGradient | ResourceColor> = [this.gradientColors]

   build() {
     DataPanel(
       {
         values: [99.99,], /// 当前数据为99.99几乎占满.
         max: 100, /// 数据最大值为100
         type: DataPanelType.Circle, /// 设置为圆环
       })
       .width(110)
       .height(110)
       .valueColors(this.colorArray) /// 设置各数据段颜色.
       .trackShadow(null) /// 投影样式:设置null为不开启投影.
       .strokeWidth(10) /// 设置圆环粗细
       .trackBackgroundColor('#08182431') /// 底板颜色
     // 设置组件的旋转.
     // .rotate({
     //   x: 0,
     //   y: 0,
     //   z: 1,
     //   centerX: '50%',
     //   centerY: '50%',
     //   angle: 90
     // })
   }
   

3.使用角度渐变

    Stack(){
      Row()
          .width(110)
          .height(110)
          .borderRadius(55)
          .sweepGradient({
            center:[55,55],/// 角度渐变的中点.
            start:0,/// 开始角度.
            end:360,/// 结束角度,注意这里不要使用数学函数Math.PI,因为这里角度口径不太一样。Math.PI的值才圆周律大小。
            colors:[
              [Color.Red,0],
              [Color.Yellow,0.25],
              [Color.Blue,0.5],
              [Color.Green,0.75],
              [Color.Orange,1]
            ]
          })
        /// 白色占位覆盖,
        Row()
          .width(90)
          .height(90)
          .borderRadius(45)
          .backgroundColor(Color.White)
    }

效果如下

WechatIMG275.jpg