list注释优化

This commit is contained in:
yhh
2023-03-13 22:17:11 +08:00
parent 1adc5f1729
commit 323fb6a5fe
12 changed files with 1896 additions and 608 deletions

View File

@@ -77,6 +77,7 @@ v10.20.1
1. 进入source目录
2. 安装package包: `npm install`
3. 打包成js: `gulp build`
> 如遇到gulp未找到则先执行 `npm install gulp -g`
### 渲染集成框架
#### [cocos-framework](https://github.com/esengine/cocos-framework)

View File

@@ -4092,11 +4092,14 @@ declare module es {
}
declare module es {
/**
* AbstractTweenable作为你可能想做的任何可以执行的自定义类的基础
* 这些类不同于ITweens因为他们没有实现ITweenT接口。
* 它只是说一个AbstractTweenable不仅仅是将一个值从开始移动到结束
* 它可以做任何需要每帧执行的事情
*/
* `AbstractTweenable` 是一个抽象类,实现了 `ITweenable` 接口
* 这个类提供了 `start`、`pause`、`resume` 和 `stop` 等方法,
* 并且具有判断动画是否运行的方法 `isRunning`
* 它还有一个 `tick` 方法,子类需要根据自己的需要实现这个方法
*
* `AbstractTweenable` 在完成后往往会被保留下来, `_isCurrentlyManagedByTweenManager` 标志可以让它们知道自己当前是否被 `TweenManager` 监控着,
* 以便在必要时可以重新添加自己。
*/
abstract class AbstractTweenable implements ITweenable {
readonly discriminator: string;
protected _isPaused: boolean;
@@ -4115,9 +4118,26 @@ declare module es {
}
}
declare module es {
/**
* 属性动画工具类
*/
class PropertyTweens {
/**
* 创建一个属性为number类型的动画对象
* @param self 属性动画的目标对象
* @param memberName 属性名
* @param to 动画结束时的属性值
* @param duration 动画时长
*/
static NumberPropertyTo(self: any, memberName: string, to: number, duration: number): ITween<number>;
static Vector2PropertyTo(self: any, memeberName: string, to: Vector2, duration: number): ITween<Vector2>;
/**
* 创建一个属性为Vector2类型的动画对象
* @param self 属性动画的目标对象
* @param memberName 属性名
* @param to 动画结束时的属性值
* @param duration 动画时长
*/
static Vector2PropertyTo(self: any, memberName: string, to: Vector2, duration: number): ITween<Vector2>;
}
}
declare module es {
@@ -4201,6 +4221,10 @@ declare module es {
setContext(context: any): ITween<T>;
setNextTween(nextTween: ITweenable): ITween<T>;
tick(): boolean;
private calculateElapsedTimeExcess;
private calculateDeltaTime;
private updateElapsedTime;
private handleCompletion;
recycleSelf(): void;
isRunning(): boolean;
start(): void;
@@ -4326,8 +4350,9 @@ declare module es {
*/
class EaseHelper {
/**
* 返回 easeType 的相反 EaseType
* @param easeType
* 返回相反的缓动类型
* @param easeType 缓动类型
* @returns 返回相反的缓动类型
*/
static oppositeEaseType(easeType: EaseType): EaseType.linear | EaseType.sineIn | EaseType.sineOut | EaseType.sineInOut | EaseType.quadIn | EaseType.quadOut | EaseType.quadInOut | EaseType.quintIn | EaseType.quintOut | EaseType.quintInOut | EaseType.cubicIn | EaseType.cubicOut | EaseType.cubicInOut | EaseType.quartIn | EaseType.quartInOut | EaseType.expoIn | EaseType.expoOut | EaseType.expoInOut | EaseType.circleIn | EaseType.circleOut | EaseType.circleInOut | EaseType.elasticIn | EaseType.elasticOut | EaseType.elasticInOut | EaseType.punch | EaseType.backIn | EaseType.backOut | EaseType.backInOut | EaseType.bounceIn | EaseType.bounceOut | EaseType.bounceInOut;
static ease(easeType: EaseType, t: number, duration: number): number;
@@ -4387,13 +4412,7 @@ declare module es {
private _activeTweens;
static readonly activeTweens: ITweenable[];
private _tempTweens;
/**
* 标志表示tween更新循环正在运行
*/
private _isUpdating;
/**
* 便于暴露一个静态的API以方便访问
*/
private static _instance;
constructor();
update(): void;
@@ -4451,57 +4470,251 @@ declare module es {
*/
module Easing {
class Linear {
/**
* 线性缓动等同于t / d
* @param t 当前时间
* @param d 持续时间
*/
static easeNone(t: number, d: number): number;
}
class Quadratic {
/**
* 平方缓动进入,加速运动
* @param t 当前时间
* @param d 持续时间
*/
static easeIn(t: number, d: number): number;
/**
* 平方缓动退出,减速运动
* @param t 当前时间
* @param d 持续时间
*/
static easeOut(t: number, d: number): number;
/**
* 平方缓动进出,加速减速运动
* @param t 当前时间
* @param d 持续时间
*/
static easeInOut(t: number, d: number): number;
}
class Back {
static easeIn(t: number, d: number): number;
static easeOut(t: number, d: number): number;
static easeInOut(t: number, d: number): number;
/**
* Back.easeIn(t, d) 函数将会返回 Back 缓动进入算法的结果
*
* @param t 当前时间从0开始递增
* @param d 持续时间
* @param s 回弹的距离,默认值为 1.70158,可以省略该参数
* @return 缓动后的值
*/
static easeIn(t: number, d: number, s?: number): number;
/**
* Back.easeOut(t, d) 函数将会返回 Back 缓动退出算法的结果
*
* @param t 当前时间从0开始递增
* @param d 持续时间
* @param s 回弹的距离,默认值为 1.70158,可以省略该参数
* @return 缓动后的值
*/
static easeOut(t: number, d: number, s?: number): number;
/**
* Back.easeInOut(t, d) 函数将会返回 Back 缓动进入/退出算法的结果
*
* @param t 当前时间从0开始递增
* @param d 持续时间
* @param s 回弹的距离,默认值为 1.70158,可以省略该参数
* @return 缓动后的值
*/
static easeInOut(t: number, d: number, s?: number): number;
}
class Bounce {
/**
* 从0到目标值的反弹动画
* @param t 当前时间
* @param d 持续时间
* @returns 反弹动画进度
*/
static easeOut(t: number, d: number): number;
/**
* 从目标值到0的反弹动画
* @param t 当前时间
* @param d 持续时间
* @returns 反弹动画进度
*/
static easeIn(t: number, d: number): number;
/**
* 从0到目标值再到0的反弹动画
* @param t 当前时间
* @param d 持续时间
* @returns 反弹动画进度
*/
static easeInOut(t: number, d: number): number;
}
class Circular {
/**
* 缓动函数入口,表示从 0 到最大值的缓动(开始慢加速,后面变快)
* @param t 当前时间
* @param d 缓动总时间
*/
static easeIn(t: number, d: number): number;
/**
* 缓动函数出口,表示从最大值到 0 的缓动(开始快减速,后面变慢)
* @param t 当前时间
* @param d 缓动总时间
*/
static easeOut(t: number, d: number): number;
/**
* 缓动函数入口和出口,表示从 0 到最大值再到 0 的缓动(先慢加速,后面快减速)
* @param t 当前时间
* @param d 缓动总时间
*/
static easeInOut(t: number, d: number): number;
}
class Cubic {
/**
* easeIn方法提供了一个以慢速开始然后逐渐加速的缓动函数。
* @param t 当前时间动画已经持续的时间范围在0到d之间其中d是动画的总时间。
* @param d 动画的总时间,即动画将从开始到结束的持续时间。
* @returns 根据动画的当前时间计算出的位置值该位置值在0到1之间。
*/
static easeIn(t: number, d: number): number;
/**
* easeOut方法提供了一个以快速开始然后逐渐减速的缓动函数。
* @param t 当前时间动画已经持续的时间范围在0到d之间其中d是动画的总时间。
* @param d 动画的总时间,即动画将从开始到结束的持续时间。
* @returns 根据动画的当前时间计算出的位置值该位置值在0到1之间。
*/
static easeOut(t: number, d: number): number;
/**
* easeInOut方法提供了一个慢速开始然后加速然后减速的缓动函数。
* @param t 当前时间动画已经持续的时间范围在0到d之间其中d是动画的总时间。
* @param d 动画的总时间,即动画将从开始到结束的持续时间。
* @returns 根据动画的当前时间计算出的位置值该位置值在0到1之间。
*/
static easeInOut(t: number, d: number): number;
}
class Elastic {
/**
* 弹性函数的 easeIn 版本
* @param t - 已经经过的时间
* @param d - 动画的总时间
* @returns 经过缓动函数计算后的值
*/
static easeIn(t: number, d: number): number;
/**
* 弹性函数的 easeOut 版本
* @param t - 已经经过的时间
* @param d - 动画的总时间
* @returns 经过缓动函数计算后的值
*/
static easeOut(t: number, d: number): number;
/**
* 弹性函数的 easeInOut 版本
* @param t - 已经经过的时间
* @param d - 动画的总时间
* @returns 经过缓动函数计算后的值
*/
static easeInOut(t: number, d: number): number;
/**
* 弹性函数的 punch 版本
* @param t - 已经经过的时间
* @param d - 动画的总时间
* @returns 经过缓动函数计算后的值
*/
static punch(t: number, d: number): number;
}
class Exponential {
/**
* Exponential 缓动函数 - easeIn
* @param t 当前时间
* @param d 持续时间
* @returns 缓动值
*/
static easeIn(t: number, d: number): number;
/**
* Exponential 缓动函数 - easeOut
* @param t 当前时间
* @param d 持续时间
* @returns 缓动值
*/
static easeOut(t: number, d: number): number;
/**
* Exponential 缓动函数 - easeInOut
* @param t 当前时间
* @param d 持续时间
* @returns 缓动值
*/
static easeInOut(t: number, d: number): number;
}
class Quartic {
/**
* Quartic 缓动函数的 easeIn 版本
* @param t 当前时间
* @param d 持续时间
* @returns 根据当前时间计算出的值
*/
static easeIn(t: number, d: number): number;
/**
* Quartic 缓动函数的 easeOut 版本
* @param t 当前时间
* @param d 持续时间
* @returns 根据当前时间计算出的值
*/
static easeOut(t: number, d: number): number;
/**
* Quartic 缓动函数的 easeInOut 版本
* @param t 当前时间
* @param d 持续时间
* @returns 根据当前时间计算出的值
*/
static easeInOut(t: number, d: number): number;
}
/**
* Quintic 类提供了三种 Quintic 缓动函数
*/
class Quintic {
/**
* 缓动函数,具有 Quintic easeIn 效果
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 缓动值
*/
static easeIn(t: number, d: number): number;
/**
* 缓动函数,具有 Quintic easeOut 效果
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 缓动值
*/
static easeOut(t: number, d: number): number;
/**
* 缓动函数,具有 Quintic easeInOut 效果
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 缓动值
*/
static easeInOut(t: number, d: number): number;
}
class Sinusoidal {
/**
* Sinusoidal 类的缓动入方法。
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 介于 0 和 1 之间的数字,表示当前时间的值
*/
static easeIn(t: number, d: number): number;
/**
* Sinusoidal 类的缓动出方法。
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 介于 0 和 1 之间的数字,表示当前时间的值
*/
static easeOut(t: number, d: number): number;
/**
* Sinusoidal 类的缓动入出方法。
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 介于 0 和 1 之间的数字,表示当前时间的值
*/
static easeInOut(t: number, d: number): number;
}
}
@@ -4511,22 +4724,53 @@ declare module es {
* 一系列静态方法来处理所有常见的tween类型结构以及它们的unclamped lerps.unclamped lerps对于超过0-1范围的bounce、elastic或其他tweens是必需的
*/
class Lerps {
static lerp(from: number, to: number, t: number): any;
static lerp(from: Rectangle, to: Rectangle, t: number): any;
static lerp(from: Vector2, to: Vector2, t: number): any;
/**
* 提供通用的线性插值方法,支持数字、矩形和二维向量类型。
* @param from 起点值
* @param to 终点值
* @param t 插值参数,取值范围[0, 1]
* @returns 返回两个值的插值结果
*/
static lerp(from: number, to: number, t: number): number;
static lerp(from: Rectangle, to: Rectangle, t: number): Rectangle;
static lerp(from: Vector2, to: Vector2, t: number): Vector2;
/**
* 计算两个向量之间的角度差并使用线性插值函数进行插值
* @param from 起始向量
* @param to 目标向量
* @param t 插值因子
* @returns 插值后的向量
*/
static angleLerp(from: Vector2, to: Vector2, t: number): Vector2;
/**
* 根据不同类型的数据,使用指定的缓动类型对两个值进行插值
* @param easeType 缓动类型
* @param from 起始值
* @param to 目标值
* @param t 当前时间(相对于持续时间的百分比)
* @param duration 持续时间
* @returns 两个值之间的插值
*/
static ease(easeType: EaseType, from: Rectangle, to: Rectangle, t: number, duration: number): any;
static ease(easeType: EaseType, from: Vector2, to: Vector2, t: number, duration: number): any;
static ease(easeType: EaseType, from: number, to: number, t: number, duration: number): any;
/**
* 通过提供的t值和持续时间使用给定的缓动类型在两个Vector2之间进行角度插值。
* @param easeType 缓动类型
* @param from 开始的向量
* @param to 结束的向量
* @param t 当前时间在持续时间内的比例
* @param duration 持续时间
* @returns 插值后的Vector2值
*/
static easeAngle(easeType: EaseType, from: Vector2, to: Vector2, t: number, duration: number): Vector2;
/**
* 使用半隐式欧拉方法。速度较慢,但总是很稳定。见
* http://allenchou.net/2015/04/game-math-more-on-numeric-springing/
* @param currentValue
* @param targetValue
* @param velocity Velocity的引用。如果在两次调用之间改变targetValue请务必将其重置为0
* @param dampingRatio 值越低阻尼越小值越高阻尼越大导致弹簧度越小应在0.01-1之间以避免系统不稳定
* @param angularFrequency 角频率为2pi(弧度/秒)意味着振荡在一秒钟内完成一个完整的周期即1Hz.应小于35左右才能保持稳定
* 使用快速弹簧算法来实现平滑过渡。返回经过弹簧计算后的当前值。
* @param currentValue 当前值
* @param targetValue 目标值
* @param velocity 当前速度
* @param dampingRatio 阻尼比例
* @param angularFrequency 角频率
*/
static fastSpring(currentValue: Vector2, targetValue: Vector2, velocity: Vector2, dampingRatio: number, angularFrequency: number): Vector2;
}
@@ -5837,23 +6081,30 @@ declare module es {
*/
addRange(elements: T[]): void;
/**
* 对序列应用累加器函数
* 使用指定的累加器函数将数组中的所有元素聚合成一个值
* @param accumulator 用于计算聚合值的累加器函数。
* @param initialValue 可选参数,用于指定累加器函数的初始值。
* @returns 聚合后的值。
*/
aggregate<U>(accumulator: (accum: U, value?: T, index?: number, list?: T[]) => any, initialValue?: U): any;
/**
* 确定序列的所有元素是否满足一个条件
* 判断当前列表中的所有元素是否满足指定条件
* @param predicate 谓词函数,用于对列表中的每个元素进行评估
* @returns {boolean} 如果列表中的所有元素都满足条件,则返回 true否则返回 false
*/
all(predicate: PredicateType<T>): boolean;
/**
* 确定序列是否包含任何元素
* 该方法用于判断数组中是否存在元素
* @param predicate 可选参数,用于检查是否有至少一个元素满足该函数
* @returns 如果存在元素,返回 true如果不存在元素返回 false
*/
any(): boolean;
any(predicate: PredicateType<T>): boolean;
any(predicate?: (element: T) => boolean): boolean;
/**
* 计算通过对输入序列的每个元素调用转换函数获得的一系列数值的平均值
* 计算数组中所有元素的平均值
* @param transform 可选参数,用于将数组中的每个元素转换成另外的值进行计算
* @returns 数组的平均值
*/
average(): number;
average(transform: (value?: T, index?: number, list?: T[]) => any): number;
average(transform?: (value?: T, index?: number, list?: T[]) => any): number;
/**
* 将序列的元素转换为指定的类型。
*/
@@ -5871,92 +6122,137 @@ declare module es {
*/
contains(element: T): boolean;
/**
* 返回序列中元素的数量。
* 计算数组中所有元素的数量,或者根据指定的条件计算符合条件的元素的数量。
* @param predicate 可选参数,用于过滤元素的条件函数。
* @returns 数组元素的数量。
*/
count(): number;
count(predicate: PredicateType<T>): number;
/**
* 返回指定序列的元素,或者如果序列为空,则返回单例集合中类型参数的默认值
* 返回当前数组,如果当前数组为空,则返回一个只包含默认值的新数组
* @param defaultValue 默认值。
* @returns 当前数组,或者只包含默认值的新数组。
*/
defaultIfEmpty(defaultValue?: T): List<T>;
/**
* 根据指定的键选择器从序列中返回不同的元素。
* 根据指定的键选择器从数组中去除重复的元素。
* @param keySelector 用于选择每个元素的键的函数。
* @returns 去重后的数组。
*/
distinctBy(keySelector: (key: T) => string | number): List<T>;
/**
* 返回序列中指定索引的元素
* 根据指定索引获取数组中的元素
* @param index 要获取的元素的索引
* @returns 数组中的元素
* @throws {Error} 如果索引小于 0 或大于等于数组长度,则抛出 "ArgumentOutOfRangeException" 异常。
*/
elementAt(index: number): T;
/**
* 返回序列中指定索引处的元素,如果索引超出范围,则返回默认值
* 获取指定索引处的元素,如果索引超出数组范围,则返回 null
* @param index 索引。
* @returns 指定索引处的元素,如果索引超出数组范围,则返回 null。
*/
elementAtOrDefault(index: number): T | null;
/**
* 通过使用默认的相等比较器来比较值,生成两个序列的差值集
* 返回当前数组中不在指定数组中的元素集合
* @param source 指定数组。
* @returns 当前数组中不在指定数组中的元素集合。
*/
except(source: List<T>): List<T>;
/**
* 返回序列的第一个元素。
* 返回当前数组中第一个元素,或者符合条件的第一个元素。
* @param predicate 符合条件的判断函数。
* @returns 当前数组中第一个元素,或者符合条件的第一个元素。
*/
first(): T;
first(predicate: PredicateType<T>): T;
/**
* 返回序列的第一个元素,如果序列不包含元素,则返回默认值
* 根据指定的条件查询数组中第一个符合条件的元素,如果不存在符合条件的元素,则返回默认值 null 或 undefined
* @param predicate 可选参数,表示查询条件的谓词函数
* @returns 符合条件的元素或默认值 null 或 undefined
*/
firstOrDefault(): T;
firstOrDefault(predicate: PredicateType<T>): T;
/**
* 对列表中的每个元素执行指定的操作
* 对数组中的每个元素执行指定的操作
* @param action 要执行的操作,可以是一个函数或函数表达式
*/
forEach(action: (value?: T, index?: number, list?: T[]) => any): void;
/**
* 根据指定的键选择器函数对序列中的元素进行分组。
* 根据指定的键对数组元素进行分组,并返回一个包含分组结果的对象
* @param grouper 指定的键,用于分组
* @param mapper 可选参数,用于对分组后的每个元素进行转换的函数
* @returns 包含分组结果的对象,其中键为分组后的键,值为分组后的元素组成的数组
*/
groupBy<TResult>(grouper: (key: T) => string | number, mapper?: (element: T) => TResult): {
[key: string]: TResult[];
};
/**
* 根据键的相等将两个序列的元素关联起来,并将结果分组。默认的相等比较器用于比较键。
* 将两个数组进行联接和分组操作
* @param list 要联接的数组
* @param key1 用于从第一个数组中选择分组键的函数
* @param key2 用于从第二个数组中选择分组键的函数
* @param result 用于将分组结果映射到输出元素的函数
* @returns 经过联接和分组后的新数组
*/
groupJoin<U, R>(list: List<U>, key1: (k: T) => any, key2: (k: U) => any, result: (first: T, second: List<U>) => R): List<R>;
/**
* 返回列表中某个元素第一次出现的索引
* 返回当前列表中指定元素的索引
* @param element 要查找的元素
* @returns {number} 元素在列表中的索引值,如果不存在,则返回 -1
*/
indexOf(element: T): number;
/**
* 向列表中插入一个元素在指定索引处。
* 在数组的指定位置插入一个元素
* @param index 要插入元素的位置
* @param element 要插入的元素
* @throws 如果索引超出了数组的范围,则抛出异常
*/
insert(index: number, element: T): void | Error;
insert(index: number, element: T): void;
/**
* 通过使用默认的相等比较器来比较值,生成两个序列的交集集。
* 获取当前列表和另一个列表的交集
* @param source 另一个列表
* @returns {List<T>} 一个包含两个列表中相同元素的新列表对象
*/
intersect(source: List<T>): List<T>;
/**
* 基于匹配的键将两个序列的元素关联起来。默认的相等比较器用于比较键。
* 将当前列表和另一个列表中的元素进行联接
* @param list 另一个列表
* @param key1 当前列表的键选择器函数
* @param key2 另一个列表的键选择器函数
* @param result 结果选择器函数
* @returns {List<R>} 一个包含联接后元素的新列表对象
*/
join<U, R>(list: List<U>, key1: (key: T) => any, key2: (key: U) => any, result: (first: T, second: U) => R): List<R>;
/**
* 返回序列的最后一个元素
* 返回数组的最后一个元素或满足条件的最后一个元素
* @param predicate 可选参数,用于筛选元素的函数
* @returns 数组的最后一个元素或满足条件的最后一个元素
* @throws 如果数组为空,则抛出异常
*/
last(): T;
last(predicate: PredicateType<T>): T;
last(predicate?: PredicateType<T>): T;
/**
* 返回序列的最后一个元素,如果序列不包含元素,则返回默认值。
* 返回数组的最后一个元素或满足条件的最后一个元素,如果数组为空或没有满足条件的元素,则返回默认值 undefined
* @param predicate 可选参数,用于筛选元素的函数
* @returns 数组的最后一个元素或满足条件的最后一个元素,如果数组为空或没有满足条件的元素,则返回默认值 undefined
*/
lastOrDefault(): T;
lastOrDefault(predicate: PredicateType<T>): T;
lastOrDefault(predicate?: PredicateType<T>): T;
/**
* 返回泛型序列中的最大值
* 返回数组中的最大值,也可以通过 selector 函数对数组元素进行转换后再求最大值
* @param selector 可选参数,用于对数组元素进行转换的函数
* @returns 数组中的最大值,或者通过 selector 函数对数组元素进行转换后求得的最大值
*/
max(): number;
max(selector: (value: T, index: number, array: T[]) => number): number;
max(selector?: (value: T, index: number, array: T[]) => number): number;
/**
* 返回泛型序列中的最小值
* 返回数组中的最小值,也可以通过 selector 函数对数组元素进行转换后再求最小值
* @param selector 可选参数,用于对数组元素进行转换的函数
* @returns 数组中的最小值,或者通过 selector 函数对数组元素进行转换后求得的最小值
*/
min(): number;
min(selector: (value: T, index: number, array: T[]) => number): number;
min(selector?: (value: T, index: number, array: T[]) => number): number;
/**
* 根据指定的类型筛选序列中的元素
* 根据指定的类型筛选数组中的元素并返回一个新的数组
* @param type 指定的类型
* @returns 新的数组,其中包含了数组中所有指定类型的元素
*/
ofType<U>(type: any): List<U>;
/**
@@ -5964,80 +6260,118 @@ declare module es {
*/
orderBy(keySelector: (key: T) => any, comparer?: (a: T, b: T) => number): List<T>;
/**
* 根据键值降序对序列中的元素进行排序
* 按照指定的键选择器和比较器,对列表元素进行降序排序
* @param keySelector 用于选择排序键的函数
* @param comparer 可选参数,用于比较元素的函数,如果未指定则使用 keySelector 和降序排序
* @returns 排序后的新 List<T> 对象
*/
orderByDescending(keySelector: (key: T) => any, comparer?: (a: T, b: T) => number): List<T>;
/**
* 按键按升序对序列中的元素执行后续排序
* 在已经按照一个或多个条件排序的列表上,再按照一个新的条件进行排序
* @param keySelector 用于选择新排序键的函数
* @returns 排序后的新 List<T> 对象
*/
thenBy(keySelector: (key: T) => any): List<T>;
/**
* 根据键值按降序对序列中的元素执行后续排序
* 对当前列表中的元素进行降序排序
* @param keySelector 键选择器函数,用于对列表中的每个元素进行转换
* @returns {List<T>} 一个包含排序后元素的新列表对象
*/
thenByDescending(keySelector: (key: T) => any): List<T>;
/**
* 从列表中删除第一个出现的特定对象。
* 从当前列表中删除指定元素
* @param element 要删除的元素
* @returns {boolean} 如果删除成功,则返回 true否则返回 false
*/
remove(element: T): boolean;
/**
* 删除与指定谓词定义的条件匹配的所有元素。
* 从当前列表中删除满足指定条件的所有元素,并返回一个新的列表对象
* @param predicate 谓词函数,用于对列表中的每个元素进行评估
* @returns {List<T>} 一个包含不满足条件的元素的新列表对象
*/
removeAll(predicate: PredicateType<T>): List<T>;
/**
* 删除列表指定索引的元素
* 从当前列表中删除指定索引位置的元素
* @param index 要删除的元素在列表中的索引值
*/
removeAt(index: number): void;
/**
* 颠倒整个列表中元素顺序
* 反转当前列表中元素顺序
* @returns {List<T>} 一个包含反转后元素的新列表对象
*/
reverse(): List<T>;
/**
* 将序列中的每个元素投射到一个新形式中。
* 对数组中的每个元素进行转换,生成新的数组
* @param selector 将数组中的每个元素转换成另外的值
* @returns 新的 List 对象,包含转换后的元素
*/
select<TOut>(selector: (element: T, index: number) => TOut): List<TOut>;
/**
* 将序列的每个元素投影到一个列表中。并将得到的序列扁平化为一个序列。
* 对数组中的每个元素进行转换,并将多个新数组合并成一个数组
* @param selector 将数组中的每个元素转换成新的数组
* @returns 合并后的新数组
*/
selectMany<TOut extends List<any>>(selector: (element: T, index: number) => TOut): TOut;
/**
* 通过使用默认的相等比较器对元素的类型进行比较,确定两个序列是否相等
* 比较当前列表和指定列表是否相等
* @param list 要比较的列表对象
* @returns {boolean} 如果列表相等,则返回 true否则返回 false
*/
sequenceEqual(list: List<T>): boolean;
/**
* 返回序列中唯一的元素,如果序列中没有恰好一个元素,则抛出异常。
* 从当前列表中获取一个满足指定条件的唯一元素
* @param predicate 谓词函数,用于对列表中的每个元素进行评估
* @returns {T} 列表中唯一满足指定条件的元素
* @throws {Error} 如果列表中不恰好包含一个满足指定条件的元素,则抛出异常
*/
single(predicate?: PredicateType<T>): T;
/**
* 返回序列中唯一元素,如果序列为空,则返回默认值;如果序列中有多个元素,此方法将抛出异常。
* 从当前列表中获取一个满足指定条件的唯一元素,如果没有元素满足条件,则返回默认值 undefined
* @param predicate 谓词函数,用于对列表中的每个元素进行评估
* @returns {T} 列表中唯一满足指定条件的元素,如果没有元素满足条件,则返回默认值 undefined
*/
singleOrDefault(predicate?: PredicateType<T>): T;
/**
* 绕过序列中指定数量的元素,然后返回剩余元素。
* 从 List 的开头跳过指定数量的元素返回剩余元素的新 List
* 如果指定数量大于 List 中的元素数,则返回一个空的 List。
* @param amount 要跳过的元素数量
* @returns 新 List
*/
skip(amount: number): List<T>;
/**
* 省略序列中最后指定数量的元素,然后返回剩余的元素
* 返回由源 List 中除了最后指定数量的元素之外的所有元素组成的 List
* @param amount 要跳过的元素数。
* @returns 由源 List 中除了最后指定数量的元素之外的所有元素组成的 List。
*/
skipLast(amount: number): List<T>;
/**
* 只要指定条件为真,就绕过序列中的元素,然后返回剩余元素。
* 从 List 的开头开始,跳过符合指定谓词的元素,返回剩余元素。
* @param predicate 用于测试每个元素是否应跳过的函数。
* @returns 一个新 List包含源 List 中从跳过元素之后到末尾的元素。
*/
skipWhile(predicate: PredicateType<T>): List<T>;
/**
* 计算通过对输入序列的每个元素调用转换函数获得的数值序列的和
* 计算数组中所有元素的和
* @param transform 可选参数,用于将数组中的每个元素转换成另外的值进行计算
* @returns 数组的和
*/
sum(): number;
sum(transform: (value?: T, index?: number, list?: T[]) => number): number;
sum(transform?: (value?: T, index?: number, list?: T[]) => number): number;
/**
* 从序列的开返回指定数量的连续元素。
* 从 List 的开返回指定数量的连续元素。
* @param amount 要返回的元素数量
* @returns 一个新的 List其中包含原始 List 中开头的指定数量的元素
*/
take(amount: number): List<T>;
/**
* 从序列的末尾返回指定数目的连续元素
* 从列表末尾开始获取指定数量的元素,返回一个新的 List 对象
* @param amount 需要获取的元素数量。
* @returns 一个新的 List 对象,包含从末尾开始的指定数量的元素。
*/
takeLast(amount: number): List<T>;
/**
* 返回序列中的元素,只要指定的条件为真
* 从 List 的开头开始取出符合指定谓词的元素,直到不符合为止,返回这些元素组成的 List
* @param predicate 用于测试每个元素是否符合条件的函数。
* @returns 符合条件的元素组成的 List。
*/
takeWhile(predicate: PredicateType<T>): List<T>;
/**
@@ -6045,36 +6379,40 @@ declare module es {
*/
toArray(): T[];
/**
* 创建一个<dictionary>从List< T>根据指定的键选择器函数。
* 将数组转换为字典,根据指定的键和值对元素进行分组并返回一个新的字典
* @param key 指定的键,用于分组
* @param value 可选参数,指定的值,用于分组后的元素的值;如果未指定,则默认使用原始元素
* @returns 分组后的元素组成的新的字典
*/
toDictionary<TKey>(key: (key: T) => TKey): List<{
Key: TKey;
Value: T;
}>;
toDictionary<TKey, TValue>(key: (key: T) => TKey, value: (value: T) => TValue): List<{
toDictionary<TKey, TValue = T>(key: (key: T) => TKey, value?: (value: T) => TValue): List<{
Key: TKey;
Value: T | TValue;
}>;
/**
* 创建一个Set从一个Enumerable.List< T>。
* 将数组转换为一个 Set 对象
* @returns Set 对象,其中包含了数组中的所有元素
*/
toSet(): Set<any>;
/**
* 创建一个List< T>从一个Enumerable.List< T>。
*/
toList(): List<T>;
/**
* 创建一个查找TElement>从一个IEnumerable< T>根据指定的键选择器和元素选择器函数。
* 将数组转换为一个查找表,根据指定的键对元素进行分组并返回一个包含键值对的对象
* @param keySelector 指定的键,用于分组
* @param elementSelector 可选参数,指定的值,用于分组后的元素的值;如果未指定,则默认使用原始元素
* @returns 包含键值对的对象,其中键为分组后的键,值为分组后的元素组成的数组
*/
toLookup<TResult>(keySelector: (key: T) => string | number, elementSelector: (element: T) => TResult): {
[key: string]: TResult[];
};
/**
* 基于谓词过滤一系列值。
* 根据指定的条件,筛选数组中的元素并返回一个新的数组
* @param predicate 指定的条件
* @returns 新的数组,其中包含了数组中所有满足条件的元素
*/
where(predicate: PredicateType<T>): List<T>;
/**
* 指定的函数应用于两个序列的对应元素,生成结果序列。
* 根据指定的函数将两个数组合并成一个新的数组
* @param list 要合并的数组
* @param result 指定的函数,用于将两个元素合并为一个
* @returns 合并后的新数组
*/
zip<U, TOut>(list: List<U>, result: (first: T, second: U) => TOut): List<TOut>;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +1,13 @@
module es {
/**
* AbstractTweenable作为你可能想做的任何可以执行的自定义类的基础
* 这些类不同于ITweens因为他们没有实现ITweenT接口。
* 它只是说一个AbstractTweenable不仅仅是将一个值从开始移动到结束
* 它可以做任何需要每帧执行的事情
*/
* `AbstractTweenable` 是一个抽象类,实现了 `ITweenable` 接口
* 这个类提供了 `start`、`pause`、`resume` 和 `stop` 等方法,
* 并且具有判断动画是否运行的方法 `isRunning`
* 它还有一个 `tick` 方法,子类需要根据自己的需要实现这个方法
*
* `AbstractTweenable` 在完成后往往会被保留下来, `_isCurrentlyManagedByTweenManager` 标志可以让它们知道自己当前是否被 `TweenManager` 监控着,
* 以便在必要时可以重新添加自己。
*/
export abstract class AbstractTweenable implements ITweenable {
readonly discriminator = "ITweenable";
protected _isPaused: boolean;

View File

@@ -50,8 +50,9 @@ module es {
*/
export class EaseHelper {
/**
* 返回 easeType 的相反 EaseType
* @param easeType
* 返回相反的缓动类型
* @param easeType 缓动类型
* @returns 返回相反的缓动类型
*/
public static oppositeEaseType(easeType: EaseType) {
switch (easeType) {

View File

@@ -5,47 +5,99 @@ module es {
*/
export module Easing {
export class Linear {
/**
* 线性缓动等同于t / d
* @param t 当前时间
* @param d 持续时间
*/
public static easeNone(t: number, d: number) {
return t / d;
}
}
export class Quadratic {
/**
* 平方缓动进入,加速运动
* @param t 当前时间
* @param d 持续时间
*/
public static easeIn(t: number, d: number) {
return (t /= d) * t;
}
/**
* 平方缓动退出,减速运动
* @param t 当前时间
* @param d 持续时间
*/
public static easeOut(t: number, d: number) {
return -1 * (t /= d) * (t - 2);
}
/**
* 平方缓动进出,加速减速运动
* @param t 当前时间
* @param d 持续时间
*/
public static easeInOut(t: number, d: number) {
if ((t /= d / 2) < 1)
return 0.5 * t * t;
if ((t /= d / 2) < 1) return 0.5 * t * t;
return -0.5 * ((--t) * (t - 2) - 1);
}
}
export class Back {
public static easeIn(t: number, d: number) {
return (t /= d) * t * ((1.70158 + 1) * t - 1.70158);
/**
* Back.easeIn(t, d) 函数将会返回 Back 缓动进入算法的结果
*
* @param t 当前时间从0开始递增
* @param d 持续时间
* @param s 回弹的距离,默认值为 1.70158,可以省略该参数
* @return 缓动后的值
*/
public static easeIn(t: number, d: number, s: number = 1.70158) {
// 根据公式计算缓动结果
return (t /= d) * t * ((s + 1) * t - s);
}
public static easeOut(t: number, d: number) {
return ((t = t / d - 1) * t * ((1.70158 + 1) * t + 1.70158) + 1);
/**
* Back.easeOut(t, d) 函数将会返回 Back 缓动退出算法的结果
*
* @param t 当前时间从0开始递增
* @param d 持续时间
* @param s 回弹的距离,默认值为 1.70158,可以省略该参数
* @return 缓动后的值
*/
public static easeOut(t: number, d: number, s: number = 1.70158) {
// 根据公式计算缓动结果
return ((t = t / d - 1) * t * ((s + 1) * t + s) + 1);
}
public static easeInOut(t: number, d: number) {
let s = 1.70158;
/**
* Back.easeInOut(t, d) 函数将会返回 Back 缓动进入/退出算法的结果
*
* @param t 当前时间从0开始递增
* @param d 持续时间
* @param s 回弹的距离,默认值为 1.70158,可以省略该参数
* @return 缓动后的值
*/
public static easeInOut(t: number, d: number, s: number = 1.70158) {
// 根据公式计算缓动结果
if ((t /= d / 2) < 1) {
return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s));
s *= (1.525);
return 0.5 * (t * t * (((s + 1) * t) - s));
}
return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
s *= (1.525);
return 0.5 * ((t -= 2) * t * (((s + 1) * t) + s) + 2);
}
}
export class Bounce {
/**
* 从0到目标值的反弹动画
* @param t 当前时间
* @param d 持续时间
* @returns 反弹动画进度
*/
public static easeOut(t: number, d: number) {
if ((t /= d) < (1 / 2.75)) {
return (7.5625 * t * t);
@@ -58,10 +110,22 @@ module es {
}
}
/**
* 从目标值到0的反弹动画
* @param t 当前时间
* @param d 持续时间
* @returns 反弹动画进度
*/
public static easeIn(t: number, d: number) {
return 1 - this.easeOut(d - t, d);
}
/**
* 从0到目标值再到0的反弹动画
* @param t 当前时间
* @param d 持续时间
* @returns 反弹动画进度
*/
public static easeInOut(t: number, d: number) {
if (t < d / 2)
return this.easeIn(t * 2, d) * 0.5;
@@ -71,14 +135,29 @@ module es {
}
export class Circular {
/**
* 缓动函数入口,表示从 0 到最大值的缓动(开始慢加速,后面变快)
* @param t 当前时间
* @param d 缓动总时间
*/
public static easeIn(t: number, d: number) {
return -(Math.sqrt(1 - (t /= d) * t) - 1);
}
/**
* 缓动函数出口,表示从最大值到 0 的缓动(开始快减速,后面变慢)
* @param t 当前时间
* @param d 缓动总时间
*/
public static easeOut(t: number, d: number) {
return Math.sqrt(1 - (t = t / d - 1) * t);
}
/**
* 缓动函数入口和出口,表示从 0 到最大值再到 0 的缓动(先慢加速,后面快减速)
* @param t 当前时间
* @param d 缓动总时间
*/
public static easeInOut(t: number, d: number) {
if ((t /= d / 2) < 1)
return -0.5 * (Math.sqrt(1 - t * t) - 1);
@@ -87,14 +166,32 @@ module es {
}
export class Cubic {
/**
* easeIn方法提供了一个以慢速开始然后逐渐加速的缓动函数。
* @param t 当前时间动画已经持续的时间范围在0到d之间其中d是动画的总时间。
* @param d 动画的总时间,即动画将从开始到结束的持续时间。
* @returns 根据动画的当前时间计算出的位置值该位置值在0到1之间。
*/
public static easeIn(t: number, d: number) {
return (t /= d) * t * t;
}
/**
* easeOut方法提供了一个以快速开始然后逐渐减速的缓动函数。
* @param t 当前时间动画已经持续的时间范围在0到d之间其中d是动画的总时间。
* @param d 动画的总时间,即动画将从开始到结束的持续时间。
* @returns 根据动画的当前时间计算出的位置值该位置值在0到1之间。
*/
public static easeOut(t: number, d: number) {
return ((t = t / d - 1) * t * t + 1);
}
/**
* easeInOut方法提供了一个慢速开始然后加速然后减速的缓动函数。
* @param t 当前时间动画已经持续的时间范围在0到d之间其中d是动画的总时间。
* @param d 动画的总时间,即动画将从开始到结束的持续时间。
* @returns 根据动画的当前时间计算出的位置值该位置值在0到1之间。
*/
public static easeInOut(t: number, d: number) {
if ((t /= d / 2) < 1)
return 0.5 * t * t * t;
@@ -103,66 +200,102 @@ module es {
}
export class Elastic {
public static easeIn(t: number, d: number) {
if (t == 0)
return 0;
if ((t /= d) == 1)
return 1;
let p = d * 0.3;
let s = p / 4;
return -(1 * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p));
/**
* 弹性函数的 easeIn 版本
* @param t - 已经经过的时间
* @param d - 动画的总时间
* @returns 经过缓动函数计算后的值
*/
public static easeIn(t: number, d: number): number {
if (t === 0) return 0;
if ((t /= d) === 1) return 1;
const p = d * 0.3;
const s = p / 4;
return -1 * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p);
}
public static easeOut(t: number, d: number) {
if (t == 0)
return 0;
if ((t /= d) == 1)
return 1;
let p = d * 0.3;
let s = p / 4;
return (1 * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + 1);
/**
* 弹性函数的 easeOut 版本
* @param t - 已经经过的时间
* @param d - 动画的总时间
* @returns 经过缓动函数计算后的值
*/
public static easeOut(t: number, d: number): number {
if (t === 0) return 0;
if ((t /= d) === 1) return 1;
const p = d * 0.3;
const s = p / 4;
return 1 * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + 1;
}
public static easeInOut(t: number, d: number) {
if (t == 0)
return 0;
if ((t /= d / 2) == 2)
return 1;
let p = d * (0.3 * 1.5);
let s = p / 4;
if (t < 1)
return -0.5 * (Math.pow(2, 10 * (t -= 1)) * Math.sin(t * d - s) * (2 * Math.PI) / p);
return (Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + 1);
/**
* 弹性函数的 easeInOut 版本
* @param t - 已经经过的时间
* @param d - 动画的总时间
* @returns 经过缓动函数计算后的值
*/
public static easeInOut(t: number, d: number): number {
if (t === 0) return 0;
if ((t /= d / 2) === 2) return 1;
const p = d * (0.3 * 1.5);
const s = p / 4;
if (t < 1) {
return (
-0.5 *
Math.pow(2, 10 * (t -= 1)) *
Math.sin((t * d - s) * (2 * Math.PI) / p)
);
}
return (
Math.pow(2, -10 * (t -= 1)) *
Math.sin((t * d - s) * (2 * Math.PI) / p) *
0.5 +
1
);
}
public static punch(t: number, d: number) {
if (t == 0)
return 0;
if ((t /= d) == 1)
return 0;
/**
* 弹性函数的 punch 版本
* @param t - 已经经过的时间
* @param d - 动画的总时间
* @returns 经过缓动函数计算后的值
*/
public static punch(t: number, d: number): number {
if (t === 0) return 0;
if ((t /= d) === 1) return 0;
const p = 0.3;
return (Math.pow(2, -10 * t) * Math.sin(t * (2 * Math.PI) / p));
return Math.pow(2, -10 * t) * Math.sin(t * (2 * Math.PI) / p);
}
}
export class Exponential {
/**
* Exponential 缓动函数 - easeIn
* @param t 当前时间
* @param d 持续时间
* @returns 缓动值
*/
public static easeIn(t: number, d: number) {
return (t == 0) ? 0 : Math.pow(2, 10 * (t / d - 1));
}
/**
* Exponential 缓动函数 - easeOut
* @param t 当前时间
* @param d 持续时间
* @returns 缓动值
*/
public static easeOut(t: number, d: number) {
return t == d ? 1 : (-Math.pow(2, -10 * t / d) + 1);
}
/**
* Exponential 缓动函数 - easeInOut
* @param t 当前时间
* @param d 持续时间
* @returns 缓动值
*/
public static easeInOut(t: number, d: number) {
if (t == 0)
return 0;
@@ -177,16 +310,37 @@ module es {
}
}
export class Quartic {
public static easeIn(t: number, d: number) {
return (t /= d) * t * t * t;
/**
* Quartic 缓动函数的 easeIn 版本
* @param t 当前时间
* @param d 持续时间
* @returns 根据当前时间计算出的值
*/
public static easeIn(t: number, d: number): number {
t /= d;
return t * t * t * t;
}
public static easeOut(t: number, d: number) {
return -1 * ((t = t / d - 1) * t * t * t - 1);
/**
* Quartic 缓动函数的 easeOut 版本
* @param t 当前时间
* @param d 持续时间
* @returns 根据当前时间计算出的值
*/
public static easeOut(t: number, d: number): number {
t = t / d - 1;
return -1 * (t * t * t * t - 1);
}
public static easeInOut(t: number, d: number) {
/**
* Quartic 缓动函数的 easeInOut 版本
* @param t 当前时间
* @param d 持续时间
* @returns 根据当前时间计算出的值
*/
public static easeInOut(t: number, d: number): number {
t /= d / 2;
if (t < 1)
return 0.5 * t * t * t * t;
@@ -196,35 +350,80 @@ module es {
}
}
/**
* Quintic 类提供了三种 Quintic 缓动函数
*/
export class Quintic {
public static easeIn(t: number, d: number) {
/**
* 缓动函数,具有 Quintic easeIn 效果
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 缓动值
*/
public static easeIn(t: number, d: number): number {
return (t /= d) * t * t * t * t;
}
public static easeOut(t: number, d: number) {
/**
* 缓动函数,具有 Quintic easeOut 效果
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 缓动值
*/
public static easeOut(t: number, d: number): number {
return ((t = t / d - 1) * t * t * t * t + 1);
}
public static easeInOut(t: number, d: number) {
if ((t /= d / 2) < 1)
/**
* 缓动函数,具有 Quintic easeInOut 效果
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 缓动值
*/
public static easeInOut(t: number, d: number): number {
if ((t /= d / 2) < 1) {
return 0.5 * t * t * t * t * t;
return 0.5 * ((t -= 2) * t * t * t * t + 2);
} else {
return 0.5 * ((t -= 2) * t * t * t * t + 2);
}
}
}
export class Sinusoidal {
/**
* Sinusoidal 类的缓动入方法。
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 介于 0 和 1 之间的数字,表示当前时间的值
*/
public static easeIn(t: number, d: number) {
// 通过 cos 函数计算出当前时间对应的值
return -1 * Math.cos(t / d * (Math.PI / 2)) + 1;
}
/**
* Sinusoidal 类的缓动出方法。
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 介于 0 和 1 之间的数字,表示当前时间的值
*/
public static easeOut(t: number, d: number) {
// 通过 sin 函数计算出当前时间对应的值
return Math.sin(t / d * (Math.PI / 2));
}
/**
* Sinusoidal 类的缓动入出方法。
* @param t 当前时间(单位:毫秒)
* @param d 持续时间(单位:毫秒)
* @returns 介于 0 和 1 之间的数字,表示当前时间的值
*/
public static easeInOut(t: number, d: number) {
// 通过 cos 函数计算出当前时间对应的值
return -0.5 * (Math.cos(Math.PI * t / d) - 1);
}
}
}
}

View File

@@ -3,11 +3,19 @@ module es {
* 一系列静态方法来处理所有常见的tween类型结构以及它们的unclamped lerps.unclamped lerps对于超过0-1范围的bounce、elastic或其他tweens是必需的
*/
export class Lerps {
public static lerp(from: number, to: number, t: number);
public static lerp(from: Rectangle, to: Rectangle, t: number);
public static lerp(from: Vector2, to: Vector2, t: number);
/**
* 提供通用的线性插值方法,支持数字、矩形和二维向量类型。
* @param from 起点值
* @param to 终点值
* @param t 插值参数,取值范围[0, 1]
* @returns 返回两个值的插值结果
*/
public static lerp(from: number, to: number, t: number): number;
public static lerp(from: Rectangle, to: Rectangle, t: number): Rectangle;
public static lerp(from: Vector2, to: Vector2, t: number): Vector2;
public static lerp(from: any, to: any, t: number) {
if (typeof(from) == "number" && typeof(to) == "number") {
// 判断传入的数据类型,并执行对应的插值逻辑
if (typeof (from) == "number" && typeof (to) == "number") {
return from + (to - from) * t;
}
@@ -25,47 +33,85 @@ module es {
}
}
public static angleLerp(from: Vector2, to: Vector2, t: number) {
// 我们计算这个lerp的最短角差
let toMinusFrom = new Vector2(MathHelper.deltaAngle(from.x, to.x), MathHelper.deltaAngle(from.y, to.y));
return new Vector2(from.x + toMinusFrom.x * t, from.y + toMinusFrom.y * t);
/**
* 计算两个向量之间的角度差并使用线性插值函数进行插值
* @param from 起始向量
* @param to 目标向量
* @param t 插值因子
* @returns 插值后的向量
*/
public static angleLerp(from: Vector2, to: Vector2, t: number): Vector2 {
// 计算最短的角差,确保角度在[-180, 180]度之间
let toMinusFrom = new Vector2(
MathHelper.deltaAngle(from.x, to.x),
MathHelper.deltaAngle(from.y, to.y)
);
// 使用线性插值函数计算插值后的向量
return new Vector2(
from.x + toMinusFrom.x * t,
from.y + toMinusFrom.y * t
);
}
/**
* 根据不同类型的数据,使用指定的缓动类型对两个值进行插值
* @param easeType 缓动类型
* @param from 起始值
* @param to 目标值
* @param t 当前时间(相对于持续时间的百分比)
* @param duration 持续时间
* @returns 两个值之间的插值
*/
public static ease(easeType: EaseType, from: Rectangle, to: Rectangle, t: number, duration: number);
public static ease(easeType: EaseType, from: Vector2, to: Vector2, t: number, duration: number);
public static ease(easeType: EaseType, from: number, to: number, t: number, duration: number);
public static ease(easeType: EaseType, from: any, to: any, t: number, duration: number) {
if (typeof(from) == 'number' && typeof(to) == "number") {
// 如果传入的值都是 number 类型,就直接返回两个值之间的线性插值
if (typeof (from) == 'number' && typeof (to) == "number") {
return this.lerp(from, to, EaseHelper.ease(easeType, t, duration));
}
// 如果传入的值都是 Vector2 类型,就返回两个 Vector2 之间的插值
if (from instanceof Vector2 && to instanceof Vector2) {
return this.lerp(from, to, EaseHelper.ease(easeType, t, duration));
}
// 如果传入的值都是 Rectangle 类型,就返回两个 Rectangle 之间的插值
if (from instanceof Rectangle && to instanceof Rectangle) {
return this.lerp(from, to, EaseHelper.ease(easeType, t, duration));
}
}
public static easeAngle(easeType: EaseType, from: Vector2, to: Vector2, t: number, duration: number) {
/**
* 通过提供的t值和持续时间使用给定的缓动类型在两个Vector2之间进行角度插值。
* @param easeType 缓动类型
* @param from 开始的向量
* @param to 结束的向量
* @param t 当前时间在持续时间内的比例
* @param duration 持续时间
* @returns 插值后的Vector2值
*/
public static easeAngle(easeType: EaseType, from: Vector2, to: Vector2, t: number, duration: number): Vector2 {
return this.angleLerp(from, to, EaseHelper.ease(easeType, t, duration));
}
/**
* 使用半隐式欧拉方法。速度较慢,但总是很稳定。见
* http://allenchou.net/2015/04/game-math-more-on-numeric-springing/
* @param currentValue
* @param targetValue
* @param velocity Velocity的引用。如果在两次调用之间改变targetValue请务必将其重置为0
* @param dampingRatio 值越低阻尼越小值越高阻尼越大导致弹簧度越小应在0.01-1之间以避免系统不稳定
* @param angularFrequency 角频率为2pi(弧度/秒)意味着振荡在一秒钟内完成一个完整的周期即1Hz.应小于35左右才能保持稳定
* 使用快速弹簧算法来实现平滑过渡。返回经过弹簧计算后的当前值。
* @param currentValue 当前值
* @param targetValue 目标值
* @param velocity 当前速度
* @param dampingRatio 阻尼比例
* @param angularFrequency 角频率
*/
public static fastSpring(currentValue: Vector2, targetValue: Vector2, velocity: Vector2,
dampingRatio: number, angularFrequency: number) {
dampingRatio: number, angularFrequency: number): Vector2 {
// 计算下一帧的速度
velocity.add(velocity.scale(-2 * Time.deltaTime * dampingRatio * angularFrequency)
.add(targetValue.sub(currentValue).scale(Time.deltaTime * angularFrequency * angularFrequency)));
// 计算下一帧的当前值
currentValue.add(velocity.scale(Time.deltaTime));
// 返回计算后的当前值
return currentValue;
}
}

View File

@@ -1,31 +1,44 @@
module es {
/**
* 通用ITweenTarget用于所有属性tweens。
*/
class PropertyTarget<T> implements ITweenTarget<T> {
protected _target;
protected _propertyName;
protected _target: any; // 属性动画的目标对象
protected _propertyName: string; // 属性名
constructor(target, propertyName: string) {
/**
* @param target 属性动画的目标对象
* @param propertyName 属性名
*/
constructor(target: any, propertyName: string) {
this._target = target;
this._propertyName = propertyName;
}
public getTargetObject() {
public getTargetObject(): any {
return this._target;
}
public setTweenedValue(value: T) {
// 将属性动画的目标对象的属性值设置为动画的当前值
this._target[this._propertyName] = value;
}
public getTweenedValue(): T {
// 获取属性动画的目标对象的属性值
return this._target[this._propertyName];
}
}
/**
* 属性动画工具类
*/
export class PropertyTweens {
public static NumberPropertyTo(self, memberName: string, to: number, duration: number): ITween<number> {
/**
* 创建一个属性为number类型的动画对象
* @param self 属性动画的目标对象
* @param memberName 属性名
* @param to 动画结束时的属性值
* @param duration 动画时长
*/
public static NumberPropertyTo(self: any, memberName: string, to: number, duration: number): ITween<number> {
let tweenTarget = new PropertyTarget<number>(self, memberName);
let tween = TweenManager.cacheNumberTweens ? Pool.obtain<NumberTween>(NumberTween) : new NumberTween();
tween.initialize(tweenTarget, to, duration);
@@ -33,8 +46,15 @@ module es {
return tween;
}
public static Vector2PropertyTo(self, memeberName: string, to: Vector2, duration: number): ITween<Vector2> {
let tweenTarget = new PropertyTarget<Vector2>(self, memeberName);
/**
* 创建一个属性为Vector2类型的动画对象
* @param self 属性动画的目标对象
* @param memberName 属性名
* @param to 动画结束时的属性值
* @param duration 动画时长
*/
public static Vector2PropertyTo(self: any, memberName: string, to: Vector2, duration: number): ITween<Vector2> {
let tweenTarget = new PropertyTarget<Vector2>(self, memberName);
let tween = TweenManager.cacheVector2Tweens ? Pool.obtain<Vector2Tween>(Vector2Tween) : new Vector2Tween();
tween.initialize(tweenTarget, to, duration);

View File

@@ -13,30 +13,30 @@ module es {
export abstract class Tween<T> implements ITweenable, ITween<T> {
readonly discriminator: "ITweenControl";
protected _target: ITweenTarget<T>;
protected _isFromValueOverridden: boolean;
protected _fromValue: T;
protected _toValue: T;
protected _easeType: EaseType;
protected _shouldRecycleTween: boolean = true;
protected _isRelative: boolean;
protected _completionHandler: (tween: ITween<T>) => void;
protected _loopCompleteHandler: (tween: ITween<T>) => void;
protected _nextTween: ITweenable;
protected _target: ITweenTarget<T>; // 一个受Tween控制的对象
protected _isFromValueOverridden: boolean; // 一个标志位指示是否覆盖了FromValue
protected _fromValue: T; // 起始值
protected _toValue: T; // 结束值
protected _easeType: EaseType; // 缓动类型
protected _shouldRecycleTween: boolean = true; // 标志位表示Tween执行完毕后是否要回收Tween实例
protected _isRelative: boolean; // 标志位表示Tween是否是相对值
protected _completionHandler: (tween: ITween<T>) => void; // Tween完成时的回调函数
protected _loopCompleteHandler: (tween: ITween<T>) => void; // Tween循环完成时的回调函数
protected _nextTween: ITweenable; // 用于在Tween完成后启动下一个Tween的属性
protected _tweenState: TweenState = TweenState.complete;
private _isTimeScaleIndependent: boolean;
protected _delay: number;
protected _duration: number;
protected _timeScale: number = 1;
protected _elapsedTime: number;
protected _tweenState: TweenState = TweenState.complete; // 当前Tween的状态
private _isTimeScaleIndependent: boolean; // 标志位表示Tween是否与TimeScale无关
protected _delay: number; // 延迟时间
protected _duration: number; // Tween执行时间
protected _timeScale: number = 1; // 时间缩放系数
protected _elapsedTime: number; // 经过的时间
protected _loopType: LoopType;
protected _loops: number;
protected _delayBetweenLoops: number;
private _isRunningInReverse: boolean;
protected _loopType: LoopType; // 循环类型
protected _loops: number; // 循环次数
protected _delayBetweenLoops: number; // 循环之间的延迟时间
private _isRunningInReverse: boolean; // 标志位表示Tween是否以相反方向运行
public context: any;
public context: any; // 任意类型的属性用于存储Tween的上下文信息
public setEaseType(easeType: EaseType): ITween<T> {
this._easeType = easeType;
@@ -117,11 +117,41 @@ module es {
}
public tick(): boolean {
// 如果Tween处于暂停状态则直接返回false
if (this._tweenState == TweenState.paused)
return false;
// 当我们进行循环时我们会在0和持续时间之间限制数值
// 计算多余的时间
let elapsedTimeExcess = this.calculateElapsedTimeExcess();
// 如果Tween处于有效时间范围内则更新Tween值
if (this._elapsedTime >= 0 && this._elapsedTime <= this._duration) {
this.updateValue();
}
// 如果Tween已经完成且需要进行循环则处理循环
if (this._loopType != LoopType.none && this._tweenState == TweenState.complete && this._loops != 0) {
this.handleLooping(elapsedTimeExcess);
}
// 计算deltaTime并更新_elapsedTime
let deltaTime = this.calculateDeltaTime();
this.updateElapsedTime(deltaTime);
// 如果Tween已经完成则处理完成事件并启动下一个Tween如果有的话
if (this._tweenState == TweenState.complete) {
this.handleCompletion();
return true;
}
return false;
}
// 计算多余的时间
private calculateElapsedTimeExcess(): number {
let elapsedTimeExcess = 0;
if (!this._isRunningInReverse && this._elapsedTime >= this._duration) {
elapsedTimeExcess = this._elapsedTime - this._duration;
this._elapsedTime = this._duration;
@@ -132,42 +162,48 @@ module es {
this._tweenState = TweenState.complete;
}
// 当我们延迟开始tween的时候经过的时间会是负数所以不要更新这个值。
if (this._elapsedTime >= 0 && this._elapsedTime <= this._duration) {
this.updateValue();
}
// 如果我们有一个loopType并且我们是Complete意味着我们达到了0或持续时间处理循环。
// handleLooping将采取任何多余的elapsedTime并将其因子化并在必要时调用udpateValue来保持tween的完美准确性
if (this._loopType != LoopType.none && this._tweenState == TweenState.complete && this._loops != 0) {
this.handleLooping(elapsedTimeExcess);
}
return elapsedTimeExcess;
}
// 计算deltaTime
private calculateDeltaTime(): number {
let deltaTime = this._isTimeScaleIndependent ? Time.unscaledDeltaTime : Time.deltaTime;
deltaTime *= this._timeScale;
// 我们需要减去deltaTime
// 如果Tween是运行在反向模式下则需要将deltaTime取反
if (this._isRunningInReverse)
this._elapsedTime -= deltaTime;
else
this._elapsedTime += deltaTime;
deltaTime = -deltaTime;
if (this._tweenState == TweenState.complete) {
this._completionHandler && this._completionHandler(this);
// 如果我们有一个nextTween把它添加到TweenManager中这样它就可以开始运行了
if (this._nextTween != null) {
this._nextTween.start();
this._nextTween = null;
}
return true;
}
return false;
return deltaTime;
}
// 更新_elapsedTime
private updateElapsedTime(deltaTime: number) {
this._elapsedTime += deltaTime;
// 如果Tween处于反向模式下则需要将_elapsedTime限制在0和_duration之间
if (this._isRunningInReverse) {
this._elapsedTime = Math.max(0, this._elapsedTime);
this._elapsedTime = Math.min(this._elapsedTime, this._duration);
}
// 如果Tween处于正向模式下则需要将_elapsedTime限制在0和_duration之间
else {
this._elapsedTime = Math.min(this._elapsedTime, this._duration);
}
}
// 处理Tween完成事件并启动下一个Tween如果有的话
private handleCompletion() {
this._completionHandler && this._completionHandler(this);
// 如果有下一个Tween则启动它
if (this._nextTween != null) {
this._nextTween.start();
this._nextTween = null;
}
}
public recycleSelf() {
if (this._shouldRecycleTween) {
this._target = null;
@@ -227,7 +263,7 @@ module es {
/**
* 当通过StartCoroutine调用时这将一直持续到tween完成
*/
public * waitForCompletion() {
public* waitForCompletion() {
while (this._tweenState != TweenState.complete)
yield null;
}

View File

@@ -27,14 +27,11 @@ module es {
return this._instance._activeTweens;
}
// 临时存储已完成的tweens
private _tempTweens: ITweenable[] = [];
/**
* 标志表示tween更新循环正在运行
*/
// 标志表示tween更新循环正在运行
private _isUpdating: boolean;
/**
* 便于暴露一个静态的API以方便访问
*/
// 便于暴露一个静态的API以方便访问
private static _instance: TweenManager;
constructor() {
@@ -45,20 +42,24 @@ module es {
public update() {
this._isUpdating = true;
// 反向循环这样我们就可以把完成的weens删除了
// 反向循环,这样我们就可以把完成的tweens删除了
for (let i = this._activeTweens.length - 1; i >= 0; --i) {
let tween = this._activeTweens[i];
if (tween.tick())
if (tween.tick()) {
// 如果tween还没有完成将其加入临时列表中
this._tempTweens.push(tween);
}
}
this._isUpdating = false;
// 从临时列表中删除所有已完成的tweens
for (let i = 0; i < this._tempTweens.length; i++) {
this._tempTweens[i].recycleSelf();
new List(this._activeTweens).remove(this._tempTweens[i]);
}
// 清空临时列表
this._tempTweens.length = 0;
}
@@ -146,15 +147,15 @@ module es {
public static allTweensWithTargetEntity(target: Entity) {
let foundTweens = [];
for (let i = 0; i < this._instance._activeTweens.length; i ++) {
for (let i = 0; i < this._instance._activeTweens.length; i++) {
if (this._instance._activeTweens[i].discriminator == "ITweenControl") {
let tweenControl = this._instance._activeTweens[i] as ITweenControl;
let obj = tweenControl.getTargetObject();
if (obj instanceof Entity && obj == target ||
obj instanceof Component && obj.entity == target ||
obj instanceof Transform && obj.entity == target) {
foundTweens.push(this._instance._activeTweens[i]);
}
foundTweens.push(this._instance._activeTweens[i]);
}
}
}

View File

@@ -40,44 +40,60 @@ module es {
}
/**
* 对序列应用累加器函数
* 使用指定的累加器函数将数组中的所有元素聚合成一个值
* @param accumulator 用于计算聚合值的累加器函数。
* @param initialValue 可选参数,用于指定累加器函数的初始值。
* @returns 聚合后的值。
*/
public aggregate<U>(
accumulator: (accum: U, value?: T, index?: number, list?: T[]) => any,
initialValue?: U
): any {
return this._elements.reduce(accumulator, initialValue)
return this._elements.reduce(accumulator, initialValue);
}
/**
* 确定序列的所有元素是否满足一个条件
* 判断当前列表中的所有元素是否满足指定条件
* @param predicate 谓词函数,用于对列表中的每个元素进行评估
* @returns {boolean} 如果列表中的所有元素都满足条件,则返回 true否则返回 false
*/
public all(predicate: PredicateType<T>): boolean {
return this._elements.every(predicate)
// 调用 every 方法,传入谓词函数,检查列表中的所有元素是否都满足条件
return this._elements.every(predicate);
}
/**
* 确定序列是否包含任何元素
* 该方法用于判断数组中是否存在元素
* @param predicate 可选参数,用于检查是否有至少一个元素满足该函数
* @returns 如果存在元素,返回 true如果不存在元素返回 false
*/
public any(): boolean
public any(predicate: PredicateType<T>): boolean
public any(predicate?: PredicateType<T>): boolean {
return predicate
? this._elements.some(predicate)
: this._elements.length > 0
public any(predicate?: (element: T) => boolean): boolean {
// 如果 predicate 函数提供了,则使用 some() 方法判断是否有任意元素满足该函数
if (predicate) {
return this._elements.some(predicate);
}
// 如果没有提供 predicate 函数,则检查数组的长度是否大于 0
return this._elements.length > 0;
}
/**
* 计算通过对输入序列的每个元素调用转换函数获得的一系列数值的平均值
* 计算数组中所有元素的平均值
* @param transform 可选参数,用于将数组中的每个元素转换成另外的值进行计算
* @returns 数组的平均值
*/
public average(): number
public average(
transform: (value?: T, index?: number, list?: T[]) => any
): number
public average(
transform?: (value?: T, index?: number, list?: T[]) => any
): number {
return this.sum(transform) / this.count(transform)
// 调用 sum() 方法计算数组中所有元素的和
const sum = this.sum(transform);
// 调用 count() 方法计算数组中元素的个数
const count = this.count(transform);
// 如果元素的个数为 0则返回 NaN
if (count === 0) {
return NaN;
}
// 计算数组的平均值并返回
return sum / count;
}
/**
@@ -109,94 +125,111 @@ module es {
}
/**
* 返回序列中元素的数量。
* 计算数组中所有元素的数量,或者根据指定的条件计算符合条件的元素的数量。
* @param predicate 可选参数,用于过滤元素的条件函数。
* @returns 数组元素的数量。
*/
public count(): number
public count(predicate: PredicateType<T>): number
public count(predicate?: PredicateType<T>): number {
return predicate ? this.where(predicate).count() : this._elements.length
return predicate ? this.where(predicate).count() : this._elements.length;
}
/**
* 返回指定序列的元素,或者如果序列为空,则返回单例集合中类型参数的默认值
* 返回当前数组,如果当前数组为空,则返回一个只包含默认值的新数组
* @param defaultValue 默认值。
* @returns 当前数组,或者只包含默认值的新数组。
*/
public defaultIfEmpty(defaultValue?: T): List<T> {
return this.count() ? this : new List<T>([defaultValue])
return this.count() ? this : new List<T>([defaultValue]);
}
/**
* 根据指定的键选择器从序列中返回不同的元素。
* 根据指定的键选择器从数组中去除重复的元素。
* @param keySelector 用于选择每个元素的键的函数。
* @returns 去重后的数组。
*/
public distinctBy(keySelector: (key: T) => string | number): List<T> {
const groups = this.groupBy(keySelector);
return Object.keys(groups).reduce((res, key) => {
res.add(groups[key][0] as T);
return res
}, new List<T>())
const groups = this.groupBy(keySelector); // 根据键选择器对数组进行分组。
return Object.keys(groups).reduce((res, key) => { // 遍历分组后的对象。
res.add(groups[key][0] as T); // 将每组的第一个元素加入结果集合。
return res;
}, new List<T>()); // 返回结果集合。
}
/**
* 返回序列中指定索引的元素
* 根据指定索引获取数组中的元素
* @param index 要获取的元素的索引
* @returns 数组中的元素
* @throws {Error} 如果索引小于 0 或大于等于数组长度,则抛出 "ArgumentOutOfRangeException" 异常。
*/
public elementAt(index: number): T {
if (index < this.count() && index >= 0) {
return this._elements[index]
return this._elements[index];
} else {
throw new Error(
'ArgumentOutOfRangeException: index is less than 0 or greater than or equal to the number of elements in source.'
)
);
}
}
/**
* 返回序列中指定索引处的元素,如果索引超出范围,则返回默认值
* 获取指定索引处的元素,如果索引超出数组范围,则返回 null
* @param index 索引。
* @returns 指定索引处的元素,如果索引超出数组范围,则返回 null。
*/
public elementAtOrDefault(index: number): T | null {
return index < this.count() && index >= 0
? this._elements[index]
: undefined
return index < this.count() && index >= 0 ? this._elements[index] : null;
}
/**
* 通过使用默认的相等比较器来比较值,生成两个序列的差值集
* 返回当前数组中不在指定数组中的元素集合
* @param source 指定数组。
* @returns 当前数组中不在指定数组中的元素集合。
*/
public except(source: List<T>): List<T> {
return this.where(x => !source.contains(x))
return this.where(x => !source.contains(x));
}
/**
* 返回序列的第一个元素。
* 返回当前数组中第一个元素,或者符合条件的第一个元素。
* @param predicate 符合条件的判断函数。
* @returns 当前数组中第一个元素,或者符合条件的第一个元素。
*/
public first(): T
public first(predicate: PredicateType<T>): T
public first(): T;
public first(predicate: PredicateType<T>): T;
public first(predicate?: PredicateType<T>): T {
if (this.count()) {
return predicate ? this.where(predicate).first() : this._elements[0]
return predicate ? this.where(predicate).first() : this._elements[0];
} else {
throw new Error(
'InvalidOperationException: The source sequence is empty.'
)
throw new Error('InvalidOperationException: The source sequence is empty.');
}
}
/**
* 返回序列的第一个元素,如果序列不包含元素,则返回默认值
* 根据指定的条件查询数组中第一个符合条件的元素,如果不存在符合条件的元素,则返回默认值 null 或 undefined
* @param predicate 可选参数,表示查询条件的谓词函数
* @returns 符合条件的元素或默认值 null 或 undefined
*/
public firstOrDefault(): T
public firstOrDefault(predicate: PredicateType<T>): T
public firstOrDefault(predicate?: PredicateType<T>): T {
return this.count(predicate) ? this.first(predicate) : undefined
return this.count(predicate) ? this.first(predicate) : undefined;
}
/**
* 对列表中的每个元素执行指定的操作
* 对数组中的每个元素执行指定的操作
* @param action 要执行的操作,可以是一个函数或函数表达式
*/
public forEach(action: (value?: T, index?: number, list?: T[]) => any): void {
return this._elements.forEach(action)
return this._elements.forEach(action);
}
/**
* 根据指定的键选择器函数对序列中的元素进行分组。
* 根据指定的键对数组元素进行分组,并返回一个包含分组结果的对象
* @param grouper 指定的键,用于分组
* @param mapper 可选参数,用于对分组后的每个元素进行转换的函数
* @returns 包含分组结果的对象,其中键为分组后的键,值为分组后的元素组成的数组
*/
public groupBy<TResult>(
grouper: (key: T) => string | number,
@@ -210,12 +243,17 @@ module es {
existingGroup
? existingGroup.push(mappedValue)
: (ac[key] = [mappedValue]);
return ac
}, initialValue)
return ac;
}, initialValue);
}
/**
* 根据键的相等将两个序列的元素关联起来,并将结果分组。默认的相等比较器用于比较键。
* 将两个数组进行联接和分组操作
* @param list 要联接的数组
* @param key1 用于从第一个数组中选择分组键的函数
* @param key2 用于从第二个数组中选择分组键的函数
* @param result 用于将分组结果映射到输出元素的函数
* @returns 经过联接和分组后的新数组
*/
public groupJoin<U, R>(
list: List<U>,
@@ -223,41 +261,60 @@ module es {
key2: (k: U) => any,
result: (first: T, second: List<U>) => R
): List<R> {
// 使用 select() 方法对第一个数组中的每个元素进行分组操作
return this.select(x =>
// 调用 result 函数将分组结果映射到输出元素
result(
x,
// 使用 where() 方法从第二个数组中选择符合条件的元素,然后使用 List 对象进行包装
list.where(z => key1(x) === key2(z))
)
)
);
}
/**
* 返回列表中某个元素第一次出现的索引
* 返回当前列表中指定元素的索引
* @param element 要查找的元素
* @returns {number} 元素在列表中的索引值,如果不存在,则返回 -1
*/
public indexOf(element: T): number {
return this._elements.indexOf(element)
// 调用 indexOf 方法,查找元素在列表中的索引值,如果不存在,则返回 -1
return this._elements.indexOf(element);
}
/**
* 向列表中插入一个元素在指定索引处。
* 在数组的指定位置插入一个元素
* @param index 要插入元素的位置
* @param element 要插入的元素
* @throws 如果索引超出了数组的范围,则抛出异常
*/
public insert(index: number, element: T): void | Error {
public insert(index: number, element: T): void {
// 如果索引小于 0 或大于数组长度,则抛出异常
if (index < 0 || index > this._elements.length) {
throw new Error('Index is out of range.')
throw new Error('Index is out of range.');
}
this._elements.splice(index, 0, element)
// 使用 splice() 方法在指定位置插入元素
this._elements.splice(index, 0, element);
}
/**
* 通过使用默认的相等比较器来比较值,生成两个序列的交集集。
* 获取当前列表和另一个列表的交集
* @param source 另一个列表
* @returns {List<T>} 一个包含两个列表中相同元素的新列表对象
*/
public intersect(source: List<T>): List<T> {
return this.where(x => source.contains(x))
// 调用 where 方法,传入一个谓词函数,返回一个包含两个列表中相同元素的新列表对象
return this.where(x => source.contains(x));
}
/**
* 基于匹配的键将两个序列的元素关联起来。默认的相等比较器用于比较键。
* 将当前列表和另一个列表中的元素进行联接
* @param list 另一个列表
* @param key1 当前列表的键选择器函数
* @param key2 另一个列表的键选择器函数
* @param result 结果选择器函数
* @returns {List<R>} 一个包含联接后元素的新列表对象
*/
public join<U, R>(
list: List<U>,
@@ -265,64 +322,77 @@ module es {
key2: (key: U) => any,
result: (first: T, second: U) => R
): List<R> {
// 对当前列表中的每个元素调用 selectMany 方法,并传入一个返回值为列表的函数,最终返回一个新的列表对象
return this.selectMany(x =>
// 调用 list.where 方法,传入一个谓词函数,返回一个包含与当前元素匹配的元素的新列表对象
list.where(y => key2(y) === key1(x)).select(z => result(x, z))
)
);
}
/**
* 返回序列的最后一个元素
* 返回数组的最后一个元素或满足条件的最后一个元素
* @param predicate 可选参数,用于筛选元素的函数
* @returns 数组的最后一个元素或满足条件的最后一个元素
* @throws 如果数组为空,则抛出异常
*/
public last(): T
public last(predicate: PredicateType<T>): T
public last(predicate?: PredicateType<T>): T {
// 如果数组不为空
if (this.count()) {
return predicate
? this.where(predicate).last()
: this._elements[this.count() - 1]
// 如果提供了 predicate 函数,则使用 where() 方法进行筛选,并递归调用 last() 方法
if (predicate) {
return this.where(predicate).last();
} else {
// 否则,直接返回数组的最后一个元素
return this._elements[this.count() - 1];
}
} else {
throw Error('InvalidOperationException: The source sequence is empty.')
// 如果数组为空,则抛出异常
throw Error('InvalidOperationException: The source sequence is empty.');
}
}
/**
* 返回序列的最后一个元素,如果序列不包含元素,则返回默认值。
* 返回数组的最后一个元素或满足条件的最后一个元素,如果数组为空或没有满足条件的元素,则返回默认值 undefined
* @param predicate 可选参数,用于筛选元素的函数
* @returns 数组的最后一个元素或满足条件的最后一个元素,如果数组为空或没有满足条件的元素,则返回默认值 undefined
*/
public lastOrDefault(): T
public lastOrDefault(predicate: PredicateType<T>): T
public lastOrDefault(predicate?: PredicateType<T>): T {
return this.count(predicate) ? this.last(predicate) : undefined
// 如果数组中存在满足条件的元素,则返回最后一个满足条件的元素;否则,返回 undefined
return this.count(predicate) ? this.last(predicate) : undefined;
}
/**
* 返回泛型序列中的最大值
* 返回数组中的最大值,也可以通过 selector 函数对数组元素进行转换后再求最大值
* @param selector 可选参数,用于对数组元素进行转换的函数
* @returns 数组中的最大值,或者通过 selector 函数对数组元素进行转换后求得的最大值
*/
public max(): number
public max(selector: (value: T, index: number, array: T[]) => number): number
public max(
selector?: (value: T, index: number, array: T[]) => number
): number {
public max(selector?: (value: T, index: number, array: T[]) => number): number {
// 定义一个默认的转换函数 id用于当 selector 参数未指定时使用
const id = x => x;
return Math.max(...this._elements.map(selector || id))
// 使用 map() 方法对数组元素进行转换,并使用 Math.max() 方法求得最大值
return Math.max(...this._elements.map(selector || id));
}
/**
* 返回泛型序列中的最小值
* 返回数组中的最小值,也可以通过 selector 函数对数组元素进行转换后再求最小值
* @param selector 可选参数,用于对数组元素进行转换的函数
* @returns 数组中的最小值,或者通过 selector 函数对数组元素进行转换后求得的最小值
*/
public min(): number
public min(selector: (value: T, index: number, array: T[]) => number): number
public min(
selector?: (value: T, index: number, array: T[]) => number
): number {
public min(selector?: (value: T, index: number, array: T[]) => number): number {
// 定义一个默认的转换函数 id用于当 selector 参数未指定时使用
const id = x => x;
return Math.min(...this._elements.map(selector || id))
// 使用 map() 方法对数组元素进行转换,并使用 Math.min() 方法求得最小值
return Math.min(...this._elements.map(selector || id));
}
/**
* 根据指定的类型筛选序列中的元素
* 根据指定的类型筛选数组中的元素并返回一个新的数组
* @param type 指定的类型
* @returns 新的数组,其中包含了数组中所有指定类型的元素
*/
public ofType<U>(type: any): List<U> {
let typeName;
let typeName: string;
// 使用 switch 语句根据指定类型设置 typeName 变量
switch (type) {
case Number:
typeName = typeof 0;
@@ -334,15 +404,17 @@ module es {
typeName = typeof true;
break;
case Function:
typeName = typeof function () { }; // tslint:disable-line no-empty
typeName = typeof function () {
}; // 空函数,不做任何操作
break;
default:
typeName = null;
break
break;
}
// 如果 typeName 为 null则使用 "instanceof" 运算符检查类型;否则,使用 typeof 运算符检查类型
return typeName === null
? this.where(x => x instanceof type).cast<U>()
: this.where(x => typeof x === typeName).cast<U>()
: this.where(x => typeof x === typeName).cast<U>();
}
/**
@@ -357,211 +429,281 @@ module es {
}
/**
* 根据键值降序对序列中的元素进行排序
* 按照指定的键选择器和比较器,对列表元素进行降序排序
* @param keySelector 用于选择排序键的函数
* @param comparer 可选参数,用于比较元素的函数,如果未指定则使用 keySelector 和降序排序
* @returns 排序后的新 List<T> 对象
*/
public orderByDescending(
keySelector: (key: T) => any,
comparer = keyComparer(keySelector, true)
): List<T> {
// tslint:disable-next-line: no-use-before-declare
return new OrderedList<T>(this._elements, comparer)
// 使用 Array.slice() 方法复制数组元素,避免修改原数组
const elementsCopy = this._elements.slice();
// 根据 keySelector 和 comparer 排序元素
elementsCopy.sort(comparer);
// 创建新的 OrderedList<T> 对象并返回
return new OrderedList<T>(elementsCopy, comparer);
}
/**
* 按键按升序对序列中的元素执行后续排序
* 在已经按照一个或多个条件排序的列表上,再按照一个新的条件进行排序
* @param keySelector 用于选择新排序键的函数
* @returns 排序后的新 List<T> 对象
*/
public thenBy(keySelector: (key: T) => any): List<T> {
return this.orderBy(keySelector)
// 调用 orderBy 方法,使用 keySelector 函数对列表进行排序,并返回排序后的新列表
return this.orderBy(keySelector);
}
/**
* 根据键值按降序对序列中的元素执行后续排序
* 对当前列表中的元素进行降序排序
* @param keySelector 键选择器函数,用于对列表中的每个元素进行转换
* @returns {List<T>} 一个包含排序后元素的新列表对象
*/
public thenByDescending(keySelector: (key: T) => any): List<T> {
return this.orderByDescending(keySelector)
// 调用 orderByDescending 方法,传入键选择器函数,对当前列表中的元素进行降序排序,并返回一个新的列表对象
return this.orderByDescending(keySelector);
}
/**
* 从列表中删除第一个出现的特定对象。
* 从当前列表中删除指定元素
* @param element 要删除的元素
* @returns {boolean} 如果删除成功,则返回 true否则返回 false
*/
public remove(element: T): boolean {
return this.indexOf(element) !== -1
? (this.removeAt(this.indexOf(element)), true)
: false
// 调用 indexOf 方法,查找元素在列表中的索引值
const index = this.indexOf(element);
// 如果元素存在,则调用 removeAt 方法将其从列表中删除,并返回 true否则返回 false
return index !== -1 ? (this.removeAt(index), true) : false;
}
/**
* 删除与指定谓词定义的条件匹配的所有元素。
* 从当前列表中删除满足指定条件的所有元素,并返回一个新的列表对象
* @param predicate 谓词函数,用于对列表中的每个元素进行评估
* @returns {List<T>} 一个包含不满足条件的元素的新列表对象
*/
public removeAll(predicate: PredicateType<T>): List<T> {
return this.where(negate(predicate as any))
// 调用 negate 函数对谓词函数进行取反,然后使用 where 方法筛选出不满足条件的元素
const elements = this.where(negate(predicate as any)).toArray();
// 创建一个新的列表对象,包含不满足条件的元素,并返回该对象
return new List<T>(elements);
}
/**
* 删除列表指定索引的元素
* 从当前列表中删除指定索引位置的元素
* @param index 要删除的元素在列表中的索引值
*/
public removeAt(index: number): void {
this._elements.splice(index, 1)
// 使用 splice 方法,传入要删除的元素在列表中的索引值和要删除的元素个数,以从列表中删除指定索引位置的元素
this._elements.splice(index, 1);
}
/**
* 颠倒整个列表中元素顺序
* 反转当前列表中元素顺序
* @returns {List<T>} 一个包含反转后元素的新列表对象
*/
public reverse(): List<T> {
return new List<T>(this._elements.reverse())
// 调用 reverse 方法,反转当前列表中的元素顺序,并使用这些反转后的元素创建一个新的列表对象
return new List<T>(this._elements.reverse());
}
/**
* 将序列中的每个元素投射到一个新形式中。
* 对数组中的每个元素进行转换,生成新的数组
* @param selector 将数组中的每个元素转换成另外的值
* @returns 新的 List 对象,包含转换后的元素
*/
public select<TOut>(
selector: (element: T, index: number) => TOut
): List<TOut> {
return new List<TOut>(this._elements.map(selector))
// 使用 map() 方法对数组中的每个元素进行转换,生成新的数组
const transformedArray = this._elements.map(selector);
// 将新数组封装成 List 对象并返回
return new List<TOut>(transformedArray);
}
/**
* 将序列的每个元素投影到一个列表中。并将得到的序列扁平化为一个序列。
* 对数组中的每个元素进行转换,并将多个新数组合并成一个数组
* @param selector 将数组中的每个元素转换成新的数组
* @returns 合并后的新数组
*/
public selectMany<TOut extends List<any>>(
selector: (element: T, index: number) => TOut
): TOut {
// 使用 aggregate() 方法对数组中的每个元素进行转换,并将多个新数组合并成一个数组
return this.aggregate(
(ac, _, i) => (
ac.addRange(
this.select(selector)
.elementAt(i)
.toArray()
),
ac
),
(accumulator, _, index) => {
// 获取当前元素对应的新数组
const selectedArray = this.select(selector).elementAt(index);
// 将新数组中的所有元素添加到累加器中
return accumulator.addRange(selectedArray.toArray());
},
new List<TOut>()
)
);
}
/**
* 通过使用默认的相等比较器对元素的类型进行比较,确定两个序列是否相等
* 比较当前列表和指定列表是否相等
* @param list 要比较的列表对象
* @returns {boolean} 如果列表相等,则返回 true否则返回 false
*/
public sequenceEqual(list: List<T>): boolean {
return this.all(e => list.contains(e))
// 调用 all 方法,传入一个谓词函数,用于对当前列表中的每个元素进行评估
// 在谓词函数中调用 contains 方法,传入当前元素和指定列表对象,以检查当前元素是否存在于指定列表中
// 如果当前列表中的所有元素都存在于指定列表中,则返回 true否则返回 false
return this.all(e => list.contains(e));
}
/**
* 返回序列中唯一的元素,如果序列中没有恰好一个元素,则抛出异常。
* 从当前列表中获取一个满足指定条件的唯一元素
* @param predicate 谓词函数,用于对列表中的每个元素进行评估
* @returns {T} 列表中唯一满足指定条件的元素
* @throws {Error} 如果列表中不恰好包含一个满足指定条件的元素,则抛出异常
*/
public single(predicate?: PredicateType<T>): T {
if (this.count(predicate) !== 1) {
throw new Error('The collection does not contain exactly one element.')
} else {
return this.first(predicate)
// 调用 count 方法,传入谓词函数,以获取满足指定条件的元素个数
const count = this.count(predicate);
// 如果元素个数不等于 1则抛出异常
if (count !== 1) {
throw new Error('The collection does not contain exactly one element.');
}
// 调用 first 方法,传入谓词函数,以获取唯一元素并返回
return this.first(predicate);
}
/**
* 返回序列中唯一元素,如果序列为空,则返回默认值;如果序列中有多个元素,此方法将抛出异常。
* 从当前列表中获取一个满足指定条件的唯一元素,如果没有元素满足条件,则返回默认值 undefined
* @param predicate 谓词函数,用于对列表中的每个元素进行评估
* @returns {T} 列表中唯一满足指定条件的元素,如果没有元素满足条件,则返回默认值 undefined
*/
public singleOrDefault(predicate?: PredicateType<T>): T {
return this.count(predicate) ? this.single(predicate) : undefined
// 如果元素个数为真值,则调用 single 方法,传入谓词函数,以获取唯一元素并返回
// 否则,返回默认值 undefined
return this.count(predicate) ? this.single(predicate) : undefined;
}
/**
* 绕过序列中指定数量的元素,然后返回剩余元素。
* 从 List 的开头跳过指定数量的元素返回剩余元素的新 List
* 如果指定数量大于 List 中的元素数,则返回一个空的 List。
* @param amount 要跳过的元素数量
* @returns 新 List
*/
public skip(amount: number): List<T> {
return new List<T>(this._elements.slice(Math.max(0, amount)))
}
/**
* 省略序列中最后指定数量的元素,然后返回剩余的元素
* 返回由源 List 中除了最后指定数量的元素之外的所有元素组成的 List
* @param amount 要跳过的元素数。
* @returns 由源 List 中除了最后指定数量的元素之外的所有元素组成的 List。
*/
public skipLast(amount: number): List<T> {
return new List<T>(this._elements.slice(0, -Math.max(0, amount)))
return new List<T>(this._elements.slice(0, -Math.max(0, amount)));
}
/**
* 只要指定条件为真,就绕过序列中的元素,然后返回剩余元素。
* 从 List 的开头开始,跳过符合指定谓词的元素,返回剩余元素。
* @param predicate 用于测试每个元素是否应跳过的函数。
* @returns 一个新 List包含源 List 中从跳过元素之后到末尾的元素。
*/
public skipWhile(predicate: PredicateType<T>): List<T> {
// aggregate() 函数接收一个函数作为参数,将该函数应用于 List 的每个元素,并在每次应用后返回一个累加器的值。
// 此处使用 aggregate() 函数来计算从 List 的开头开始符合指定谓词的元素个数。
return this.skip(
this.aggregate(ac => (predicate(this.elementAt(ac)) ? ++ac : ac), 0)
)
);
}
/**
* 计算通过对输入序列的每个元素调用转换函数获得的数值序列的和
* 计算数组中所有元素的和
* @param transform 可选参数,用于将数组中的每个元素转换成另外的值进行计算
* @returns 数组的和
*/
public sum(): number
public sum(
transform: (value?: T, index?: number, list?: T[]) => number
): number
public sum(
transform?: (value?: T, index?: number, list?: T[]) => number
): number {
return transform
? this.select(transform).sum()
: this.aggregate((ac, v) => (ac += +v), 0)
// 如果提供了 transform 函数,则使用 select() 方法将每个元素转换成新的值,并调用 sum() 方法计算新数组的和
if (transform) {
return this.select(transform).sum();
}
// 如果没有提供 transform 函数,则使用 aggregate() 方法计算数组的和
// 这里使用加号 + 将元素转换为数值型
return this.aggregate((ac, v) => (ac += +v), 0);
}
/**
* 从序列的开返回指定数量的连续元素。
* 从 List 的开返回指定数量的连续元素。
* @param amount 要返回的元素数量
* @returns 一个新的 List其中包含原始 List 中开头的指定数量的元素
*/
public take(amount: number): List<T> {
return new List<T>(this._elements.slice(0, Math.max(0, amount)))
// 使用 slice() 函数截取原始 List 中的指定数量的元素
return new List<T>(this._elements.slice(0, Math.max(0, amount)));
}
/**
* 从序列的末尾返回指定数目的连续元素
* 从列表末尾开始获取指定数量的元素,返回一个新的 List 对象
* @param amount 需要获取的元素数量。
* @returns 一个新的 List 对象,包含从末尾开始的指定数量的元素。
*/
public takeLast(amount: number): List<T> {
return new List<T>(this._elements.slice(-Math.max(0, amount)))
// Math.max(0, amount) 确保 amount 大于 0如果 amount 是负数,则返回 0。
// slice() 方法从数组的指定位置开始提取元素,返回一个新的数组。
// 此处使用 slice() 方法返回 List 中末尾指定数量的元素。
return new List<T>(this._elements.slice(-Math.max(0, amount)));
}
/**
* 返回序列中的元素,只要指定的条件为真
* 从 List 的开头开始取出符合指定谓词的元素,直到不符合为止,返回这些元素组成的 List
* @param predicate 用于测试每个元素是否符合条件的函数。
* @returns 符合条件的元素组成的 List。
*/
public takeWhile(predicate: PredicateType<T>): List<T> {
// aggregate() 函数接收一个函数作为参数,将该函数应用于 List 的每个元素,并在每次应用后返回一个累加器的值。
// 此处使用 aggregate() 函数来计算从 List 的开头开始符合指定谓词的元素个数。
return this.take(
this.aggregate(ac => (predicate(this.elementAt(ac)) ? ++ac : ac), 0)
)
);
}
/**
* 复制列表中的元素到一个新数组。
*/
public toArray(): T[] {
return this._elements
return this._elements;
}
/**
* 创建一个<dictionary>从List< T>根据指定的键选择器函数。
* 将数组转换为字典,根据指定的键和值对元素进行分组并返回一个新的字典
* @param key 指定的键,用于分组
* @param value 可选参数,指定的值,用于分组后的元素的值;如果未指定,则默认使用原始元素
* @returns 分组后的元素组成的新的字典
*/
public toDictionary<TKey>(
key: (key: T) => TKey
): List<{ Key: TKey; Value: T }>
public toDictionary<TKey, TValue>(
key: (key: T) => TKey,
value: (value: T) => TValue
): List<{ Key: TKey; Value: T | TValue }>
public toDictionary<TKey, TValue>(
public toDictionary<TKey, TValue = T>(
key: (key: T) => TKey,
value?: (value: T) => TValue
): List<{ Key: TKey; Value: T | TValue }> {
return this.aggregate((dicc, v, i) => {
// 使用 select() 方法获取元素的键和值,并将其添加到字典中
dicc[
this.select(key)
.elementAt(i)
.toString()
] = value ? this.select(value).elementAt(i) : v;
] = value ? this.select(value).elementAt(i) : v;
// 将键和值添加到结果列表中
dicc.add({
Key: this.select(key).elementAt(i),
Value: value ? this.select(value).elementAt(i) : v
});
return dicc
}, new List<{ Key: TKey; Value: T | TValue }>())
return dicc;
}, new List<{ Key: TKey; Value: T | TValue }>());
}
/**
* 创建一个Set从一个Enumerable.List< T>。
* 将数组转换为一个 Set 对象
* @returns Set 对象,其中包含了数组中的所有元素
*/
public toSet() {
let result = new Set();
@@ -572,39 +714,44 @@ module es {
}
/**
* 创建一个List< T>从一个Enumerable.List< T>。
*/
public toList(): List<T> {
return this
}
/**
* 创建一个查找TElement>从一个IEnumerable< T>根据指定的键选择器和元素选择器函数。
* 将数组转换为一个查找表,根据指定的键对元素进行分组并返回一个包含键值对的对象
* @param keySelector 指定的键,用于分组
* @param elementSelector 可选参数,指定的值,用于分组后的元素的值;如果未指定,则默认使用原始元素
* @returns 包含键值对的对象,其中键为分组后的键,值为分组后的元素组成的数组
*/
public toLookup<TResult>(
keySelector: (key: T) => string | number,
elementSelector: (element: T) => TResult
): { [key: string]: TResult[] } {
return this.groupBy(keySelector, elementSelector)
return this.groupBy(keySelector, elementSelector);
}
/**
* 基于谓词过滤一系列值。
* 根据指定的条件,筛选数组中的元素并返回一个新的数组
* @param predicate 指定的条件
* @returns 新的数组,其中包含了数组中所有满足条件的元素
*/
public where(predicate: PredicateType<T>): List<T> {
return new List<T>(this._elements.filter(predicate))
return new List<T>(this._elements.filter(predicate));
}
/**
* 指定的函数应用于两个序列的对应元素,生成结果序列。
* 根据指定的函数将两个数组合并成一个新的数组
* @param list 要合并的数组
* @param result 指定的函数,用于将两个元素合并为一个
* @returns 合并后的新数组
*/
public zip<U, TOut>(
list: List<U>,
result: (first: T, second: U) => TOut
): List<TOut> {
return list.count() < this.count()
? list.select((x, y) => result(this.elementAt(y), x))
: this.select((x, y) => result(x, list.elementAt(y)))
if (list.count() < this.count()) {
// 如果要合并的数组的长度小于当前数组的长度,就使用要合并的数组的长度进行循环迭代
return list.select((x, y) => result(this.elementAt(y), x));
} else {
// 如果要合并的数组的长度大于或等于当前数组的长度,就使用当前数组的长度进行循环迭代
return this.select((x, y) => result(x, list.elementAt(y)));
}
}
}
@@ -616,7 +763,7 @@ module es {
export class OrderedList<T> extends List<T> {
constructor(elements: T[], private _comparer: (a: T, b: T) => number) {
super(elements);
this._elements.sort(this._comparer)
this._elements.sort(this._comparer); // 对元素数组进行排序
}
/**
@@ -627,7 +774,7 @@ module es {
return new OrderedList(
this._elements,
composeComparers(this._comparer, keyComparer(keySelector, false))
)
);
}
/**
@@ -638,7 +785,7 @@ module es {
return new OrderedList(
this._elements,
composeComparers(this._comparer, keyComparer(keySelector, true))
)
);
}
}
}