import { Component, NodePool, Prefab, Tween, UIOpacity, UITransform, _decorator, instantiate, tween, view } from 'cc'; import UIMgrToastCell from './UIMgrToastCell'; const { property, ccclass, requireComponent } = _decorator; @ccclass('UIMgrToast') @requireComponent(UITransform) export default class UIMgrToast extends Component { @property(Prefab) private cell: Prefab = null; /**每条信息显示几秒 */ private lifeTime = 2; /**消失时花费几秒渐隐 */ private outTime = 0.2; /**挤压基础速度 */ private squeezeSpeed = 200; /**节点缓存池子 */ private pool = new NodePool(); add(data: { message: string, timeout?: number }) { const cell = this.pool.get() || instantiate(this.cell); cell.setPosition(0, 0, 0); cell.parent = this.node; cell.active = true; cell.getComponent(UIMgrToastCell).init(data.message); cell.getComponent(UIOpacity).opacity = 255; tween(cell.getComponent(UIOpacity)) .delay(data.timeout || this.lifeTime) .to(this.outTime, { opacity: 0 }) .call(() => { this.pool.put(cell); }) .start(); } clear() { const children = this.node.children; for (let index = children.length - 1; index >= 0; index--) { Tween.stopAllByTarget(children[index].getComponent(UIOpacity)); children[index].destroy(); } } get size() { return this.node.children.length; } protected onDestroy() { this.pool.clear(); } protected update(dt: number) { const children = this.node.children; for (let index = children.length - 1, recovery = false; index >= 0; index--) { const zero = index === children.length - 1; const curr = children[index]; // 直接触发回收逻辑 if (recovery) { Tween.stopAllByTarget(curr.getComponent(UIOpacity)); this.pool.put(curr); continue; } if (zero) { const currUT = curr.getComponent(UITransform); const lastMaxY = 0 - currUT.height / 2; const currMinY = curr.position.y + lastMaxY; if (currMinY > lastMaxY) { // 存在空隙 const addLen = Math.max(-this.squeezeSpeed * dt * (children.length - index), lastMaxY - currMinY); curr.setPosition(curr.position.x, curr.position.y + addLen, curr.position.z); } } else { const last = children[index + 1]; const currUT = curr.getComponent(UITransform); const lastUT = last.getComponent(UITransform); const currMinY = curr.position.y - currUT.height / 2 - 6;//6像素的间隔 const lastMaxY = last.position.y + lastUT.height / 2; if (currMinY < lastMaxY) { // 存在重叠 const addLen = Math.min(this.squeezeSpeed * dt * (children.length - index - 1), lastMaxY - currMinY); curr.setPosition(curr.position.x, curr.position.y + addLen, curr.position.z); const winSize = view.getVisibleSize(); if (currMinY > winSize.height / 2) { // 触发回收逻辑 recovery = true; Tween.stopAllByTarget(curr.getComponent(UIOpacity)); this.pool.put(curr); } } else if (currMinY > lastMaxY) { // 存在空隙 const addLen = Math.max(-this.squeezeSpeed * dt * (children.length - index), lastMaxY - currMinY); curr.setPosition(curr.position.x, curr.position.y + addLen, curr.position.z); } } } } }