import { HeroDeedItem } from '../model/Index' import { ThirdViewModel } from '../viewModel/ThirdViewModel' import { Location } from '../model/AnimationModel' import { IBestToast } from 'basic' import { HistoryApis } from '../Apis/HistoryApis' @ComponentV2 export struct ThirdView { vm: ThirdViewModel = new ThirdViewModel() build() { Column() { Row(){ Text('英雄人物模范事迹') .fontSize(18) .fontWeight(500) .fontColor('#FF333333') } .width("100%") .padding({top: 28, bottom: 15}) .justifyContent(FlexAlign.Center) List({space: 10}){ Repeat(this.vm.heroicModelCategory) .each((item) => { ListItem(){ Text(item.item) .fontSize(14) .borderRadius(44) .padding({left: 16, top: 6, right: 16, bottom: 6}) .fontWeight(this.vm.currentCategory == item.index ? 700 : 400) .fontColor(this.vm.currentCategory == item.index ? '#FFFFFFFF' : '#FF787878') .backgroundColor(this.vm.currentCategory == item.index ? '#FF45E595' : '#FFFFFFFF') .shadow(this.vm.currentCategory == item.index ? null : { color: '#1A000000', radius: 4 }) } .onClick(() => { this.vm.changeCategory(item.index) }) }) .key((item) => item) } .height(32) .width("100%") .scrollBar(BarState.Off) .listDirection(Axis.Horizontal) Column(){ List({space: 20}){ Repeat(this.vm.dataSource) .each((item) => { ListItem(){ HeroItem({data: item.item, flowerEvent: (i: HeroDeedItem) =>{ this.vm.onFlower(i, item.index) }}) } }) .key((item) => JSON.stringify(item)) } .width("100%") .height('100%') .scrollBar(BarState.Off) .onReachEnd(() => { if(this.vm.dataSource.length != 0) this.vm.getHeroDeedList(false) }) } .width("100%") .layoutWeight(1) } .width('100%') .height('100%') .padding({left: 17, right: 17, top: this.vm.safeTop}) .linearGradient({colors: [['#FFF4FFF1', 0], ['#FFFFFFFF', 0.8]]}) } } // 英雄人物事迹 Item @ComponentV2 struct HeroItem{ @Param @Require data: HeroDeedItem @Event flowerEvent: (data: HeroDeedItem) => void // 详情是否展开 - 默认收起 @Local isOpen: boolean = false @Local height_: number = 207 // 开始撒花动画 @Local flowerAnimation: boolean = false // 花瓣的坐标数组 @Local flowerCoordinates: Array = [] // 打开、关闭 详情 changeDetail(){ this.getUIContext().animateTo({ duration: 300 }, () =>{ this.isOpen = !this.isOpen }) } // 献花 async onFlower(){ try { let ans = await HistoryApis.giveFlowers(this.data.contentId!) console.log(`ans = ${JSON.stringify(ans)}`) this.flowerEvent(ans) this.startFlowerAnimation() } catch (e) { // IBestToast.show('献花失败') } } // 开启献花动画 startFlowerAnimation(){ IBestToast.show(`感谢您为${this.data?.heroName}英雄献花`) this.generateFlowerCoordinates(true) setTimeout(() => { this.generateFlowerCoordinates(false) }, 100) } // 生成花瓣坐标 generateFlowerCoordinates(isStart: boolean = true){ if(isStart){ this.flowerCoordinates = [] let len = this.isOpen ? 10 : 7 for(let i = 0; i < len; i++){ let x = 10 + Math.random() * 70 let y = 10 + Math.random() * (this.height_ - 40) let location: Location = new Location(x, y) this.flowerCoordinates.push(location) } this.flowerAnimation = true } else { for (let i = 0; i < this.flowerCoordinates.length; i++) { let f = new Location(this.flowerCoordinates[i].x, this.flowerCoordinates[i].y) // 将原来的固定值修改为随机值 // f.x += (Math.random() > 0.5 ? 1 : -1) * (5 + Math.random() * 15) f.y += 15 + Math.random() * (this.isOpen ? 300 : 50) this.getUIContext().animateTo({ duration: 800 }, () => { this.flowerCoordinates.splice(i, 1, f) }) } setTimeout(() => { this.flowerAnimation = false }, 800) } } build() { Stack(){ Column(){ Column(){ Row(){ Text(this.data?.heroName) .fontSize(22) .fontWeight(800) .fontColor('#FF333333') Text(this.data?.period) .fontSize(14) .fontWeight(400) .fontColor('#FF333333') } .width("100%") .justifyContent(FlexAlign.SpaceBetween) Row(){ Text(this.data?.description) .fontSize(14) .width("100%") .fontWeight(400) .fontColor('#FF333333') } .width("100%") .padding({top: 29}) Row(){ Row({space: 8}){ Image($r('app.media.icon_flower')) .width(38) .aspectRatio(1) Text(){ Span(this.data?.flowersNum ?? '0') .fontSize(20) .fontWeight(400) .fontColor('#FFFF7B00') Span('朵鲜花') .fontSize(12) .fontWeight(400) .fontColor('#FF333333') } } Row(){ Text('献花') .fontSize(14) .fontWeight(400) .fontColor('#FFFFFFFF') } .width(85) .height(30) .borderRadius(8) .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Center) .linearGradient({colors: [['#FFFFCA00', 0], ['#FFFF9D01', 0.5]], angle: 90}) .onClick(() => { this.onFlower() }) } .width("100%") .padding({top: 13, bottom: 30}) .justifyContent(FlexAlign.SpaceBetween) } .background(this.bgc(), {align: Alignment.Top}) .padding({left: 13, right: 13, top: 5}) Column(){ Column({space: 6}){ this.fontComp('英雄事迹') Text(this.data.heroicDeeds) .width("100%") .fontSize(12) .fontWeight(400) .lineHeight(20) this.fontComp('精神内涵') Row({space: 12}){ ForEach(this.data.type?.split('、'), (item: string, index) => { Text(item) .fontSize(12) .fontWeight(400) .borderRadius(5) .fontColor('#52886F') .backgroundColor('#F2F2F2') .padding({left: 13, top: 6, right: 13, bottom: 6}) }) } .width("100%") .justifyContent(FlexAlign.Start) .padding({bottom: 37}) } .height(this.isOpen ? '' : 0) // .backgroundColor(Color.Black) Row({space: 7}){ Text(this.isOpen ? '收起详情' : '展开详情') .fontSize(10) .fontWeight(400) .fontColor('#FF52886F') Image($r('app.media.icon_heroOpen')) .width(13) .aspectRatio(1) .rotate({angle: this.isOpen ? 180 : 0}) } .width("100%") .padding({top: 6, bottom: 6}) .justifyContent(FlexAlign.Center) .onClick(() => { this.changeDetail() }) } .padding({left: 13, right: 13}) } .width("100%") .justifyContent(FlexAlign.Start) .alignItems(HorizontalAlign.Center) .onAreaChange((o, n) => { if(this.isOpen){ this.height_ = Math.max(this.height_, n.height as number) } else { this.height_ = Math.min(this.height_, n.height as number) } console.log(`this.height_ = ${JSON.stringify(this.height_)}`) }) if(this.flowerAnimation) { Column(){ Repeat(this.flowerCoordinates) .each((item) => { Image($r('app.media.icon_hero_flower')) .width(36) .aspectRatio(1) .zIndex(999) .position({ x: `${item.item.x}%`, y: item.item.y }) .opacity(this.flowerAnimation ? 1 : 0) }) .key((item) => JSON.stringify(item)) } .width("100%") .height(this.height_) .opacity(this.flowerAnimation ? 1 : 0) } } .width('100%') .borderRadius(8) .padding({bottom: 8}) .backgroundColor(Color.White) .shadow({ color: '#1A000000', radius: 4 }) } @Builder bgc(){ Image($r('app.media.img_heroBgImg')) .width("100%") .height(207) } @Builder fontComp(text: string){ Stack({alignContent: Alignment.BottomStart}){ Image($r('app.media.icon_unLine')) .width(56) .height(13) .visibility(this.isOpen ? Visibility.Visible : Visibility.Hidden) Row(){ Text(text) .fontSize(14) .fontWeight(500) .fontColor('#333333') } .width("100%") .padding({bottom: 5}) .justifyContent(FlexAlign.Start) } } }