主页面布局左右滑动切换,内部卡片可上滑切换运行效果:

 










Fly.ets 主界面+Swiper切换+背景颜色变化渐变

import { FlyEvent,FlyComponent } from './FlyComponent';
import { image } from '@kit.ImageKit';
import { resourceManager } from '@kit.LocalizationKit';
import { effectKit } from '@kit.ArkGraphics2D';

@Entry
@Component
export struct  Fly {


  @State swiperList: string[] = ['0','1','2','3'];
  @State cardList: Resource[] = [$r('app.media.1'),$r('app.media.2'),$r('app.media.3'),$r('app.media.2'),$r('app.media.4'),$r('app.media.2'),$r('app.media.3'),$r('app.media.4')];

  @State targetIndex: number = 0;
  @State bgColor:string = "";
  aboutToAppear(){
    this.setBackgroundColor()
  }

  async setBackgroundColor(){
    const context = getContext(this);
    const media : Resource = this.cardList[this.targetIndex];
    //获取resourceManager资源管理器
    const resourceMgr: resourceManager.ResourceManager = context.resourceManager;
    const fileData = await resourceMgr.getMediaContent(media);
    //获取图片的ArrayBufferc
    const buffer = fileData.buffer;
    //创建imageSource
    const imageSource: image.ImageSource = image.createImageSource(buffer);
    //创建pixelMap
    const pixelMap: image.PixelMap = await imageSource.createPixelMap();

    effectKit.createColorPicker(pixelMap, (err, colorPicker) => {
      //读取图像主色的颜色值,结果写入Color
      let color = colorPicker.getMainColorSync();
      this.bgColor = "#" + color.alpha.toString(16) + color.red.toString(16) + color.green.toString(16) + color.blue.toString(16);
      console.log('bgColor='+this.bgColor)
    })
  }

  build() {
    Column(){
      Column() {
        Swiper() {
          ForEach(this.swiperList, (index:number) => {
            Column(){
              FlyComponent({
                cardData: this.cardList,
                cardWidth:300,
                cardHeight:400,
                onThrowDone: () =>{
                  console.log('Fly=================完成')
                  const data: ResourceStr =  this.cardList.splice(0,1)[0];
                  this.cardList.push(data);
                },
                onDragFlyMove:(e:FlyEvent) =>{
                  console.log('Fly',JSON.stringify(e))
                }
              })
              Text(`Item ${index + 1}`)
                .width('100%')
                .height('100px')
                .backgroundColor(index % 2 === 0 ? 0xFF6347 : 0xCCCCCC)
            }
          })
        }
        .onChange((index:number)=>{
          this.targetIndex = index;
          this.setBackgroundColor();
        })
        .displayCount('auto') // 设置显示数量为自动
        .loop(true) // 设置循环滑动
        .padding('10px') // 设置内边距
        .margin('10px') // 设置外边距
        .zIndex(1) // 设置z-index为1,确保在重叠时显示在最上层
      }
    }
    .linearGradient({
      direction: GradientDirection.Bottom, // 渐变方向
      repeating: false, // 渐变颜色是否重复
      colors: [[this.bgColor, 0.0], [0xffffff, 0.5]] // 数组末尾元素占比小于1时满足重复着色效果
    })
  }
}

FlyComponent.ets 飞卡组件


export interface FlyEvent{
  left: number;
  top: number;
  distance: number;
}

//飞卡组件
@Entry
@Component
export struct FlyComponent {
  @Prop cardData:  Resource[] = [];
  // 正常卡片宽度
  @State cardWidth: number = 260;
  // 正常卡片高度
  @State cardHeight: number = 300;
  // 卡片层叠的横向边距
  @State leftPad: number = 10;
  // 卡片层叠的纵向边距
  @State topPad: number = 6;
  // 卡片背景色
  @State cardBgColor: string = "#fff";
  // 卡片拖拽方向
  @State dragDirection: String = "all";
  // 卡片的圆角弧度
  @State flyborderRadius: number = 10;
  // 卡片触发飞卡效果的距离
  @State throwTriggerDistance: number = 100;
  // 飞卡的移动距离
  @State throwDistance: number = 1000;
  // 是否开启卡片描边效果
  @State hasBorder: boolean = false;
  // 是否开启阴影效果
  @State hasShadow: boolean = true;
  // 是否可用
  @State disabled: boolean = false;

  @State left: number = 0;
  @State top: number = 0;
  @State startLeft: number = 0;
  @State startTop: number = 0;
  @State isDrag: boolean = false;
  @State isThrow: boolean = false;
  @State needBack: boolean = false;
  @State isAnimating: boolean = false;
  @State left2: number = 0;
  @State top2: number = 0;
  @State width2: number = 0;
  @State height2: number = 0;
  @State left3: number = 0;
  @State top3: number = 0;
  @State width3: number = 0;
  @State height3: number = 0;
  @State left4: number = 0;
  @State top4: number = 0;
  @State width4: number = 0;
  @State height4: number = 0;
  @State opacity4: number = 0;
  @State paddingLeft: number = 0;
  @State paddingTop: number = 0;

  public onThrowDone:Function | null = null;

  public onDragFlyStart:Function | null = null;

  public onDragFlyMove:Function | null = null;

  public onDragStop:Function | null = null;

  public onThrowFail:Function | null = null;

  public onThrowStart:Function | null = null;

  aboutToAppear(): void {
    this.resetAllCard();
  }

  getDistance(x1: number, y1: number, x2: number, y2: number): number {
    const _x: number = Math.abs(x1 - x2);
    const _y: number = Math.abs(y1 - y2);
    return Math.sqrt(_x * _x + _y * _y);
  }

  touchStart(e: TouchEvent) {
    if (this.isAnimating) {
      return;
    }
    this.isDrag = true;
    this.needBack = false;
    this.isThrow = false;
    const curTouch: TouchObject = e.touches[0];
    this.startLeft = curTouch.x - this.left;
    this.startTop = curTouch.y - this.top;

    if(this.onDragFlyStart){
      this.onDragFlyStart();
    }
  }

  touchMove(e: TouchEvent) {
    if (this.disabled) {
      return;
    }
    if (this.isAnimating) {
      return;
    }

    const curTouch: TouchObject = e.touches[0];
    if (this.dragDirection == "all" || this.dragDirection == "horizontal") {
      this.left =
        curTouch.x - this.startLeft;
    }
    if (this.dragDirection == "all" || this.dragDirection == "vertical") {
      this.top = curTouch.y - this.startTop;
    }
    const distance: number = this.getDistance(0, 0, this.left, this.top);

    if(this.onDragFlyMove){
      this.onDragFlyMove({ left: this.left, top: this.top, distance: distance });
    }

  }

  touchCancel(e: TouchEvent) {
    let distance: number = this.getDistance(0, 0, this.left, this.top);

    this.isDrag = false;
    if(this.onDragStop){
      this.onDragStop({ left: this.left, top: this.top, distance: distance });
    }

    if (this.isAnimating) {
      return;
    }

    const that = this;
    const curTouch = e.touches[0];
    distance = this.getDistance(0, 0, this.left, this.top);
    if (distance > this.throwTriggerDistance) {
      this.makeCardThrow();
    } else {
      this.makeCardBack();
    }
  }

  resetAllCardDown() {
    this.left = 0;
    this.top = 0;

    this.width2 = (this.cardWidth - this.leftPad * 2);
    this.height2 = (this.cardHeight - this.topPad * 2);
    this.left2 = this.leftPad;
    this.top2 = (this.topPad * 3);

    this.width3 = (this.cardWidth - this.leftPad * 4);
    this.height3 = (this.cardHeight - this.topPad * 4);
    this.left3 = this.leftPad * 2;
    this.top3 = (this.topPad * 6);

    this.width4 = (this.cardWidth - this.leftPad * 6);
    this.height4 = (this.cardHeight - this.topPad * 6);
    this.left4 = this.leftPad * 3;
    this.top4 = (this.topPad * 9);
    this.opacity4 = 0;

  }

  resetAllCard() {
    this.resetAllCardDown();
  }

  makeCardThrow() {
    const that = this;

    this.isThrow = true;
    this.needBack = false;

    const angle = Math.atan2((this.top - 0), (this.left - 0));
    this.left = Math.cos(angle) * this.throwDistance;
    this.top = Math.sin(angle) * this.throwDistance;

    this.width2 = this.cardWidth;
    this.height2 = this.cardHeight;
    this.left2 = 0;
    this.top2 = 0;

    this.width3 = (this.cardWidth - this.leftPad * 2);
    this.height3 = (this.cardHeight - this.topPad * 2);
    this.left3 = this.leftPad;
    this.top3 = (this.topPad * 3);

    this.width4 = (this.cardWidth - this.leftPad * 4);
    this.height4 = (this.cardHeight - this.topPad * 4);
    this.left4 = this.leftPad * 2;
    this.top4 = (this.topPad * 6);
    this.opacity4 = 1;

    this.isAnimating = true;

    if(this.onThrowStart){
      this.onThrowStart();
    }

    setTimeout( () => {
      that.isThrow = false;
      that.isAnimating = false;
      if(that.onThrowDone){
        that.onThrowDone();
      }
      that.resetAllCard();
    }, 400);
  }

  makeCardBack() {
    const that = this;

    this.isThrow = false;
    this.needBack = true;

    if (this.needBack) {
      this.left = 0;
      this.top = 0;
    }

    this.isAnimating = true;
    setTimeout( () => {
      if( that.onThrowFail){
        that.onThrowFail();
      }

      that.isAnimating = false;
      that.needBack = true;
    }, 600);
  }

  @Styles
  setImageShadow():void{
    .backgroundColor(this.cardBgColor)
    .borderRadius(this.flyborderRadius)
    .borderWidth(1)
    .borderColor("#ccc")
    .shadow({ radius: 0, color: "#000", offsetX: 0, offsetY: 0 })
  }


  build() {
    Column() {
      Stack() {
        Column() {
          Image(this.cardData.length > 4 ? this.cardData[3]:$r('app.media.4'))
            .borderRadius(this.flyborderRadius)
        }
        .width(this.width4)
        .height(this.height4)
        .position({x:this.left4,y:this.top4})
        .setImageShadow()

        Column() {
          Image(this.cardData.length > 3 ? this.cardData[2]:$r('app.media.3'))
            .borderRadius(this.flyborderRadius)
        }
        .width(this.width3)
        .height(this.height3)
        .position({x:this.left3,y:this.top3})
        .setImageShadow()

        Column() {
          Image(this.cardData.length > 2 ? this.cardData[1]:$r('app.media.2'))
            .borderRadius(this.flyborderRadius)
        }
        .width(this.width2)
        .height(this.height2)
        .position({x:this.left2,y:this.top2})
        .setImageShadow()

        Column() {
          Image(this.cardData.length > 1 ? this.cardData[0]:$r('app.media.1'))
            .borderRadius(this.flyborderRadius)
        }
        .width(this.cardWidth)
        .height(this.cardHeight)
        .position({x:this.left,y:this.top})
        .onTouch((event?: TouchEvent) => {
          if (event) {
            if (event.type === TouchType.Down) {
                this.touchStart(event);
            }
            if (event.type === TouchType.Up) {
                this.touchCancel(event);
            }
            if (event.type === TouchType.Move) {
              this.touchMove(event);
            }
          }
        })
        .setImageShadow()
      }
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .width('100%')
    .height('100%')
    .align(Alignment.Center)
  }
}

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐