wangyong_wd

feat:实现swiper indicator自定义动画效果

@@ -18,6 +18,8 @@ export { LabelComponent } from "./src/main/ets/components/view/LabelComponent" @@ -18,6 +18,8 @@ export { LabelComponent } from "./src/main/ets/components/view/LabelComponent"
18 18
19 export { BannerComponent } from "./src/main/ets/components/view/BannerComponent" 19 export { BannerComponent } from "./src/main/ets/components/view/BannerComponent"
20 20
  21 +export { ZhCarouselLayout01 } from './src/main/ets/components/compview/ZhCarouselLayout01'
  22 +
21 export { SingleRow03Component } from "./src/main/ets/components/page/SingleRow03Component" 23 export { SingleRow03Component } from "./src/main/ets/components/page/SingleRow03Component"
22 24
23 export { SingleColumnComponent } from "./src/main/ets/components/page/SingleColumnComponent" 25 export { SingleColumnComponent } from "./src/main/ets/components/page/SingleColumnComponent"
@@ -17,6 +17,7 @@ import { ZhSingleColumn04 } from './compview/ZhSingleColumn04'; @@ -17,6 +17,7 @@ import { ZhSingleColumn04 } from './compview/ZhSingleColumn04';
17 import { ZhSingleColumn05 } from './compview/ZhSingleColumn05'; 17 import { ZhSingleColumn05 } from './compview/ZhSingleColumn05';
18 import { ZhSingleColumn09 } from './compview/ZhSingleColumn09'; 18 import { ZhSingleColumn09 } from './compview/ZhSingleColumn09';
19 import { ZhGridLayout03 } from './compview/ZhGridLayout03'; 19 import { ZhGridLayout03 } from './compview/ZhGridLayout03';
  20 +import { ZhCarouselLayout01 } from './compview/ZhCarouselLayout01';
20 import { CardParser } from './CardParser'; 21 import { CardParser } from './CardParser';
21 import { LiveHorizontalReservationComponent } from './view/LiveHorizontalReservationComponent'; 22 import { LiveHorizontalReservationComponent } from './view/LiveHorizontalReservationComponent';
22 import { ZhGridLayout02 } from './compview/ZhGridLayout02'; 23 import { ZhGridLayout02 } from './compview/ZhGridLayout02';
@@ -45,7 +46,7 @@ export struct CompParser { @@ -45,7 +46,7 @@ export struct CompParser {
45 if (compDTO.compStyle === CompStyle.Label_03) { 46 if (compDTO.compStyle === CompStyle.Label_03) {
46 LabelComponent({ compDTO: compDTO }) 47 LabelComponent({ compDTO: compDTO })
47 } else if (compDTO.compStyle === CompStyle.Zh_Carousel_Layout_01) { 48 } else if (compDTO.compStyle === CompStyle.Zh_Carousel_Layout_01) {
48 - BannerComponent({ compDTO: compDTO }) 49 + ZhCarouselLayout01({ compDTO: compDTO })
49 } else if (compDTO.compStyle === CompStyle.Zh_Single_Row_01 && compDTO.imageScale === 2) { 50 } else if (compDTO.compStyle === CompStyle.Zh_Single_Row_01 && compDTO.imageScale === 2) {
50 LiveHorizontalCardComponent({ compDTO: compDTO }) 51 LiveHorizontalCardComponent({ compDTO: compDTO })
51 } else if (compDTO.compStyle === CompStyle.Zh_Single_Row_01 && compDTO.imageScale === 3) { 52 } else if (compDTO.compStyle === CompStyle.Zh_Single_Row_01 && compDTO.imageScale === 3) {
  1 +import { CompDTO, ContentDTO, } from 'wdBean';
  2 +import { BreakpointConstants, CommonConstants, DurationEnum } from 'wdConstant';
  3 +import { BreakPointType, Logger } from 'wdKit';
  4 +import { CompUtils } from '../../utils/CompUtils';
  5 +import { ProcessUtils } from '../../utils/ProcessUtils';
  6 +import { EmptyComponent } from '../view/EmptyComponent';
  7 +
  8 +const TAG = 'Zh_Carousel_Layout-01';
  9 +
  10 +/**
  11 + * 轮播组件,即Banner/轮播大图/焦点图/自动滑动
  12 + * 样式:
  13 + * 'Zh_Carousel_Layout-01', // 通用轮播卡:视频、直播、活动、专题、榜单、外链
  14 + */
  15 +
  16 +
  17 +class MyDataSource implements IDataSource {
  18 + private list: number[] = []
  19 +
  20 + constructor(list: number[]) {
  21 + this.list = list
  22 + }
  23 +
  24 + totalCount(): number {
  25 + return this.list.length
  26 + }
  27 +
  28 + getData(index: number): number {
  29 + return this.list[index]
  30 + }
  31 +
  32 + registerDataChangeListener(listener: DataChangeListener): void {
  33 + }
  34 +
  35 + unregisterDataChangeListener() {
  36 + }
  37 +}
  38 +
  39 +@Component
  40 +export struct ZhCarouselLayout01 {
  41 + @StorageLink('currentBreakpoint') @Watch('watchCurrentBreakpoint') currentBreakpoint: string = BreakpointConstants.BREAKPOINT_XS;
  42 + @State compDTO: CompDTO = {} as CompDTO
  43 + private data: MyDataSource = new MyDataSource([])
  44 + @State firstWd: number = 0
  45 + @State SecondWd: number = 0
  46 + @State swiperIndex: number = 0
  47 +
  48 + watchCurrentBreakpoint() {
  49 + Logger.info(TAG, `watchCurrentBreakpoint, this.currentBreakpoint: ${this.currentBreakpoint}`);
  50 + }
  51 +
  52 + aboutToAppear() {
  53 + Logger.info(TAG, `aboutToAppear, beanList:${this.compDTO?.operDataList?.length}, currentBreakpoint:${this.currentBreakpoint}`);
  54 + let list: number[] = []
  55 + for (let i = 1; i <= this.compDTO?.operDataList?.length; i++) {
  56 + list.push(i);
  57 + }
  58 + this.data = new MyDataSource(list)
  59 + }
  60 +
  61 + isAutoPlay() {
  62 + if (this.compDTO.extraData) {
  63 + return JSON.parse(this.compDTO.extraData).autoplay == 1
  64 + } else {
  65 + return false
  66 + }
  67 + }
  68 +
  69 + build() {
  70 + if (this.compDTO?.operDataList?.length) {
  71 + Stack() {
  72 + Swiper() {
  73 + ForEach(this.compDTO?.operDataList, (item: ContentDTO, index: number) => {
  74 + CarouselLayout01CardView({
  75 + item: item,
  76 + index: index
  77 + })
  78 + })
  79 + }
  80 + .borderRadius($r('app.float.image_border_radius'))
  81 + .displayCount(this.buildDisplayCount()) // 仅展示1个图片
  82 + .cachedCount(2)
  83 + .index(0) // The default index of Swiper.
  84 + .indicator(false)
  85 + .loop(true)
  86 + .vertical(false)
  87 + .curve(Curve.Linear)
  88 + .autoPlay(this.isAutoPlay())
  89 + .onAnimationStart((index: number, targetIndex: number) => {
  90 + Logger.info(TAG, `Swiper onAnimationStart index : ${index}, targetIndex: ${targetIndex}`);
  91 + this.swiperIndex = targetIndex
  92 + })
  93 + .onChange((index: number) => {
  94 + Logger.info(TAG, `Swiper onChange index : ${index}`);
  95 +
  96 + })
  97 + .onAnimationEnd((index: number, extraInfo: SwiperAnimationEvent) => {
  98 + this.firstWd = 12
  99 + setTimeout(() => {
  100 + this.SecondWd = 12
  101 + }, 2000)
  102 + console.info("onAnimationEnd, index: " + index)
  103 + })
  104 +
  105 + // 自定义indicator
  106 + GridRow({
  107 + columns: this.data.totalCount(),
  108 + gutter: { x: 2 }
  109 + }) {
  110 + LazyForEach(this.data, (item: string, index: number) => {
  111 + GridCol() {
  112 + if (index === this.swiperIndex) {
  113 + indicatorAnimations({
  114 + index: index,
  115 + isAutoPlay: this.isAutoPlay()
  116 + })
  117 + } else {
  118 + Row() {
  119 + Image($r('app.media.swiper_indicator_gray'))
  120 + .width('100%')
  121 + .height(2)
  122 + }
  123 + }
  124 + }
  125 + }, (item: string) => item)
  126 + }
  127 + .width(CommonConstants.FULL_PARENT)
  128 + .padding({
  129 + left: 10,
  130 + right: 10,
  131 + top: 12,
  132 + bottom: 12
  133 + })
  134 + .alignItems(ItemAlign.End)
  135 + }
  136 + .alignContent(Alignment.BottomEnd)
  137 + .width(CommonConstants.FULL_WIDTH)
  138 + .padding({
  139 + left: $r('app.float.card_comp_pagePadding_lf'),
  140 + right: $r('app.float.card_comp_pagePadding_lf'),
  141 + top: $r('app.float.card_comp_pagePadding_tb'),
  142 + bottom: $r('app.float.card_comp_pagePadding_tb')
  143 + })
  144 +
  145 + // .backgroundColor($r('app.color.white'))
  146 + } else {
  147 + EmptyComponent({ emptyHeight: 200 })
  148 + }
  149 + }
  150 +
  151 + public buildDisplayCount(): number {
  152 + return new BreakPointType({ xs: 1, sm: 1, md: 2, lg: 3 }).getValue(this.currentBreakpoint)
  153 + }
  154 +}
  155 +
  156 +
  157 +@Component
  158 +struct CarouselLayout01CardView {
  159 + private item: ContentDTO = {} as ContentDTO;
  160 + private index: number = -1;
  161 +
  162 + build() {
  163 + Stack() {
  164 + Image(this.item.coverUrl)
  165 + .width(CommonConstants.FULL_PARENT)
  166 + .height(CommonConstants.FULL_PARENT)
  167 + .objectFit(ImageFit.Cover)
  168 + Row()
  169 + .width(CommonConstants.FULL_PARENT)
  170 + .height(60)
  171 + .linearGradient({
  172 + direction: GradientDirection.Top, // 渐变方向:to Top/从下往上
  173 + colors: [[0x7508111A, 0.0], [0x7508111A, 0.3], [Color.Transparent, 1.0]]
  174 + })
  175 + // 文本信息
  176 + Text(`${this.item.newsTitle}`)
  177 + .width(CommonConstants.FULL_PARENT)
  178 + .height(39)
  179 + .padding({
  180 + left: 10,
  181 + right: 10
  182 + })
  183 + .margin({
  184 + bottom: 28
  185 + })
  186 + .fontColor(Color.White)
  187 + .fontSize($r('app.float.font_size_16'))
  188 + .fontWeight(FontWeight.Medium)
  189 + .textAlign(TextAlign.Start)
  190 + .align(Alignment.Bottom)
  191 + .maxLines(CompUtils.MAX_LINES_2)
  192 + .textOverflow({ overflow: TextOverflow.Ellipsis })
  193 + }
  194 + .width(CommonConstants.FULL_WIDTH)
  195 + .aspectRatio(CompUtils.ASPECT_RATIO_2_1)
  196 + .alignContent(Alignment.BottomStart)
  197 + .hoverEffect(HoverEffect.Scale)
  198 + .onClick((event: ClickEvent) => {
  199 + Logger.info(TAG, `ZhCarouselLayout01 onClick event index: ${this.index}`);
  200 + ProcessUtils.processPage(this.item)
  201 + })
  202 + }
  203 +}
  204 +
  205 +
  206 +@Component
  207 +struct indicatorAnimations {
  208 + @Prop index: number = 0
  209 + @Prop isAutoPlay: boolean = true
  210 + @State leftW: number | string = 0
  211 + @State rightW: number | string = 0
  212 + @State centerFontSize: number = 0
  213 +
  214 + aboutToAppear(): void {
  215 + if (this.isAutoPlay) {
  216 + setTimeout(() => {
  217 + this.leftW = '100%'
  218 + this.centerFontSize = 11
  219 + }, 0)
  220 + setTimeout(() => {
  221 + this.rightW = '100%'
  222 + }, 1500)
  223 + } else {
  224 + this.leftW = '100%'
  225 + this.centerFontSize = 11
  226 + this.rightW = '100%'
  227 + }
  228 +
  229 + }
  230 +
  231 + build() {
  232 + Flex({ alignItems: ItemAlign.End }) {
  233 + Stack() {
  234 + Image($r('app.media.swiper_indicator_gray'))
  235 + .width('100%')
  236 + .height(2)
  237 + Image($r('app.media.swiper_indicator_white'))
  238 + .width(this.leftW)
  239 + .height(2)
  240 + .animation({
  241 + duration: 1500,
  242 + curve: Curve.EaseOut,
  243 + playMode: PlayMode.Normal
  244 + })
  245 + }
  246 + .width('100%')
  247 + .alignContent(Alignment.Start)
  248 +
  249 + Text(`0${this.index + 1}`)
  250 + .fontSize(this.centerFontSize)
  251 + .fontColor($r('app.color.white'))
  252 + .width(16)
  253 + .textAlign(TextAlign.Center)
  254 + .margin({
  255 + bottom: -2
  256 + })
  257 + .flexShrink(0)
  258 + .animation({
  259 + duration: 300,
  260 + curve: Curve.EaseOut,
  261 + playMode: PlayMode.Normal
  262 + })
  263 + Stack() {
  264 + Image($r('app.media.swiper_indicator_gray'))
  265 + .width('100%')
  266 + .height(2)
  267 + Image($r('app.media.swiper_indicator_white'))
  268 + .width(this.rightW)
  269 + .height(2)
  270 + .animation({
  271 + duration: 1500,
  272 + curve: Curve.EaseOut,
  273 + playMode: PlayMode.Normal
  274 + })
  275 + }
  276 + .width('100%')
  277 + .alignContent(Alignment.Start)
  278 + }
  279 + .height(14)
  280 + }
  281 +}