Egret旋转加载进度条

先上一张效果图
这里写图片描述
然后是LoadingUI里的代码

class LoadingUI extends egret.Sprite implements RES.PromiseTaskReporter {

    public constructor() {
        super();
        this.createView();
    }

    private bg1:egret.Bitmap;
    private bg2:egret.Bitmap;
    private loadingicon:egret.Bitmap;
    private bitmapText :egret.BitmapText;
    private createView(): void {
        // 加载loadingBg图
        let loadingbg:egret.Bitmap = new egret.Bitmap()
        loadingbg.texture = RES.getRes("loading_bg_jpg");
        loadingbg.width = 640 ;
        loadingbg.height = 1136 ;
        this.addChild(loadingbg);

        this.bg1= new egret.Bitmap()
        this.bg1.texture = RES.getRes("loading_json.loading_bar1_png");
        this.bg1.anchorOffsetX = this.bg1.width /
<think>我们正在使用EgretWing(一个基于TypeScript的游戏开发框架)实现一个进度条动画。目标:确保进度条匀速平滑增长,用户无法察觉停顿。 关键点: 1. 使用动画来更新进度条的宽度(或类似属性)从0%到100%。 2. 动画需要是线性的(匀速),所以我们需要使用线性插值器(interpolator)。 3. 在Egret中,我们可以使用egret.Tween来实现动画。 步骤: a. 创建进度条(通常是一个矩形图形,我们可以用一个背景和一个前景来表示进度)。 b. 使用egret.Tween来改变前景的宽度(从0到目标宽度),并设置时间为固定值(比如1500毫秒),使用线性缓动函数。 示例代码结构: 1. 首先,创建进度条的背景和前景(例如两个矩形)。 2. 将前景添加到背景中,并设置前景的初始宽度为0。 3. 使用Tween动画改变前景的宽度。 注意:为了确保平滑,我们使用线性变化(即匀速)。 具体代码示例: 假设我们有一个进度条背景:bg,一个进度条前景:progressBar。 创建进度条: ``` let bg: egret.Shape = new egret.Shape(); bg.graphics.beginFill(0xCCCCCC); // 背景色 bg.graphics.drawRect(0, 0, 200, 20); // 背景矩形 bg.graphics.endFill(); this.addChild(bg); let progressBar: egret.Shape = new egret.Shape(); progressBar.graphics.beginFill(0x00FF00); // 进度条颜色 progressBar.graphics.drawRect(0, 0, 0, 20); // 初始宽度为0 progressBar.graphics.endFill(); this.addChild(progressBar); // 设置进度条的位置,比如在背景上 progressBar.x = bg.x; progressBar.y = bg.y; ``` 然后,使用Tween动画: ``` // 设置动画时间为1500毫秒,从0到背景的宽度(200) egret.Tween.get(progressBar) .to({ width: 200 }, 1500) .call(() => { console.log("进度条动画完成"); }); ``` 但是,上面的代码中,我们直接改变了progressBar的width属性。注意:egret.Shape的宽度改变并不会重绘图形,所以我们需要在改变宽度的同时重绘矩形?实际上,我们不应该直接改变Shape的宽度,因为Shape的绘制是在graphics中完成的。因此,我们需要换一种思路:我们可以在每一帧更新时重新绘制进度条。 更好的做法: 我们可以用一个变量表示当前进度(0-1),然后在Tween中改变这个变量,并在每一帧更新时根据这个变量重绘进度条。 步骤: 1. 创建一个表示当前进度的变量progress(0到1)。 2. 使用Tween改变progress从0到1,并设置缓动为线性。 3. 在Tween的每一帧更新中,我们根据progress重绘进度条。 代码示例: ``` class ProgressBar extends egret.DisplayObjectContainer { private bg: egret.Shape; private progressBar: egret.Shape; private maxWidth: number = 200; private height: number = 20; public constructor() { super(); this.createView(); } private createView(): void { // 背景 this.bg = new egret.Shape(); this.bg.graphics.beginFill(0xCCCCCC); this.bg.graphics.drawRect(0, 0, this.maxWidth, this.height); this.bg.graphics.endFill(); this.addChild(this.bg); this.progressBar = new egret.Shape(); this.addChild(this.progressBar); this.progressBar.x = 0; this.progressBar.y = 0; } public setProgress(progress: number): void { // 限制progress在0-1 if (progress < 0) progress = 0; if (progress > 1) progress = 1; this.progressBar.graphics.clear(); this.progressBar.graphics.beginFill(0x00FF00); this.progressBar.graphics.drawRect(0, 0, this.maxWidth * progress, this.height); this.progressBar.graphics.endFill(); } public animateTo(targetProgress: number, duration: number): void { // 当前进度,如果没有设置过,则从0开始 let currentProgress = this.progressBar.width / this.maxWidth; // 使用Tween改变progress let obj = { progress: currentProgress }; egret.Tween.get(obj) .to({ progress: targetProgress }, duration, egret.Ease.sineIn) // 这里我们使用线性缓动,但egret.Ease中没有线性?实际上有线性:使用egret.Ease.linear,或者直接使用默认的(默认是线性)?或者使用null .call(() => { console.log("动画完成"); }) .onChange(() => { this.setProgress(obj.progress); }); } } ``` 注意:在animateTo方法中,我们创建了一个对象obj来存储当前的进度值(0-1)。然后使用Tween改变这个值,并在每一帧变化时调用setProgress重绘进度条。 但是,在egret.Tween中,默认的缓动函数是线性吗?查看文档:egret.Ease.linear是线性函数。我们可以这样写: ``` egret.Tween.get(obj).to({progress: targetProgress}, duration, egret.Ease.linear) ``` 或者,如果我们不传递缓动函数,默认是线性吗?实际上,默认是quadIn(二次方缓入)。所以我们需要明确指定缓动函数为线性。 因此,修改为: ``` egret.Tween.get(obj).to({progress: targetProgress}, duration, egret.Ease.linear) ``` 使用: ``` let progressBar = new ProgressBar(); this.addChild(progressBar); progressBar.animateTo(1, 1500); // 在1.5秒内从当前进度到100% ``` 这样,进度条就会匀速增长。 另外,为了确保用户无法察觉停顿,我们需要注意: 1. 动画的帧率:Egret引擎默认帧率是60fps,所以动画会非常平滑。 2. 使用线性变化,速度恒定。 引用:在Egret中,Tween动画的使用可以参考官方文档[^1]。另外,关于进度条的绘制,我们使用了简单的图形绘制[^2]。 注意:上面的代码中,我们每次重绘都清除了graphics然后重新绘制,这样在性能上是可以接受的,因为进度条通常不会太复杂。 如果希望更高效,也可以考虑使用egret.Rect对象来改变进度条的尺寸,但是egret.Shape本身并不支持直接改变绘制的矩形大小,所以重绘是常见做法。 另一种思路:使用Bitmap(图片)作为进度条的前景,然后改变其scaleX,这样也可以实现,而且性能可能更好(因为不需要重绘)。但是要注意,如果使用scaleX,那么进度条的锚点需要设置在左边(默认是中心,所以需要设置anchorOffsetX为0,或者设置regX=0)。 使用Bitmap和scaleX的示例: 假设我们有一个进度条前景的纹理(texture),我们可以创建一个Bitmap,然后设置其锚点在左边(设置regX=0)。 ``` let progressBar: egret.Bitmap = new egret.Bitmap(); progressBar.texture = RES.getRes("progress_bar_png"); progressBar.x = 0; progressBar.y = 0; progressBar.scaleX = 0; // 初始为0 // 设置锚点在左边(默认锚点在左上角,所以scaleX从左边开始缩放) // 默认情况下,缩放是围绕锚点进行的,而锚点默认是(0,0)即左上角,所以scaleX从左边缩放是符合的。 然后动画: let obj = { scale: 0 }; egret.Tween.get(obj).to({scale:1}, 1500, egret.Ease.linear) .onChange(() => { progressBar.scaleX = obj.scale; }); ``` 这种方法避免了每一帧重绘图形,性能更好,推荐使用。 因此,我们可以结合两种方式,如果有纹理资源,使用Bitmap方式;如果没有,使用Shape重绘。 总结:在EgretWing中实现平滑匀速的进度条动画,核心是使用egret.Tween并设置线性缓动函数,然后通过改变显示对象的宽度(重绘)或缩放(scaleX)来更新进度条的显示。 相关问题: 1. 如何在Egret中创建自定义形状的进度条(例如圆环形)? 2. 如何实现带文本显示的进度条(显示百分比)? 3. 在Egret中,如何处理资源加载进度条?</think>### 在 EgretWing 中实现平滑匀速增长的进度条动画 在 EgretWing 中实现平滑匀速增长的进度条动画,核心是使用 **egret.Tween** 动画库结合线性插值器(LinearInterpolator)。以下是完整实现方案: #### 1. 创建进度条基本结构 ```typescript class SmoothProgressBar extends egret.DisplayObjectContainer { private bg: egret.Shape; // 背景 private progressBar: egret.Shape; // 进度条 private maxWidth: number = 300; // 最大宽度 public constructor() { super(); this.createView(); } private createView(): void { // 创建背景 this.bg = new egret.Shape(); this.bg.graphics.beginFill(0xCCCCCC); this.bg.graphics.drawRect(0, 0, this.maxWidth, 20); this.bg.graphics.endFill(); this.addChild(this.bg); // 创建进度条 this.progressBar = new egret.Shape(); this.progressBar.graphics.beginFill(0x00FF00); // 绿色进度条 this.progressBar.graphics.drawRect(0, 0, 0, 20); // 初始宽度0 this.progressBar.graphics.endFill(); this.addChild(this.progressBar); } } ``` #### 2. 实现匀速动画方法 ```typescript public startProgress(duration: number = 1500): void { // 重置进度条 this.progressBar.width = 0; // 创建动画对象 const targetProps = { width: this.maxWidth }; // 使用线性插值器确保匀速 egret.Tween.get(this.progressBar) .to(targetProps, duration, egret.Ease.linear) // 关键:线性缓动 .call(() => { console.log("进度条动画完成"); }); } ``` #### 3. 使用示例 ```typescript // 在场景中使用 const progressBar = new SmoothProgressBar(); progressBar.x = 50; progressBar.y = 100; this.addChild(progressBar); // 启动匀速动画(1.5秒完成) progressBar.startProgress(1500); ``` ### 关键实现原理 1. **线性插值器** 通过 `egret.Ease.linear` 确保进度条宽度随时间**均匀增加**,消除任何加速/减速效果: $$ \text{width}(t) = \text{startWidth} + (\text{endWidth} - \text{startWidth}) \times \frac{t}{\text{duration}} $$ 2. **性能优化** - 使用 `egret.Shape` 替代 `Bitmap` 减少内存占用 - 避免在动画过程中重绘图形(仅修改宽度属性) 3. **平滑性保障** Egret 引擎默认以 60FPS 运行动画,结合线性插值可确保肉眼无法察觉帧率波动[^1]。 ### 进阶优化建议 1. **添加进度文本** ```typescript // 在类中添加 private progressText: egret.TextField; // 在动画中更新 .onChange(() => { const percent = Math.floor((this.progressBar.width / this.maxWidth) * 100); this.progressText.text = `${percent}%`; }) ``` 2. **支持颜色渐变** 使用 `Graphics` 的 `lineGradientStyle` 实现渐变效果: ```typescript this.progressBar.graphics.lineGradientStyle( egret.GradientType.LINEAR, [0x00FF00, 0xFFFF00], // 绿到黄渐变 [1, 1], [0, 255] ); ``` 3. **暂停/继续控制** ```typescript private currentTween: egret.Tween; public pause(): void { egret.Tween.pauseTweens(this.progressBar); } public resume(): void { egret.Tween.resumeTweens(this.progressBar); } ``` ### 实际应用场景 此方案适用于: - 游戏资源加载进度显示 - 任务处理进度反馈 - 数据上传/下载进度展示 - 用户操作等待指示器 通过线性缓动函数和精确的宽度计算,可确保进度条以恒定速度增长,避免用户感知到卡顿[^2]。 --- ### 相关问题 1. 如何在 Egret 中实现非线性进度的进度条(如先快后慢)? 2. 进度条动画如何与资源加载实际进度同步? 3. 在 Egret 中如何创建圆形/环形的进度条? 4. 多段颜色进度条(如 0-70%绿色,70-100%红色)如何实现? 5. 如何为进度条添加"缓冲动画"效果(如网络下载中的二次进度)? [^1]: 线性插值器确保动画匀速执行,避免用户感知到卡顿,参考动画平滑性实现原理。 [^2]: 通过精确控制每一帧的宽度增量,消除进度跳跃现象,参考游戏动画设计最佳实践。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值