|
@@ -1,165 +1,251 @@
|
|
|
-@Component
|
|
|
|
|
|
|
+import { DeerSearch } from '../components/DeerSearch'
|
|
|
|
|
+import { SecondViewModel } from './viewModel/SecondViewModel'
|
|
|
|
|
+import { CustomTextStyle } from '../style/CustomTextStyle'
|
|
|
|
|
+import { bookItemComp } from '../components/BuilderIndex'
|
|
|
|
|
+
|
|
|
|
|
+@ComponentV2
|
|
|
export struct SecondView {
|
|
export struct SecondView {
|
|
|
- @State animate_scale: boolean = false; // 商品缩小动画
|
|
|
|
|
- @State toggle: boolean = false; // 轨迹动画控制flag
|
|
|
|
|
- @State imageScaleX: number = 1; // 商品缩小尺寸X
|
|
|
|
|
- @State imageScaleY: number = 1; // 商品缩小尺寸Y
|
|
|
|
|
- @State cartAngle: number = 0; // 购物车抖动幅度
|
|
|
|
|
|
|
+ vm: SecondViewModel = new SecondViewModel()
|
|
|
|
|
|
|
|
build() {
|
|
build() {
|
|
|
- Column() {
|
|
|
|
|
- Row() {
|
|
|
|
|
- // 用stack包两个image,实现商品缩小动效;这里需要注意的是,图片给大小,父组件不给大小,跟随image大小;
|
|
|
|
|
- // 使得column包着图片做路径动画;
|
|
|
|
|
- Stack() {
|
|
|
|
|
- Image($r('app.media.app_icon'))
|
|
|
|
|
- .objectFit(ImageFit.Contain)
|
|
|
|
|
- .width(400)
|
|
|
|
|
- .height(400)
|
|
|
|
|
- if (this.animate_scale) {
|
|
|
|
|
- Column() {
|
|
|
|
|
- Image($r('app.media.app_icon'))
|
|
|
|
|
- .objectFit(ImageFit.Contain)
|
|
|
|
|
- .width(400)
|
|
|
|
|
- .height(400)
|
|
|
|
|
- .scale({ x: this.imageScaleX, y: this.imageScaleY })
|
|
|
|
|
- .motionPath({
|
|
|
|
|
- path: 'Mstart.x start.y C -400 50, -150 200, -360 1480', // -360 1500是相对于原位置的终点位置
|
|
|
|
|
- from: 0.0,
|
|
|
|
|
- to: 1.0,
|
|
|
|
|
- rotatable: false
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- .zIndex(3)
|
|
|
|
|
- .alignItems(this.toggle ? HorizontalAlign.Start : HorizontalAlign.Center)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ Column(){
|
|
|
|
|
+ Row({space: 12}){
|
|
|
|
|
+ Row({space: 6}){
|
|
|
|
|
+ Text('年龄选择')
|
|
|
|
|
+ .attributeModifier(new CustomTextStyle({size: 14, weight: 600}))
|
|
|
|
|
+
|
|
|
|
|
+ Image($r('[basic].media.icon_expension'))
|
|
|
|
|
+ .width(10)
|
|
|
|
|
+ .height(8)
|
|
|
|
|
+ .rotate({ angle: this.vm.openAgeDialog ? 180 : 0 })
|
|
|
|
|
+ .animation({duration: 200, curve: Curve.Smooth})
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- .backgroundColor(Color.Blue)
|
|
|
|
|
|
|
+ .borderRadius(18)
|
|
|
|
|
+ .backgroundColor('#FFFECF2F')
|
|
|
|
|
+ .border({width: 2, color: '#FF000000'})
|
|
|
|
|
+ .padding({left: 15, top: 8, right: 15, bottom: 8})
|
|
|
|
|
+ .bindMenu(this.ageSelect())
|
|
|
|
|
+ .onClick(() => { if(!this.vm.openAgeDialog) this.vm.openAgeDialog = true })
|
|
|
|
|
|
|
|
- Column() {
|
|
|
|
|
- Text('XXX元')
|
|
|
|
|
- .fontSize(20)
|
|
|
|
|
- Text('收货地址:XXX')
|
|
|
|
|
- .fontSize(18)
|
|
|
|
|
|
|
+ DeerSearch({showSearchButton: false, enable: false})
|
|
|
|
|
+ .layoutWeight(1)
|
|
|
}
|
|
}
|
|
|
- .width('100%')
|
|
|
|
|
- .margin({ left: 20, top: 20, bottom: 20 })
|
|
|
|
|
- .alignItems(HorizontalAlign.Start)
|
|
|
|
|
-
|
|
|
|
|
- Row() {
|
|
|
|
|
- Column() {
|
|
|
|
|
- Image($r('app.media.app_icon'))
|
|
|
|
|
- .width(25)
|
|
|
|
|
- .height(25)
|
|
|
|
|
- .margin(5)
|
|
|
|
|
- Text('首页')
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ .width("100%")
|
|
|
|
|
+ .padding({left: 16, right: 16, top: this.vm.safeTop, bottom: 20})
|
|
|
|
|
+ .linearGradient( this.vm.openTypeDialog ? {colors: [['#FFF2C0', 0], ['#FFF3C6', 1]]} : undefined)
|
|
|
|
|
|
|
|
- Column() {
|
|
|
|
|
- Image($r('app.media.app_icon'))
|
|
|
|
|
- .width(25)
|
|
|
|
|
- .height(25)
|
|
|
|
|
- .margin(5)
|
|
|
|
|
- Text('消息')
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ Column(){
|
|
|
|
|
+ RelativeContainer(){
|
|
|
|
|
+ // 页面的 Title
|
|
|
|
|
+ Column(){
|
|
|
|
|
+ Row(){
|
|
|
|
|
+ Row(){
|
|
|
|
|
+ List({space: 22, scroller: this.vm.categoryControl}){
|
|
|
|
|
+ ForEach(this.vm.categoryList, (item: string, index) => {
|
|
|
|
|
+ ListItem(){
|
|
|
|
|
+ Column(){
|
|
|
|
|
+ Text(item)
|
|
|
|
|
+ .zIndex(99)
|
|
|
|
|
+ .onClick(() => { this.vm.changeCategory(index) })
|
|
|
|
|
+ .attributeModifier(new CustomTextStyle({size: 16, weight: 600, color: this.vm.categoryIndex == index ? '#FF111111' : '#FF777777'}))
|
|
|
|
|
|
|
|
- Column() {
|
|
|
|
|
- Image($r('app.media.app_icon'))
|
|
|
|
|
- .width(25)
|
|
|
|
|
- .rotate({
|
|
|
|
|
- angle: this.cartAngle
|
|
|
|
|
- })
|
|
|
|
|
- .height(25)
|
|
|
|
|
- .margin(5)
|
|
|
|
|
- Text('购物车')
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if(this.vm.categoryIndex == index){
|
|
|
|
|
+ Image($r('[basic].media.icon_SelectBg'))
|
|
|
|
|
+ .width(45)
|
|
|
|
|
+ .height(16)
|
|
|
|
|
+ .margin({top:-10})
|
|
|
|
|
+ .transition(TransitionEffect.asymmetric(TransitionEffect.move(TransitionEdge.TOP), TransitionEffect.move(TransitionEdge.TOP)).animation({ duration: 100, curve: Curve.Smooth }))
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .alignItems(HorizontalAlign.Center)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ .height(40)
|
|
|
|
|
+ .width("100%")
|
|
|
|
|
+ .scrollBar(BarState.Off)
|
|
|
|
|
+ .listDirection(Axis.Horizontal)
|
|
|
|
|
+ }.layoutWeight(1)
|
|
|
|
|
|
|
|
- Button('加入购物车')
|
|
|
|
|
- .zIndex(1)
|
|
|
|
|
- .backgroundColor('#ffcdcdcd')
|
|
|
|
|
- .fontColor(Color.Red)
|
|
|
|
|
- .fontSize(15)
|
|
|
|
|
- .width(120)
|
|
|
|
|
- .margin({ left: 20, right: 10 })
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.animate_scale = true;
|
|
|
|
|
- // 先做商品缩小动效
|
|
|
|
|
- this.animationImageScale();
|
|
|
|
|
|
|
+ Row(){
|
|
|
|
|
+ Image($r('[basic].media.icon_expension'))
|
|
|
|
|
+ .width(10)
|
|
|
|
|
+ .height(8)
|
|
|
|
|
+ .rotate({ angle: this.vm.openTypeDialog ? 180 : 0 })
|
|
|
|
|
+ .animation({duration: 200, curve: Curve.Smooth})
|
|
|
|
|
+ }
|
|
|
|
|
+ .padding({left: 16, top: 2})
|
|
|
|
|
+ .onClick(() => { this.vm.openCategoryDialog() })
|
|
|
|
|
+
|
|
|
|
|
+ }.alignItems(VerticalAlign.Top)
|
|
|
|
|
+
|
|
|
|
|
+ Row(){
|
|
|
|
|
+ Row(){
|
|
|
|
|
+ ForEach(['最新', '最热'], (item: string, index: number) => {
|
|
|
|
|
+ Text(item)
|
|
|
|
|
+ .borderRadius(15)
|
|
|
|
|
+ .padding({left: 12, top: 5, right: 12, bottom: 5})
|
|
|
|
|
+ .attributeModifier(new CustomTextStyle({size: 14, weight: 600}))
|
|
|
|
|
+ .border({width: 2, color: this.vm.sortType == index ? '#FF000000' : Color.Transparent})
|
|
|
|
|
+ .backgroundColor(this.vm.sortType == index ? '#FFFECF2F' : Color.Transparent)
|
|
|
|
|
+ .onClick(() => { this.vm.changeSortType(index) })
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Row({space: 16}){
|
|
|
|
|
+ Row({space: 6}){
|
|
|
|
|
+ Blank()
|
|
|
|
|
+ .width(14)
|
|
|
|
|
+ .aspectRatio(1)
|
|
|
|
|
+ .borderRadius(2)
|
|
|
|
|
+ .border({width: 2, color: '#FF000000'})
|
|
|
|
|
+ .backgroundColor(this.vm.isRead ? '#FFFECF2F' : Color.White)
|
|
|
|
|
+ Text('未读')
|
|
|
|
|
+ .attributeModifier(new CustomTextStyle({size: 14, weight: 400}))
|
|
|
|
|
+ }.onClick(() => { this.vm.changeIsRead() })
|
|
|
|
|
+
|
|
|
|
|
+ Text(this.vm.showMode ? '封面模式' : '列表模式')
|
|
|
|
|
+ .onClick(() => { this.vm.changeShowMode() })
|
|
|
|
|
+ .attributeModifier(new CustomTextStyle({size: 14, weight: 400}))
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .width("100%")
|
|
|
|
|
+ .margin({top: 10})
|
|
|
|
|
+ .justifyContent(FlexAlign.SpaceBetween)
|
|
|
|
|
+ }
|
|
|
|
|
+ .width("100%")
|
|
|
|
|
+ .id('classify')
|
|
|
|
|
+ .backgroundColor(Color.White)
|
|
|
|
|
+ .borderRadius({bottomLeft: 20, bottomRight: 20})
|
|
|
|
|
+ .padding({left: 16, right: 16, bottom: 18})
|
|
|
|
|
+ .alignRules({
|
|
|
|
|
+ left: { anchor: '__container__', align: HorizontalAlign.Start },
|
|
|
|
|
+ top: { anchor: '__container__', align: VerticalAlign.Top }
|
|
|
})
|
|
})
|
|
|
- Button('购买')
|
|
|
|
|
- .width(120)
|
|
|
|
|
- .zIndex(1)
|
|
|
|
|
- .backgroundColor(Color.Red)
|
|
|
|
|
- .fontColor(Color.White)
|
|
|
|
|
- .fontSize(15)
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 书籍列表项
|
|
|
|
|
+ Column(){
|
|
|
|
|
+ List({space: 12}){
|
|
|
|
|
+ ListItem()
|
|
|
|
|
+
|
|
|
|
|
+ Repeat(this.vm.bookList)
|
|
|
|
|
+ .each((item) => {
|
|
|
|
|
+ bookItemComp(item.item, () => {})
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ .width("100%")
|
|
|
|
|
+ .height("100%")
|
|
|
|
|
+ .scrollBar(BarState.Off)
|
|
|
|
|
+ }
|
|
|
|
|
+ .id('list')
|
|
|
|
|
+ .width("100%")
|
|
|
|
|
+ .layoutWeight(1)
|
|
|
|
|
+ .padding({left: 16, right: 16})
|
|
|
|
|
+ .backgroundColor(Color.Transparent)
|
|
|
|
|
+ .alignRules({
|
|
|
|
|
+ left: { anchor: '__container__', align: HorizontalAlign.Start },
|
|
|
|
|
+ top: { anchor: 'classify', align: VerticalAlign.Bottom }
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // 分类弹窗
|
|
|
|
|
+ if(this.vm.openTypeDialog){
|
|
|
|
|
+ Column(){
|
|
|
|
|
+ Column(){
|
|
|
|
|
+ Row(){
|
|
|
|
|
+ Column(){
|
|
|
|
|
+ Text('选择分类')
|
|
|
|
|
+ .zIndex(99)
|
|
|
|
|
+ .attributeModifier(new CustomTextStyle({size: 16, weight: 600}))
|
|
|
|
|
+
|
|
|
|
|
+ Image($r('[basic].media.icon_SelectBg'))
|
|
|
|
|
+ .width(45)
|
|
|
|
|
+ .height(16)
|
|
|
|
|
+ .margin({top:-10})
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Column(){
|
|
|
|
|
+ Image($r('[basic].media.icon_expension'))
|
|
|
|
|
+ .width(10)
|
|
|
|
|
+ .height(8)
|
|
|
|
|
+ .rotate({ angle: this.vm.openTypeDialog ? 180 : 0 })
|
|
|
|
|
+ .animation({duration: 200, curve: Curve.Smooth})
|
|
|
|
|
+ }
|
|
|
|
|
+ .width(50)
|
|
|
|
|
+ .height(24)
|
|
|
|
|
+ .alignItems(HorizontalAlign.End)
|
|
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
|
|
+ .onClick(() => { this.vm.openCategoryDialog() })
|
|
|
|
|
+ }
|
|
|
|
|
+ .width("100%")
|
|
|
|
|
+ .justifyContent(FlexAlign.SpaceBetween)
|
|
|
|
|
+
|
|
|
|
|
+ Grid(){
|
|
|
|
|
+ ForEach(this.vm.categoryList, (item: string, index: number) => {
|
|
|
|
|
+ GridItem(){
|
|
|
|
|
+ Text(item)
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .borderRadius(18)
|
|
|
|
|
+ .textAlign(TextAlign.Center)
|
|
|
|
|
+ .padding({top: 6, bottom: 6})
|
|
|
|
|
+ .backgroundColor(this.vm.categoryIndex == index ? '#FFFECF2F' : '#FFFFFF')
|
|
|
|
|
+ .border({width: 2, color: this.vm.categoryIndex == index ? '#FF000000' : '#FFFFFF'})
|
|
|
|
|
+ .attributeModifier(new CustomTextStyle({size: 16, weight: 400}))
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.vm.changeCategory(index, true)
|
|
|
|
|
+ this.vm.openCategoryDialog()
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ .rowsGap(14)
|
|
|
|
|
+ .columnsGap(23)
|
|
|
|
|
+ .margin({top: 13})
|
|
|
|
|
+ .maxCount(Math.abs(this.vm.categoryList.length/3))
|
|
|
|
|
+ .columnsTemplate('repeat(3, 1fr)')
|
|
|
|
|
+ }
|
|
|
|
|
+ .width("100%")
|
|
|
|
|
+ .onClick(() => {})
|
|
|
|
|
+ .padding({left: 17, right: 17, bottom: 13})
|
|
|
|
|
+ .borderRadius({bottomLeft: 16, bottomRight: 16})
|
|
|
|
|
+ .linearGradient({colors: [['#FFF3C6', 0], ['#FFF9E4', 1]]})
|
|
|
|
|
+ .transition(TransitionEffect.translate({ y: -20 })
|
|
|
|
|
+ .animation({ duration: 200, curve: Curve.Friction}))
|
|
|
|
|
+ }
|
|
|
|
|
+ .width("100%")
|
|
|
|
|
+ .height("100%")
|
|
|
|
|
+ .backgroundColor('rgba(0, 0, 0, 0.5)')
|
|
|
|
|
+ .onClick(() => { this.vm.openCategoryDialog() })
|
|
|
|
|
+ .alignRules({
|
|
|
|
|
+ left: { anchor: '__container__', align: HorizontalAlign.Start },
|
|
|
|
|
+ top: { anchor: '__container__', align: VerticalAlign.Top }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .height('100%')
|
|
|
|
|
+ .backgroundColor('#F7F9FA')
|
|
|
}
|
|
}
|
|
|
- .zIndex(1)
|
|
|
|
|
- .height('20%')
|
|
|
|
|
.width('100%')
|
|
.width('100%')
|
|
|
|
|
+ .layoutWeight(1)
|
|
|
}
|
|
}
|
|
|
- .justifyContent(FlexAlign.SpaceBetween)
|
|
|
|
|
- .height('100%')
|
|
|
|
|
.width('100%')
|
|
.width('100%')
|
|
|
|
|
+ .height('100%')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- animationImageShake() {
|
|
|
|
|
- animateTo({
|
|
|
|
|
- duration: 100,
|
|
|
|
|
- curve: Curve.Linear,
|
|
|
|
|
- onFinish: () => {
|
|
|
|
|
- animateTo({
|
|
|
|
|
- duration: 100,
|
|
|
|
|
- curve: Curve.Linear,
|
|
|
|
|
- onFinish: () => {
|
|
|
|
|
- // 最终节点,恢复所有设置
|
|
|
|
|
- this.cartAngle = 0;
|
|
|
|
|
- this.animate_scale = false;
|
|
|
|
|
- this.imageScaleX = 1;
|
|
|
|
|
- this.imageScaleY = 1;
|
|
|
|
|
- }
|
|
|
|
|
- }, () => {
|
|
|
|
|
- this.cartAngle = -30;
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- }, () => {
|
|
|
|
|
- this.cartAngle = 30;
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- animationImageScale() {
|
|
|
|
|
- animateTo({
|
|
|
|
|
- duration: 100,
|
|
|
|
|
- curve: Curve.EaseOut,
|
|
|
|
|
- iterations: 1,
|
|
|
|
|
- playMode: PlayMode.Normal,
|
|
|
|
|
- onFinish: () => {
|
|
|
|
|
- console.info('scale play end')
|
|
|
|
|
- // 做路径动效
|
|
|
|
|
- this.animationImageMove();
|
|
|
|
|
- }
|
|
|
|
|
- }, () => {
|
|
|
|
|
- this.imageScaleX = 0.1
|
|
|
|
|
- this.imageScaleY = 0.1
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- animationImageMove() {
|
|
|
|
|
- animateTo({
|
|
|
|
|
- duration: 100, curve: Curve.Linear,
|
|
|
|
|
- onFinish: () => {
|
|
|
|
|
- console.info('move play end')
|
|
|
|
|
- // 购物车图标抖动动效;
|
|
|
|
|
- // this.animationImageShake();
|
|
|
|
|
- }
|
|
|
|
|
- }, () => {
|
|
|
|
|
- this.toggle = !this.toggle // 通过this.toggle变化组件的位置
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ @Builder
|
|
|
|
|
+ ageSelect(){
|
|
|
|
|
+ Column({space: 17}){
|
|
|
|
|
+ ForEach(['0-2岁', '3-6岁', '7-10岁', '10岁+'], (item: string, index) => {
|
|
|
|
|
+ Text(item)
|
|
|
|
|
+ .attributeModifier(new CustomTextStyle({size: 14, weight: 600}))
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ .margin(-4)
|
|
|
|
|
+ .borderRadius(20)
|
|
|
|
|
+ .border({width: 2, color: '#FF000000'})
|
|
|
|
|
+ .padding({left: 32, right: 32, top: 19, bottom: 19})
|
|
|
|
|
+ .onDisAppear(() => { this.vm.openAgeDialog = false })
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|