feat(card): 添加长按放大功能并调整卡牌布局

- 在 CardComp 中实现长按触发卡牌放大,优化触摸交互逻辑
- 调整 MissionCardComp 中卡牌位置数组顺序,修复布局错位
- 修改 card.prefab 中多个 UI 元素的坐标和对齐方式,优化视觉呈现
- 移除卡牌种类标识的显示逻辑,简化卡牌 UI
This commit is contained in:
walkpan
2026-04-20 23:59:38 +08:00
parent 033fd44560
commit 0829b0bc9d
3 changed files with 135 additions and 29 deletions

View File

@@ -3044,7 +3044,7 @@
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": 0, "x": 0,
"y": -71.448, "y": 70,
"z": 0 "z": 0
}, },
"_lrot": { "_lrot": {
@@ -3178,11 +3178,11 @@
"__prefab": { "__prefab": {
"__id__": 138 "__id__": 138
}, },
"_alignFlags": 16, "_alignFlags": 17,
"_target": null, "_target": null,
"_left": 0, "_left": 0,
"_right": 0, "_right": 0,
"_top": 163.951, "_top": 30,
"_bottom": 0, "_bottom": 0,
"_horizontalCenter": 0, "_horizontalCenter": 0,
"_verticalCenter": 0, "_verticalCenter": 0,
@@ -5982,8 +5982,8 @@
}, },
"_lpos": { "_lpos": {
"__type__": "cc.Vec3", "__type__": "cc.Vec3",
"x": -70.639, "x": 0,
"y": 96.745, "y": -101.274,
"z": 0 "z": 0
}, },
"_lrot": { "_lrot": {
@@ -6389,12 +6389,12 @@
"__prefab": { "__prefab": {
"__id__": 283 "__id__": 283
}, },
"_alignFlags": 9, "_alignFlags": 20,
"_target": null, "_target": null,
"_left": -5.638999999999996, "_left": -5.638999999999996,
"_right": 0, "_right": 0,
"_top": -1.7450000000000045, "_top": 196.274,
"_bottom": 0, "_bottom": -6.274000000000001,
"_horizontalCenter": 0, "_horizontalCenter": 0,
"_verticalCenter": 0, "_verticalCenter": 0,
"_isAbsLeft": true, "_isAbsLeft": true,
@@ -8440,7 +8440,7 @@
"__id__": 390 "__id__": 390
} }
], ],
"_active": true, "_active": false,
"_components": [ "_components": [
{ {
"__id__": 396 "__id__": 396

View File

@@ -123,6 +123,12 @@ export class CardComp extends CCComp {
private iconVisualToken: number = 0; private iconVisualToken: number = 0;
/** 是否处于放大状态 */ /** 是否处于放大状态 */
private isEnlarged: boolean = false; private isEnlarged: boolean = false;
/** 长按定时器标记 */
private longPressTimer: any = null;
/** 是否触发了长按 */
private isLongPressed: boolean = false;
/** 长按触发时间(秒) */
private readonly LONG_PRESS_DURATION: number = 0.5;
// ======================== 生命周期 ======================== // ======================== 生命周期 ========================
@@ -502,6 +508,20 @@ export class CardComp extends CCComp {
if (!this.cardData || this.isUsing) return; if (!this.cardData || this.isUsing) return;
this.touchStartY = event.getUILocation().y; this.touchStartY = event.getUILocation().y;
this.isDragging = true; this.isDragging = true;
this.isLongPressed = false;
// 开启长按定时器
this.unschedule(this.onLongPress);
this.scheduleOnce(this.onLongPress, this.LONG_PRESS_DURATION);
}
/** 长按触发逻辑 */
private onLongPress() {
if (!this.isDragging || this.isUsing) return;
this.isLongPressed = true;
this.isEnlarged = true;
this.applyCardUI();
this.playReboundAnim();
} }
/** /**
@@ -512,6 +532,15 @@ export class CardComp extends CCComp {
const currentY = event.getUILocation().y; const currentY = event.getUILocation().y;
const deltaY = Math.max(0, currentY - this.touchStartY); const deltaY = Math.max(0, currentY - this.touchStartY);
// 拖拽距离超过一定阈值,取消长按
if (deltaY > 10) {
this.unschedule(this.onLongPress);
if (this.isLongPressed && !this.isEnlarged) {
// 如果已经触发了长按但想取消放大(比如拖拽时恢复),视情况处理
// 这里我们认为一旦拖动就取消未触发的长按,如果已经触发放大则保持放大直到松手
}
}
let baseX = this.restPosition.x; let baseX = this.restPosition.x;
let baseY = this.restPosition.y; let baseY = this.restPosition.y;
if (this.isEnlarged) { if (this.isEnlarged) {
@@ -529,31 +558,45 @@ export class CardComp extends CCComp {
/** /**
* 触摸结束: * 触摸结束:
* - 上拉距离 >= dragUseThreshold → 视为"使用卡牌" * - 上拉距离 >= dragUseThreshold → 视为"使用卡牌"
* - 否则视为"点击",切换放大缩小状态并回弹 * - 否则视为"点击"或者"长按结束"
*/ */
private onCardTouchEnd(event: EventTouch) { private onCardTouchEnd(event: EventTouch) {
this.unschedule(this.onLongPress);
if (!this.isDragging || !this.cardData || this.isUsing) return; if (!this.isDragging || !this.cardData || this.isUsing) return;
const endY = event.getUILocation().y; const endY = event.getUILocation().y;
const deltaY = endY - this.touchStartY; const deltaY = endY - this.touchStartY;
this.isDragging = false; this.isDragging = false;
if (deltaY >= this.dragUseThreshold) { if (deltaY >= this.dragUseThreshold) {
this.useCard(); this.useCard();
// 使用卡牌后恢复非放大状态
this.isEnlarged = false;
this.isLongPressed = false;
return; return;
} }
this.toggleEnlarge();
this.playReboundAnim(); // 无论是点击还是长按松手,都恢复正常大小
if (this.isEnlarged) {
this.isEnlarged = false;
this.applyCardUI();
} }
/** 切换卡牌的放大/缩小状态 */ this.isLongPressed = false;
private toggleEnlarge() { this.playReboundAnim();
this.isEnlarged = !this.isEnlarged;
this.applyCardUI();
} }
/** 触摸取消:回弹至原位 */ /** 触摸取消:回弹至原位 */
private onCardTouchCancel() { private onCardTouchCancel() {
this.unschedule(this.onLongPress);
if (!this.isDragging || this.isUsing) return; if (!this.isDragging || this.isUsing) return;
this.isDragging = false; this.isDragging = false;
if (this.isEnlarged) {
this.isEnlarged = false;
this.applyCardUI();
}
this.isLongPressed = false;
this.playReboundAnim(); this.playReboundAnim();
} }
@@ -619,12 +662,12 @@ export class CardComp extends CCComp {
this.node.setPosition(targetX, targetY, this.restPosition.z); this.node.setPosition(targetX, targetY, this.restPosition.z);
// ---- 卡牌种类标识(近战 / 远程 / 辅助等) ---- // ---- 卡牌种类标识(近战 / 远程 / 辅助等) ----
if (this.Ckind_node) { // if (this.Ckind_node) {
const kindName = CKind[this.cardData.kind]; // const kindName = CKind[this.cardData.kind];
this.Ckind_node.children.forEach(child => { // this.Ckind_node.children.forEach(child => {
child.active = (child.name === kindName); // child.active = (child.name === kindName);
}); // });
} // }
// ---- 背景底框(按卡池等级显示对应子节点) ---- // ---- 背景底框(按卡池等级显示对应子节点) ----
const cardLvStr = `lv${this.cardData.pool_lv}`; const cardLvStr = `lv${this.cardData.pool_lv}`;
@@ -654,6 +697,40 @@ export class CardComp extends CCComp {
uiTrans.setContentSize(this.isEnlarged ? 230 : 170, this.isEnlarged ? 300 : 230); uiTrans.setContentSize(this.isEnlarged ? 230 : 170, this.isEnlarged ? 300 : 230);
} }
// 同时修改背景节点和边框节点的尺寸
if (this.BG_node) {
const bgTrans = this.BG_node.getComponent(UITransform);
if (bgTrans) bgTrans.setContentSize(this.isEnlarged ? 230 : 170, this.isEnlarged ? 300 : 230);
this.BG_node.children.forEach(child => {
const childTrans = child.getComponent(UITransform);
if (childTrans) childTrans.setContentSize(this.isEnlarged ? 230 : 170, this.isEnlarged ? 300 : 230);
});
}
if (this.HF_node) {
const hfTrans = this.HF_node.getComponent(UITransform);
if (hfTrans) hfTrans.setContentSize(this.isEnlarged ? 230 : 170, this.isEnlarged ? 300 : 230);
this.HF_node.children.forEach(child => {
const childTrans = child.getComponent(UITransform);
if (childTrans) childTrans.setContentSize(this.isEnlarged ? 230 : 170, this.isEnlarged ? 300 : 230);
});
}
if (this.NF_node) {
const nfTrans = this.NF_node.getComponent(UITransform);
if (nfTrans) nfTrans.setContentSize(this.isEnlarged ? 230 : 170, this.isEnlarged ? 300 : 230);
this.NF_node.children.forEach(child => {
const childTrans = child.getComponent(UITransform);
if (childTrans) childTrans.setContentSize(this.isEnlarged ? 230 : 170, this.isEnlarged ? 300 : 230);
});
}
const hbNode = this.node.getChildByName("HB");
if (hbNode) {
const hbTrans = hbNode.getComponent(UITransform);
if (hbTrans) hbTrans.setContentSize(this.isEnlarged ? 230 : 170, this.isEnlarged ? 300 : 230);
}
if(this.card_type===CardType.Hero){ if(this.card_type===CardType.Hero){
// 英雄卡:显示英雄名 + 星级 + AP/HP // 英雄卡:显示英雄名 + 星级 + AP/HP
const hero = HeroInfo[this.card_uuid]; const hero = HeroInfo[this.card_uuid];
@@ -801,16 +878,45 @@ export class CardComp extends CCComp {
if (uiTrans) { if (uiTrans) {
uiTrans.setContentSize(170, 230); uiTrans.setContentSize(170, 230);
} }
if (this.BG_node) {
const bgTrans = this.BG_node.getComponent(UITransform);
if (bgTrans) bgTrans.setContentSize(170, 230);
this.BG_node.children.forEach(child => {
const childTrans = child.getComponent(UITransform);
if (childTrans) childTrans.setContentSize(170, 230);
});
}
if (this.HF_node) {
const hfTrans = this.HF_node.getComponent(UITransform);
if (hfTrans) hfTrans.setContentSize(170, 230);
this.HF_node.children.forEach(child => {
const childTrans = child.getComponent(UITransform);
if (childTrans) childTrans.setContentSize(170, 230);
});
}
if (this.NF_node) {
const nfTrans = this.NF_node.getComponent(UITransform);
if (nfTrans) nfTrans.setContentSize(170, 230);
this.NF_node.children.forEach(child => {
const childTrans = child.getComponent(UITransform);
if (childTrans) childTrans.setContentSize(170, 230);
});
}
const hbNode = this.node.getChildByName("HB");
if (hbNode) {
const hbTrans = hbNode.getComponent(UITransform);
if (hbTrans) hbTrans.setContentSize(170, 230);
}
this.iconVisualToken += 1; this.iconVisualToken += 1;
this.setLabel(this.name_node, ""); this.setLabel(this.name_node, "");
this.setLabel(this.cost_node, ""); this.setLabel(this.cost_node, "");
if (this.info_node) this.info_node.active = false; if (this.info_node) this.info_node.active = false;
if (this.oinfo_node) this.oinfo_node.active = false; if (this.oinfo_node) this.oinfo_node.active = false;
if (this.Ckind_node) { // if (this.Ckind_node) {
this.Ckind_node.children.forEach(child => { // this.Ckind_node.children.forEach(child => {
child.active = false; // child.active = false;
}); // });
} // }
if (this.BG_node) { if (this.BG_node) {
this.BG_node.children.forEach(child => child.active = false); this.BG_node.children.forEach(child => child.active = false);
} }

View File

@@ -138,7 +138,7 @@ export class MissionCardComp extends CCComp {
/** 卡牌面板收起态缩放scale=0 隐藏) */ /** 卡牌面板收起态缩放scale=0 隐藏) */
private cardsHideScale: Vec3 = new Vec3(0, 0, 1); private cardsHideScale: Vec3 = new Vec3(0, 0, 1);
/** 卡牌原始定位点 */ /** 卡牌原始定位点 */
private cardsPos = [-260,86,-86,260] private cardsPos = [-260,-86,86,260]
/** /**
* 英雄信息面板映射EID → { node, model, comp } * 英雄信息面板映射EID → { node, model, comp }
* 用于追踪每个出战英雄的面板实例和数据引用 * 用于追踪每个出战英雄的面板实例和数据引用