ZhCarouselLayout01.ets 10.3 KB
import { CompDTO, ContentDTO } from 'wdBean';
import { BreakpointConstants, CommonConstants } 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';
import { Notes } from '../cardview/notes';
import { InfomationCardClick } from '../../utils/infomationCardClick'
import font from '@ohos.font';

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 {
  @State pageId: string = '';
  @State pageName: string = '';
  @StorageLink('currentBreakpoint') @Watch('watchCurrentBreakpoint') currentBreakpoint: string =
    BreakpointConstants.BREAKPOINT_XS;
  @State compDTO: CompDTO = {} as CompDTO

  @State firstWd: number = 0
  @State SecondWd: number = 0
  @State swiperIndex: number = 0

  private data: MyDataSource = new MyDataSource([])

  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)

    font.registerFont({
      familyName: 'BebasNeue',
      familySrc: $rawfile('font/BebasNeue.ttf')
    })
  }

  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
            })
              .onClick((event: ClickEvent) => {
                InfomationCardClick.track(this.compDTO, item, this.pageId, this.pageName)
                Logger.info(TAG, `ZhCarouselLayout01 onClick event index: ${index}`)
                ProcessUtils.processPage(item)
              })
          })
        }
        .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)
      .padding({
        left: 10,
        right: 10,
        top: $r('app.float.card_comp_pagePadding_tb'),
        bottom: $r('app.float.card_comp_pagePadding_tb')
      })
      .backgroundColor(0xffffff)
      .width(CommonConstants.FULL_WIDTH)
    } else {
      EmptyComponent({ emptyHeight: 200 })
    }
  }

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


@Component
struct CarouselLayout01CardView {
  @State loadImg: boolean = false;
  private item: ContentDTO = new ContentDTO();
  private length: number = 1; // 轮播图数量

  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') {
          // 2024-05-28 给CardMediaInfo组件添加beused的字段让其知道被哪个组件使用,不传默认为空
          CardMediaInfo({ contentDTO: this.item,livePeopleNum:false ,beused:'Zh_Carousel_Layout_01'})
            .width(CommonConstants.FULL_PARENT)
        }
        Blank()
        // 文本信息
        Stack() {
          if(this.item.objectType == '5'){
            Notes({ objectType: this.item.objectType,objectLevel:this.item.objectLevel })
          } else {
            if (this.item.seoTags) {
              Notes({ newTags: this.item.seoTags })
            }
            if (this.item.newTags) {
              Notes({ newTags: this.item.newTags })
            }
          }
          Text(`${this.item.newsTitle}`)
            .width(CommonConstants.FULL_PARENT)
            .fontColor(Color.White)
            .fontSize($r('app.float.font_size_18'))
            .fontWeight(FontWeight.Medium)
            .textAlign(TextAlign.Start)
            .align(Alignment.Bottom)
            .maxLines(CompUtils.MAX_LINES_2)
            .textOverflow({ overflow: TextOverflow.Ellipsis })
            .textIndent((this.item.newTags?.length || this.item.seoTags?.length) > 2 &&
              (this.item.newTags?.length ||this.item.seoTags?.length) < 5 ? 58 :
              ((this.item.newTags?.length > 0 || this.item.seoTags?.length > 0) ||this.item.objectType == '5') ? 35 :
                0 )
        }
        // .height(39)
        .padding({
          left: 10,
          right: 10
        })
        .margin({
          bottom: this.length > 1 ? 28 : 10
        })
        .alignContent(Alignment.TopStart)

      }
      .width(CommonConstants.FULL_PARENT)
      .height(CommonConstants.FULL_PARENT)
    }
    .width(CommonConstants.FULL_WIDTH)
    .aspectRatio(CompUtils.ASPECT_RATIO_16_9)
    .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 = 10
      }, 0)
      setTimeout(() => {
        this.rightW = '100%'
      }, 1500)
    } else {
      this.leftW = '100%'
      this.centerFontSize = 10
      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_gray'))
          .objectFit(ImageFit.Contain)
          .width('96%')
          .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(11)
        .textAlign(TextAlign.Center)
        .margin({
          bottom: -2
        })
        .fontFamily('BebasNeue')
        .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_gray'))
          .objectFit(ImageFit.Contain)
          .width('96%')
          .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)
  }
}