feat(英雄列表): 添加轮播动画效果以提升用户体验
- 新增两个英雄图标节点用于扩展轮播视图 - 实现平滑的轮播动画,点击前后按钮时图标会滑动切换 - 添加动画状态锁防止动画冲突 - 重构英雄信息更新逻辑,支持五节点轮播布局 - 使用tween实现位置动画,优化视觉流畅度
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
import { _decorator, Animation, AnimationClip, Button, Event, Label, Node, NodeEventType, Sprite, resources } from "cc";
|
||||
import { _decorator, Animation, AnimationClip, Button, Event, Label, Node, NodeEventType, Sprite, resources, tween, Vec3 } from "cc";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
import { HeroInfo, HeroList } from "../common/config/heroSet";
|
||||
@@ -19,6 +19,10 @@ export class HListComp extends CCComp {
|
||||
@property(Node)
|
||||
nhero_icon=null!
|
||||
@property(Node)
|
||||
phero1_icon=null!
|
||||
@property(Node)
|
||||
nhero1_icon=null!
|
||||
@property(Node)
|
||||
ap_node=null!
|
||||
@property(Node)
|
||||
hp_node=null!
|
||||
@@ -35,6 +39,9 @@ export class HListComp extends CCComp {
|
||||
huuid:number=null!
|
||||
private currentIndex: number = 0;
|
||||
private iconVisualTokens: Map<Node, number> = new Map();
|
||||
private isAnimating: boolean = false;
|
||||
private carouselNodes: Node[] = [];
|
||||
private fixedPositions: Vec3[] = [];
|
||||
debugMode: boolean = false;
|
||||
|
||||
onLoad() {
|
||||
@@ -43,49 +50,96 @@ export class HListComp extends CCComp {
|
||||
}
|
||||
|
||||
start() {
|
||||
if (this.phero1_icon && this.phero_icon && this.hero_icon && this.nhero_icon && this.nhero1_icon) {
|
||||
this.carouselNodes = [this.phero1_icon, this.phero_icon, this.hero_icon, this.nhero_icon, this.nhero1_icon];
|
||||
this.fixedPositions = this.carouselNodes.map(n => n.position.clone());
|
||||
}
|
||||
|
||||
if (HeroList && HeroList.length > 0) {
|
||||
this.currentIndex = 0;
|
||||
this.updateHeroView();
|
||||
this.initAllNodes();
|
||||
this.updateHeroInfo();
|
||||
}
|
||||
}
|
||||
|
||||
private onPreClick() {
|
||||
if (!HeroList || HeroList.length === 0) return;
|
||||
if (!HeroList || HeroList.length === 0 || this.isAnimating || this.carouselNodes.length < 5) return;
|
||||
this.isAnimating = true;
|
||||
|
||||
this.currentIndex = (this.currentIndex - 1 + HeroList.length) % HeroList.length;
|
||||
this.updateHeroView();
|
||||
|
||||
const [n0, n1, n2, n3, n4] = this.carouselNodes;
|
||||
|
||||
// n4 instantly jumps from rightmost to leftmost position to get ready to slide in
|
||||
n4.setPosition(new Vec3(this.fixedPositions[0].x, n4.position.y, n4.position.z));
|
||||
this.updateNodeAnimationByOffset(n4, -2);
|
||||
this.updateHeroInfo();
|
||||
|
||||
tween(n0).to(0.2, { position: new Vec3(this.fixedPositions[1].x, n0.position.y, n0.position.z) }).start();
|
||||
tween(n1).to(0.2, { position: new Vec3(this.fixedPositions[2].x, n1.position.y, n1.position.z) }).start();
|
||||
tween(n2).to(0.2, { position: new Vec3(this.fixedPositions[3].x, n2.position.y, n2.position.z) }).start();
|
||||
tween(n3).to(0.2, { position: new Vec3(this.fixedPositions[4].x, n3.position.y, n3.position.z) })
|
||||
.call(() => {
|
||||
this.carouselNodes = [n4, n0, n1, n2, n3];
|
||||
this.isAnimating = false;
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
private onNextClick() {
|
||||
if (!HeroList || HeroList.length === 0) return;
|
||||
if (!HeroList || HeroList.length === 0 || this.isAnimating || this.carouselNodes.length < 5) return;
|
||||
this.isAnimating = true;
|
||||
|
||||
this.currentIndex = (this.currentIndex + 1) % HeroList.length;
|
||||
this.updateHeroView();
|
||||
|
||||
const [n0, n1, n2, n3, n4] = this.carouselNodes;
|
||||
|
||||
// n0 instantly jumps from leftmost to rightmost position to get ready to slide in
|
||||
n0.setPosition(new Vec3(this.fixedPositions[4].x, n0.position.y, n0.position.z));
|
||||
this.updateNodeAnimationByOffset(n0, 2);
|
||||
this.updateHeroInfo();
|
||||
|
||||
tween(n1).to(0.2, { position: new Vec3(this.fixedPositions[0].x, n1.position.y, n1.position.z) }).start();
|
||||
tween(n2).to(0.2, { position: new Vec3(this.fixedPositions[1].x, n2.position.y, n2.position.z) }).start();
|
||||
tween(n3).to(0.2, { position: new Vec3(this.fixedPositions[2].x, n3.position.y, n3.position.z) }).start();
|
||||
tween(n4).to(0.2, { position: new Vec3(this.fixedPositions[3].x, n4.position.y, n4.position.z) })
|
||||
.call(() => {
|
||||
this.carouselNodes = [n1, n2, n3, n4, n0];
|
||||
this.isAnimating = false;
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
private updateHeroView() {
|
||||
this.huuid = HeroList[this.currentIndex];
|
||||
private getHeroUuid(offset: number): number {
|
||||
const len = HeroList.length;
|
||||
return HeroList[(this.currentIndex + offset + len * 5) % len];
|
||||
}
|
||||
|
||||
private updateNodeAnimationByOffset(node: Node, offset: number) {
|
||||
const uuid = this.getHeroUuid(offset);
|
||||
this.updateHeroAnimation(node, uuid);
|
||||
}
|
||||
|
||||
private updateHeroInfo() {
|
||||
this.huuid = this.getHeroUuid(0);
|
||||
const hero = HeroInfo[this.huuid];
|
||||
if (!hero) return;
|
||||
|
||||
// 获取前后英雄的 uuid
|
||||
const preIndex = (this.currentIndex - 1 + HeroList.length) % HeroList.length;
|
||||
const nextIndex = (this.currentIndex + 1) % HeroList.length;
|
||||
const pUuid = HeroList[preIndex];
|
||||
const nUuid = HeroList[nextIndex];
|
||||
|
||||
// 更新基础属性标签
|
||||
this.setLabelText(this.name_node, hero.name);
|
||||
this.setLabelText(this.ap_node, `攻击力: ${hero.ap}`);
|
||||
this.setLabelText(this.hp_node, `生命值: ${hero.hp}`);
|
||||
|
||||
// 更新动画
|
||||
this.updateHeroAnimation(this.hero_icon, this.huuid);
|
||||
this.updateHeroAnimation(this.phero_icon, pUuid);
|
||||
this.updateHeroAnimation(this.nhero_icon, nUuid);
|
||||
|
||||
// 更新技能列表
|
||||
this.updateSkillInfo(hero);
|
||||
}
|
||||
|
||||
private initAllNodes() {
|
||||
if (this.carouselNodes.length < 5) return;
|
||||
this.updateNodeAnimationByOffset(this.carouselNodes[0], -2);
|
||||
this.updateNodeAnimationByOffset(this.carouselNodes[1], -1);
|
||||
this.updateNodeAnimationByOffset(this.carouselNodes[2], 0);
|
||||
this.updateNodeAnimationByOffset(this.carouselNodes[3], 1);
|
||||
this.updateNodeAnimationByOffset(this.carouselNodes[4], 2);
|
||||
}
|
||||
|
||||
private setLabelText(node: Node, text: string) {
|
||||
if (!node) return;
|
||||
const label = node.getComponent(Label) || node.getComponentInChildren(Label);
|
||||
|
||||
Reference in New Issue
Block a user