ZhCarouselLayout01.ets 7.72 KB
import { CompDTO, ContentDTO, } from 'wdBean';
import { BreakpointConstants, CommonConstants, DurationEnum } from 'wdConstant';
import { BreakPointType, Logger } from 'wdKit';
import { CompUtils } from '../../utils/CompUtils';
import { ProcessUtils } from '../../utils/ProcessUtils';
import { EmptyComponent } from '../view/EmptyComponent';

const TAG = 'Zh_Carousel_Layout-01';

/**
 * 轮播组件,即Banner/轮播大图/焦点图/自动滑动
 * 样式:
 * 'Zh_Carousel_Layout-01', // 通用轮播卡:视频、直播、活动、专题、榜单、外链
 */


class MyDataSource implements IDataSource {
  private list: number[] = []

  constructor(list: number[]) {
    this.list = list
  }

  totalCount(): number {
    return this.list.length
  }

  getData(index: number): number {
    return this.list[index]
  }

  registerDataChangeListener(listener: DataChangeListener): void {
  }

  unregisterDataChangeListener() {
  }
}

@Component
export struct ZhCarouselLayout01 {
  @StorageLink('currentBreakpoint') @Watch('watchCurrentBreakpoint') currentBreakpoint: string = BreakpointConstants.BREAKPOINT_XS;
  @State compDTO: CompDTO = {} as CompDTO
  private data: MyDataSource = new MyDataSource([])
  @State firstWd: number = 0
  @State SecondWd: number = 0
  @State swiperIndex: number = 0

  watchCurrentBreakpoint() {
    Logger.info(TAG, `watchCurrentBreakpoint, this.currentBreakpoint: ${this.currentBreakpoint}`);
  }

  aboutToAppear() {
    Logger.info(TAG, `aboutToAppear, beanList:${this.compDTO?.operDataList?.length}, currentBreakpoint:${this.currentBreakpoint}`);
    let list: number[] = []
    for (let i = 1; i <= this.compDTO?.operDataList?.length; i++) {
      list.push(i);
    }
    this.data = new MyDataSource(list)
  }

  isAutoPlay() {
    if (this.compDTO.extraData) {
      return JSON.parse(this.compDTO.extraData).autoplay == 1
    } else {
      return false
    }
  }

  build() {
    if (this.compDTO?.operDataList?.length) {
      Stack() {
        Swiper() {
          ForEach(this.compDTO?.operDataList, (item: ContentDTO, index: number) => {
            CarouselLayout01CardView({
              item: item,
              index: index
            })
          })
        }
        .borderRadius($r('app.float.image_border_radius'))
        .displayCount(this.buildDisplayCount()) // 仅展示1个图片
        .cachedCount(2)
        .index(0) // The default index of Swiper.
        .indicator(false)
        .loop(true)
        .vertical(false)
        .curve(Curve.Linear)
        .autoPlay(this.isAutoPlay())
        .onAnimationStart((index: number, targetIndex: number) => {
          Logger.info(TAG, `Swiper onAnimationStart index : ${index}, targetIndex: ${targetIndex}`);
          this.swiperIndex = targetIndex
        })
        .onChange((index: number) => {
          Logger.info(TAG, `Swiper onChange index : ${index}`);

        })
        .onAnimationEnd((index: number, extraInfo: SwiperAnimationEvent) => {
          this.firstWd = 12
          setTimeout(() => {
            this.SecondWd = 12
          }, 2000)
          console.info("onAnimationEnd, index: " + index)
        })

        // 自定义indicator
        GridRow({
          columns: this.data.totalCount(),
          gutter: { x: 2 }
        }) {
          LazyForEach(this.data, (item: string, index: number) => {
            GridCol() {
              if (index === this.swiperIndex) {
                indicatorAnimations({
                  index: index,
                  isAutoPlay: this.isAutoPlay()
                })
              } else {
                Row() {
                  Image($r('app.media.swiper_indicator_gray'))
                    .width('100%')
                    .height(2)
                }
              }
            }
          }, (item: string) => item)
        }
        .width(CommonConstants.FULL_PARENT)
        .padding({
          left: 10,
          right: 10,
          top: 12,
          bottom: 12
        })
        .alignItems(ItemAlign.End)
      }
      .alignContent(Alignment.BottomEnd)
      .width(CommonConstants.FULL_WIDTH)
      .padding({
        left: $r('app.float.card_comp_pagePadding_lf'),
        right: $r('app.float.card_comp_pagePadding_lf'),
        top: $r('app.float.card_comp_pagePadding_tb'),
        bottom: $r('app.float.card_comp_pagePadding_tb')
      })

      // .backgroundColor($r('app.color.white'))
    } else {
      EmptyComponent({ emptyHeight: 200 })
    }
  }

  public buildDisplayCount(): number {
    return new BreakPointType({ xs: 1, sm: 1, md: 2, lg: 3 }).getValue(this.currentBreakpoint)
  }
}


@Component
struct CarouselLayout01CardView {
  private item: ContentDTO = {} as ContentDTO;
  private index: number = -1;

  build() {
    Stack() {
      Image(this.item.coverUrl)
        .width(CommonConstants.FULL_PARENT)
        .height(CommonConstants.FULL_PARENT)
        .objectFit(ImageFit.Cover)
      Row()
        .width(CommonConstants.FULL_PARENT)
        .height(60)
        .linearGradient({
          direction: GradientDirection.Top, // 渐变方向:to Top/从下往上
          colors: [[0x7508111A, 0.0], [0x7508111A, 0.3], [Color.Transparent, 1.0]]
        })
      // 文本信息
      Text(`${this.item.newsTitle}`)
        .width(CommonConstants.FULL_PARENT)
        .height(39)
        .padding({
          left: 10,
          right: 10
        })
        .margin({
          bottom: 28
        })
        .fontColor(Color.White)
        .fontSize($r('app.float.font_size_16'))
        .fontWeight(FontWeight.Medium)
        .textAlign(TextAlign.Start)
        .align(Alignment.Bottom)
        .maxLines(CompUtils.MAX_LINES_2)
        .textOverflow({ overflow: TextOverflow.Ellipsis })
    }
    .width(CommonConstants.FULL_WIDTH)
    .aspectRatio(CompUtils.ASPECT_RATIO_2_1)
    .alignContent(Alignment.BottomStart)
    .hoverEffect(HoverEffect.Scale)
    .onClick((event: ClickEvent) => {
      Logger.info(TAG, `ZhCarouselLayout01 onClick event index: ${this.index}`);
      ProcessUtils.processPage(this.item)
    })
  }
}


@Component
struct indicatorAnimations {
  @Prop index: number = 0
  @Prop isAutoPlay: boolean = true
  @State leftW: number | string = 0
  @State rightW: number | string = 0
  @State centerFontSize: number = 0

  aboutToAppear(): void {
    if (this.isAutoPlay) {
      setTimeout(() => {
        this.leftW = '100%'
        this.centerFontSize = 11
      }, 0)
      setTimeout(() => {
        this.rightW = '100%'
      }, 1500)
    } else {
      this.leftW = '100%'
      this.centerFontSize = 11
      this.rightW = '100%'
    }

  }

  build() {
    Flex({ alignItems: ItemAlign.End }) {
      Stack() {
        Image($r('app.media.swiper_indicator_gray'))
          .width('100%')
          .height(2)
        Image($r('app.media.swiper_indicator_white'))
          .width(this.leftW)
          .height(2)
          .animation({
            duration: 1500,
            curve: Curve.EaseOut,
            playMode: PlayMode.Normal
          })
      }
      .width('100%')
      .alignContent(Alignment.Start)

      Text(`0${this.index + 1}`)
        .fontSize(this.centerFontSize)
        .fontColor($r('app.color.white'))
        .width(16)
        .textAlign(TextAlign.Center)
        .margin({
          bottom: -2
        })
        .flexShrink(0)
        .animation({
          duration: 300,
          curve: Curve.EaseOut,
          playMode: PlayMode.Normal
        })
      Stack() {
        Image($r('app.media.swiper_indicator_gray'))
          .width('100%')
          .height(2)
        Image($r('app.media.swiper_indicator_white'))
          .width(this.rightW)
          .height(2)
          .animation({
            duration: 1500,
            curve: Curve.EaseOut,
            playMode: PlayMode.Normal
          })
      }
      .width('100%')
      .alignContent(Alignment.Start)
    }
    .height(14)
  }
}