import { BaseComponent, ImageTexture } from '@uino/thing';
import { Utils } from '../common/Utils';
// generate gradient
function gradient(reversal) {
const colorArr = [];
for (let i = 0; i < 10; i++) {
let temp = 0;
if(reversal){
temp = i > 1 ? 255 : 0;
}else{
temp = i < 9 ? 255 : 0;
}
colorArr.push(...[temp, temp, temp, 255]);
}
const imageData = new Uint8Array(colorArr);
let texture = new THING.ImageTexture({ data: imageData, width: 10, height: 1 });
texture.wrapType = THING.ImageWrapType.ClampToEdge;
return texture;
}
let _gradientMap ;
let _reversalGradientMap;
/**
* 线生长动画组件类,用于通过操作UV坐标控制线条的生长动画效果。
* @class LineGrowthComponent
* @public
* @memberof THING
* @example
* // 创建并添加组件到线条
* const line = new THING.RouteLine();
* const growth = line.addComponent(THING.LineGrowthComponent);
*
* // 控制线可见范围
* growth.progress = 0.3; // 隐藏起点30%
*/
class LineGrowthComponent extends BaseComponent {
/**
* 线生长动画组件类构造函数,用于通过操作UV坐标控制线条的生长动画效果。
* @constructor
* @public
*/
constructor() {
super();
this._objectName = '';
}
/**
* When add component.
* @param {THING.BaseObject} object The object
*/
onAdd(object) {
super.onAdd(object);
_gradientMap = _gradientMap ? _gradientMap : gradient(false);
_reversalGradientMap = _reversalGradientMap ? _reversalGradientMap : gradient(true);
this._gradientMap = _gradientMap;
this._reversalGradientMap = _reversalGradientMap;
object.style.begin();
object.style.alphaMap = _gradientMap;
object.style.transparent = true;
object.style.end();
this._object = object;
this._objectName = object.name;
this._result = null;
this._reversal = false;
this._progress = 0;
}
/**
* When remove component.
*/
onRemove() {
if(this._result)
{
this._result.stop();
}
this._result = null;
super.onRemove();
this._objectName = '';
}
/**
* Calculate scale factor and update object style
* @param {number} progress - Progress value between 0 and 1
* @returns {object} - Contains scaleFactor and adjustedProgress
*/
_calculateStyleParams(progress) {
let scaleFactor;
if (this._object.uvModeType === THING.UVModeType.Tile) {
let width = 1;
switch (this._object.type) {
case 'RouteLine':
width = this._object.width;
break;
case 'PolygonLine':
width = this._object.radius * 2 * Math.PI;
break;
default:
break;
}
scaleFactor = 1 / this._object.length * width;
} else {
scaleFactor = 1;
}
// 调整进度计算逻辑
// progress = 0 时 adjustedProgress = 0.9
// progress = 1 时 adjustedProgress = -0.15
const adjustedProgress = this._reversal ?
(-0.22 + (1 - progress) * 1.05) : // 当progress=1时为-0.15,当progress=0时为0.9
(0.92 - progress * 1.05); // 当progress=0时为0.9,当progress=1时为-0.15
this._object.style.begin();
this._object.style.alphaMap = this._reversal ? this._reversalGradientMap : this._gradientMap;
this._object.style.end();
return { scaleFactor, adjustedProgress };
}
/**
* 播放线生长动画。
* @public
* @param {object} [options={}] 动画参数。
* @param {number} [options.time=1000] 动画持续时间,单位为毫秒。
* @param {number} [options.delayTime=0] 动画开始前的延迟时间。
* @param {THING.LerpType} [options.lerpType=THING.LerpType.Linear.None] 动画缓动类型。
* @param {THING.LoopType} [options.loopType] 动画循环类型。
* @param {number} [options.repeatTimes=1] 动画重复次数。
* @param {number} [options.progress=1] 动画进度值,取值范围为0到1。
* @param {Function} [options.onComplete] 动画完成时触发的回调函数。
* @param {Function} [options.complete] 动画完成时触发的备用回调函数。
* @example
* lineGrowth.play({
* time: 2000, // 动画持续2秒
* delayTime: 500, // 延迟0.5秒开始
* repeatTimes: 3, // 重复3次
* progress: 0.8 // 动画播放到线条的80%
* });
*/
play(options = {}) {
this.setProgress(0);
const time = options['time'] || 1000;
const delayTime = options['delayTime'] || 0;
const lerpType = options['lerpType'] || THING.LerpType.Linear.None;
const loopType = options['loopType'];
const repeatTimes = options['repeatTimes'] || 1;
const progress = options['progress'] || 1;
const callback = Utils.parseValue(options['onComplete'], options['complete']);
const { scaleFactor, adjustedProgress } = this._calculateStyleParams(progress);
const to = adjustedProgress;
this._object.style.imageSlotType = THING.ImageSlotType.AlphaMap;
this._object.style.uv = {
offset: [1, 0],
repeat: [scaleFactor, 1],
center: [0, 0],
rotation: 0
};
this._object.style.imageSlotType = THING.ImageSlotType.Map;
this._result = this._object.app.tweenManager.lerpTo(1, to, time, delayTime)
.times(repeatTimes)
.easing(lerpType)
.looping(loopType)
.onUpdate((ev, progress) => {
this._object.style.imageSlotType = THING.ImageSlotType.AlphaMap;
this._object.style.uv = {
offset: [this._reversal ? -ev.value : ev.value, 0],
repeat: [scaleFactor, 1],
center: [0, 0],
rotation: 0
};
this._object.style.imageSlotType = THING.ImageSlotType.Map;
})
.onComplete(ev => {
if (callback) {
callback();
}
})
.start();
}
/**
* 获取当前线生长动画进度。进度值范围为0到1。
* @public
* @type {number}
*/
get progress() {
return this._progress;
}
set progress(value) {
this.setProgress(value)
this._progress = value;
}
/**
* 设置线生长进度。
* @public
* @param {number} value - 进度值范围为0到1。
*/
setProgress(value) {
if (!this._object) return;
const progress = Math.max(0, Math.min(1, value));
const { scaleFactor, adjustedProgress } = this._calculateStyleParams(progress);
this._object.style.imageSlotType = THING.ImageSlotType.AlphaMap;
this._object.style.uv = {
offset: [this._reversal ? -adjustedProgress : adjustedProgress, 0],
repeat: [scaleFactor, 1],
center: [0, 0],
rotation: 0
};
this._object.style.imageSlotType = THING.ImageSlotType.Map;
}
/**
* 设置线生长方向是否反转。
* @public
* @type {boolean} value - 是否反转线生长方向。
*/
set reversal(value) {
this._reversal = value;
}
get reversal() {
return this._reversal;
}
}
export { LineGrowthComponent }