ZhCarouselLayout01.ets 8.68 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 'wdRouter';
import { EmptyComponent } from '../view/EmptyComponent';
import { CardMediaInfo } from '../cardCommon/CardMediaInfo';
import { onlyWifiLoadImg } from '../../utils/lazyloadImg';

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,
              length: this.compDTO.operDataList.length
            })
          })
        }
        .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)
        })

        if (this.compDTO?.operDataList.length > 1) {
          // 自定义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')
      })
      .onClick((event: ClickEvent) => {
        Logger.info(TAG, `ZhCarouselLayout01 onClick event index: ${this.swiperIndex}`);
        ProcessUtils.processPage(this.compDTO.operDataList[this.swiperIndex])
      })
    } 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 length: number = 1; // 轮播图数量
  @State loadImg: boolean = false;

  async aboutToAppear(): Promise<void> {
    this.loadImg = await onlyWifiLoadImg();
  }

  build() {
    Stack() {
      Image(this.loadImg ? this.item.coverUrl : '')
        .width(CommonConstants.FULL_PARENT)
        .height(CommonConstants.FULL_PARENT)
        .objectFit(ImageFit.Cover)
        .backgroundColor(0xf5f5f5)

      Row()
        .width(CommonConstants.FULL_PARENT)
        .height(60)
        .linearGradient({
          direction: GradientDirection.Top, // 渐变方向:to Top/从下往上
          colors: [[0x7508111A, 0.0], [0x7508111A, 0.3], [Color.Transparent, 1.0]]
        })
      Column() {
        // 这里用于展示轮播图右上角信息,这里只对直播类型的展示
        if (this.item.objectType === '2' || this.item.objectType ==='4') {
          CardMediaInfo({ contentDTO: this.item })
            .width(CommonConstants.FULL_PARENT)
        }
        Blank()
        // 文本信息
        Text(`${this.item.corner}${this.item.newsTitle}`)
          .width(CommonConstants.FULL_PARENT)
          .height(39)
          .padding({
            left: 10,
            right: 10
          })
          .margin({
            bottom: this.length > 1 ? 28 : 10
          })
          .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_PARENT)
      .height(CommonConstants.FULL_PARENT)
    }
    .width(CommonConstants.FULL_WIDTH)
    .aspectRatio(CompUtils.ASPECT_RATIO_2_1)
    .alignContent(Alignment.BottomStart)
    .hoverEffect(HoverEffect.Scale)
  }
}


@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(this.index + 1 < 10 ? `0${this.index + 1}` : `${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)
  }
}