import { _decorator, CCFloat, Component, geometry, Label, tween, Vec3 } from 'cc'; const { ccclass, property } = _decorator; @ccclass('FloatingText') export class FloatingText extends Component { @property({ type: Label, visible: true }) private _label: Label; @property({ type: CCFloat, visible: true }) private _moveSpeed = 1; @property({ type: geometry.AnimationCurve, visible: true }) private _animationCurve: geometry.AnimationCurve = new geometry.AnimationCurve(); private readonly _scaleUpDuration = 0.2; private readonly _scaleDownDuration = 0.2; private _moveDuration = 0; public show(text: string, position: Vec3, scale = 1, duration = 1) { if (duration < this._scaleUpDuration + this._scaleDownDuration) { console.warn( `show duration time of floating text must be greater than ${this._scaleUpDuration + this._scaleDownDuration}`, ); duration = this._scaleUpDuration + this._scaleDownDuration + 0.5; } this._moveDuration = duration - (this._scaleUpDuration + this._scaleDownDuration); this.node.setWorldPosition(position); this.node.setScale(Vec3.ZERO); this._label.string = text; tween(this.node) .to(this._scaleUpDuration, { scale: new Vec3(scale, scale, 1) }, { easing: 'backOut' }) .by( this._moveDuration, { worldPosition: new Vec3(0, 1 * this._moveSpeed, 10), }, { easing: (k) => { return this._animationCurve.evaluate(k); }, }, ) .to( this._scaleDownDuration, { scale: Vec3.ZERO, }, { easing: 'backIn' }, ) .start(); } }