# 添加旋转转盘
This commit is contained in:
parent
b3de7b808d
commit
58d626b437
@ -65,7 +65,7 @@ export class BezierCurveAnimation extends Component {
|
|||||||
/** 更新事件 */
|
/** 更新事件 */
|
||||||
@property({
|
@property({
|
||||||
displayName: '更新事件',
|
displayName: '更新事件',
|
||||||
tooltip: '(当前缓动曲线Y_yN, 当前缓动下标_indexN)',
|
tooltip: '(当前缓动曲线Y_yN, 当前缓动下标_indexN, 总曲线Y_yN)',
|
||||||
type: [cc.EventHandler]
|
type: [cc.EventHandler]
|
||||||
})
|
})
|
||||||
updateEventAS: cc.EventHandler[] = [];
|
updateEventAS: cc.EventHandler[] = [];
|
||||||
@ -162,14 +162,16 @@ export class BezierCurveAnimation extends Component {
|
|||||||
let timeRangeN = timeRatioNs[tweenIndexN] - lastTimeRatioN;
|
let timeRangeN = timeRatioNs[tweenIndexN] - lastTimeRatioN;
|
||||||
/** 曲线位置 */
|
/** 曲线位置 */
|
||||||
let posN = (ratioN - lastTimeRatioN) / timeRangeN;
|
let posN = (ratioN - lastTimeRatioN) / timeRangeN;
|
||||||
/** 曲线位置 */
|
/** 当前曲线 Y */
|
||||||
let yN = curveFS[tweenIndexN](posN);
|
let currCurveYN = curveFS[tweenIndexN](posN);
|
||||||
|
/** 总曲线 Y */
|
||||||
|
let totalCurveYN = currCurveYN * timeRangeN + lastTimeRatioN;
|
||||||
// 缓动切换事件触发
|
// 缓动切换事件触发
|
||||||
if (lastTweenIndexN !== tweenIndexN) {
|
if (lastTweenIndexN !== tweenIndexN) {
|
||||||
this.emit('tweenSwitchEventAS', lastTweenIndexN);
|
this.emit('tweenSwitchEventAS', lastTweenIndexN);
|
||||||
}
|
}
|
||||||
// 更新事件触发
|
// 更新事件触发
|
||||||
this.emit('updateEventAS', yN, tweenIndexN);
|
this.emit('updateEventAS', currCurveYN, tweenIndexN, totalCurveYN);
|
||||||
// 更新缓动下标
|
// 更新缓动下标
|
||||||
lastTweenIndexN = tweenIndexN;
|
lastTweenIndexN = tweenIndexN;
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,8 @@ const { ccclass, property, requireComponent, executeInEditMode } = _decorator;
|
|||||||
|
|
||||||
/** 旋转抽奖方向 */
|
/** 旋转抽奖方向 */
|
||||||
export enum RollingLotteryDirection {
|
export enum RollingLotteryDirection {
|
||||||
/** 竖 */
|
竖,
|
||||||
VERTICAL,
|
横
|
||||||
/** 横 */
|
|
||||||
HORIZONTAL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 循环滚动抽奖 */
|
/** 循环滚动抽奖 */
|
||||||
@ -19,15 +17,15 @@ export class RollingLottery extends Component {
|
|||||||
/* --------------- 属性 --------------- */
|
/* --------------- 属性 --------------- */
|
||||||
/** 滚动方向 */
|
/** 滚动方向 */
|
||||||
@property({ displayName: '滚动方向', type: cc.Enum(RollingLotteryDirection) })
|
@property({ displayName: '滚动方向', type: cc.Enum(RollingLotteryDirection) })
|
||||||
dire = RollingLotteryDirection.VERTICAL;
|
dire = RollingLotteryDirection.竖;
|
||||||
|
|
||||||
/** 子节点刷新事件 */
|
/** 子节点刷新事件 */
|
||||||
@property({ displayName: '子节点刷新事件', tooltip: '(子节点_node, 下标_indexN)', type: cc.EventHandler })
|
@property({ displayName: '子节点刷新事件', tooltip: '(子节点_node, 下标_indexN)', type: cc.EventHandler })
|
||||||
itemUpdateEvent = new cc.EventHandler();
|
itemUpdateEvent = new cc.EventHandler();
|
||||||
|
|
||||||
/** 中心节点变更事件 */
|
/** 当前下标变更事件 */
|
||||||
@property({ displayName: '中心节点变更事件', tooltip: '(下标_indexN, 跳过状态_jumpB)', type: cc.EventHandler })
|
@property({ displayName: '当前下标变更事件', tooltip: '(下标_indexN, 跳过状态_jumpB)', type: cc.EventHandler })
|
||||||
centerNodeEvent = new cc.EventHandler();
|
indexChangeEvent = new cc.EventHandler();
|
||||||
|
|
||||||
/** 滚动结束事件 */
|
/** 滚动结束事件 */
|
||||||
@property({ displayName: '滚动结束事件', type: cc.EventHandler })
|
@property({ displayName: '滚动结束事件', type: cc.EventHandler })
|
||||||
@ -83,17 +81,20 @@ export class RollingLottery extends Component {
|
|||||||
get tailNode() {
|
get tailNode() {
|
||||||
return this.node.children[0];
|
return this.node.children[0];
|
||||||
}
|
}
|
||||||
/** 当前中心下标 */
|
/** 当前下标 */
|
||||||
get currIndexN() {
|
get currIndexN() {
|
||||||
return this._currIndexN;
|
return this._currIndexN;
|
||||||
}
|
}
|
||||||
set currIndexN(valueN_) {
|
set currIndexN(valueN_) {
|
||||||
this.setCurrIndexN(valueN_);
|
this._setCurrIndexN(valueN_);
|
||||||
}
|
}
|
||||||
/* ------------------------------- get/set ------------------------------- */
|
/* ------------------------------- get/set ------------------------------- */
|
||||||
setCurrIndexN(valueN_: number) {
|
private _setCurrIndexN(valueN_: number) {
|
||||||
|
if (valueN_ === this._currIndexN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this._currIndexN = valueN_;
|
this._currIndexN = valueN_;
|
||||||
this.centerNodeEvent.emit([this._currIndexN, this._jumpB]);
|
this.indexChangeEvent.emit([this._currIndexN, this._jumpB]);
|
||||||
// logger.log('当前选中', this._currIndexN);
|
// logger.log('当前选中', this._currIndexN);
|
||||||
}
|
}
|
||||||
/* ------------------------------- 生命周期 ------------------------------- */
|
/* ------------------------------- 生命周期 ------------------------------- */
|
||||||
@ -103,7 +104,96 @@ export class RollingLottery extends Component {
|
|||||||
this._initEvent();
|
this._initEvent();
|
||||||
}
|
}
|
||||||
/* ------------------------------- 功能 ------------------------------- */
|
/* ------------------------------- 功能 ------------------------------- */
|
||||||
/** 获取在世界坐标系下的节点包围盒(不包含自身激活的子节点范围) */
|
/** 初始化数据 */
|
||||||
|
private _initData(): void {
|
||||||
|
this.curveComp = this.node.getComponent(BezierCurveAnimation);
|
||||||
|
|
||||||
|
// 设置更新事件
|
||||||
|
let updateEvent = new cc.EventHandler();
|
||||||
|
updateEvent.component = cc.js.getClassName(this);
|
||||||
|
updateEvent.handler = '_eventUpdate';
|
||||||
|
updateEvent.target = this.node;
|
||||||
|
this.curveComp.updateEventAS.push(updateEvent);
|
||||||
|
|
||||||
|
// 设置结束事件
|
||||||
|
let endEvent = new cc.EventHandler();
|
||||||
|
endEvent.component = cc.js.getClassName(this);
|
||||||
|
endEvent.handler = '_eventEnd';
|
||||||
|
endEvent.target = this.node;
|
||||||
|
this.curveComp.endEventAS.push(endEvent);
|
||||||
|
|
||||||
|
this._resetData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化视图 */
|
||||||
|
private _initView(): void {
|
||||||
|
this.node.getComponent(cc.Layout).enabled = false;
|
||||||
|
|
||||||
|
// 初始化子节点及选中
|
||||||
|
if (this.node.children.length) {
|
||||||
|
// 重置子节点
|
||||||
|
this.node.children.forEach((v, kN) => {
|
||||||
|
v.name = String(kN + this._currIndexN);
|
||||||
|
this.itemUpdateEvent.emit([v, kN + this._currIndexN]);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.jump(this._currIndexN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化事件 */
|
||||||
|
private _initEvent(): void {
|
||||||
|
this.node.on(cc.Node.EventType.CHILD_ADDED, this._nodeChildAdded, this);
|
||||||
|
this.node.on(cc.Node.EventType.CHILD_REMOVED, this._nodeChildRemoved, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重制数据 */
|
||||||
|
private _resetData(): void {
|
||||||
|
this._currIndexN = 0;
|
||||||
|
this._ItemSize = this.node.children[0].getComponent(cc.UITransform).contentSize.clone();
|
||||||
|
|
||||||
|
// item 大小矩形,中心点在节点 (0, 0) 位置
|
||||||
|
this._parentCenterRect = cc.rect(
|
||||||
|
this.node.worldPosition.x - this._ItemSize.width * 0.5,
|
||||||
|
this.node.worldPosition.y - this._ItemSize.height * 0.5,
|
||||||
|
this._ItemSize.width,
|
||||||
|
this._ItemSize.height
|
||||||
|
);
|
||||||
|
|
||||||
|
// 重置数据
|
||||||
|
this._uiTransformTab = Object.create(null);
|
||||||
|
this._uiTransformTab[this.node.uuid] = this.node.getComponent(cc.UITransform);
|
||||||
|
this._selfRect = this._getBoundingBoxToWorld(this.node);
|
||||||
|
this._perimeterV3.set(cc.Vec3.ZERO);
|
||||||
|
|
||||||
|
// 更新 _uiTransformTab, _perimeterV3
|
||||||
|
let itemSize: cc.Size;
|
||||||
|
this.node.children.forEach((v1) => {
|
||||||
|
this._uiTransformTab[v1.uuid] = v1.getComponent(cc.UITransform);
|
||||||
|
itemSize = this._uiTransformTab[v1.uuid].contentSize;
|
||||||
|
this._perimeterV3.add3f(itemSize.x, itemSize.y, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重制视图 */
|
||||||
|
private _resetView(): void {
|
||||||
|
if (this.node.children.length) {
|
||||||
|
this.jump(this._currIndexN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置 */
|
||||||
|
private _reset(): void {
|
||||||
|
this._resetData();
|
||||||
|
this._resetView();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取在世界坐标系下的节点包围盒(不包含自身激活的子节点范围)
|
||||||
|
* @param node_ 目标节点
|
||||||
|
* @param outRect_ 输出矩形
|
||||||
|
* @returns 输出矩形
|
||||||
|
*/
|
||||||
private _getBoundingBoxToWorld(node_: cc.Node, outRect_ = cc.rect()): cc.Rect {
|
private _getBoundingBoxToWorld(node_: cc.Node, outRect_ = cc.rect()): cc.Rect {
|
||||||
let uiTransform = this._uiTransformTab[node_.uuid];
|
let uiTransform = this._uiTransformTab[node_.uuid];
|
||||||
cc.Mat4.fromRTS(this._tempM4, node_.getRotation(), node_.getPosition(), node_.getScale());
|
cc.Mat4.fromRTS(this._tempM4, node_.getRotation(), node_.getPosition(), node_.getScale());
|
||||||
@ -117,13 +207,20 @@ export class RollingLottery extends Component {
|
|||||||
return outRect_;
|
return outRect_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新节点下标 */
|
/**
|
||||||
|
* 更新节点下标
|
||||||
|
* @param node_ 目标节点
|
||||||
|
* @param indexN_ 下标
|
||||||
|
*/
|
||||||
private _updateNodeIndex(node_: cc.Node, indexN_: number): void {
|
private _updateNodeIndex(node_: cc.Node, indexN_: number): void {
|
||||||
node_.name = String(indexN_);
|
node_.name = String(indexN_);
|
||||||
this.itemUpdateEvent.emit([node_, indexN_]);
|
this.itemUpdateEvent.emit([node_, indexN_]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 上到下移动子节点 */
|
/**
|
||||||
|
* 上到下移动子节点
|
||||||
|
* @param distN_ 距离
|
||||||
|
*/
|
||||||
private _moveNodeTopToBottom(distN_: number): void {
|
private _moveNodeTopToBottom(distN_: number): void {
|
||||||
this.node.children.forEach((v, kN) => {
|
this.node.children.forEach((v, kN) => {
|
||||||
this._temp.currTransform = this._uiTransformTab[v.uuid];
|
this._temp.currTransform = this._uiTransformTab[v.uuid];
|
||||||
@ -183,7 +280,10 @@ export class RollingLottery extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 下到上移动子节点 */
|
/**
|
||||||
|
* 下到上移动子节点
|
||||||
|
* @param distN_ 距离
|
||||||
|
*/
|
||||||
private _moveNodeBottomToTop(distN_: number): void {
|
private _moveNodeBottomToTop(distN_: number): void {
|
||||||
this.node.children.forEach((v, kN) => {
|
this.node.children.forEach((v, kN) => {
|
||||||
this._temp.currTransform = this._uiTransformTab[v.uuid];
|
this._temp.currTransform = this._uiTransformTab[v.uuid];
|
||||||
@ -242,129 +342,193 @@ export class RollingLottery extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 左到右移动子节
|
||||||
|
* @param distN_ 距离
|
||||||
|
*/
|
||||||
|
private _moveNodeLeftToRight(distN_: number): void {
|
||||||
|
this.node.children.forEach((v, kN) => {
|
||||||
|
this._temp.currTransform = this._uiTransformTab[v.uuid];
|
||||||
|
this._temp.updatePosB = false;
|
||||||
|
this._getBoundingBoxToWorld(v, this._temp.currNodeRect);
|
||||||
|
|
||||||
|
// 移动坐标
|
||||||
|
this._temp.currNodeRect.x += distN_;
|
||||||
|
|
||||||
|
// 相交则更新节点坐标
|
||||||
|
if (this._temp.currNodeRect.intersects(this._selfRect)) {
|
||||||
|
this._temp.updatePosB = true;
|
||||||
|
}
|
||||||
|
// 若不相交则超出范围
|
||||||
|
else {
|
||||||
|
// 若节点在左方则跳过更新
|
||||||
|
if (this._temp.currNodeRect.xMax < this._selfRect.xMin) {
|
||||||
|
this._temp.updatePosB = true;
|
||||||
|
} else {
|
||||||
|
// (超出范围 / 周长) + 超出视图区域的 1
|
||||||
|
this._temp.outOfRangeMultipleN =
|
||||||
|
Math.floor((this._temp.currNodeRect.xMin - this._selfRect.xMax) / this._perimeterV3.x) + 1;
|
||||||
|
|
||||||
|
// 更新坐标
|
||||||
|
this._temp.currNodeRect.x -= this._temp.outOfRangeMultipleN * this._perimeterV3.x;
|
||||||
|
v.worldPosition = cc.v3(
|
||||||
|
this._temp.currNodeRect.x + this._ItemSize.width * this._temp.currTransform.anchorX,
|
||||||
|
v.worldPosition.y
|
||||||
|
);
|
||||||
|
|
||||||
|
// 更新 item 下标
|
||||||
|
this._updateNodeIndex(
|
||||||
|
v,
|
||||||
|
Number(v.name) - this._temp.outOfRangeMultipleN * this.node.children.length
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新节点坐标
|
||||||
|
if (this._temp.updatePosB) {
|
||||||
|
v.worldPosition = cc.v3(
|
||||||
|
this._temp.currNodeRect.x + this._temp.currNodeRect.width * this._temp.currTransform.anchorX,
|
||||||
|
v.worldPosition.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新当前下标
|
||||||
|
this._temp.currIndexN = Number(v.name);
|
||||||
|
|
||||||
|
if (
|
||||||
|
this._temp.currIndexN < this._currIndexN &&
|
||||||
|
cc.Rect.intersection(this._temp3Rect, this._temp.currNodeRect, this._parentCenterRect).width >=
|
||||||
|
this._parentCenterRect.width * 0.5
|
||||||
|
) {
|
||||||
|
this.currIndexN = this._temp.currIndexN;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 右到左移动子节
|
||||||
|
* @param distN_ 距离
|
||||||
|
*/
|
||||||
|
private _moveNodeRightToLeft(distN_: number): void {
|
||||||
|
this.node.children.forEach((v, kN) => {
|
||||||
|
this._temp.currTransform = this._uiTransformTab[v.uuid];
|
||||||
|
this._temp.updatePosB = false;
|
||||||
|
this._getBoundingBoxToWorld(v, this._temp.currNodeRect);
|
||||||
|
|
||||||
|
// 移动坐标
|
||||||
|
this._temp.currNodeRect.x += distN_;
|
||||||
|
|
||||||
|
// 相交则更新节点坐标
|
||||||
|
if (this._temp.currNodeRect.intersects(this._selfRect)) {
|
||||||
|
this._temp.updatePosB = true;
|
||||||
|
}
|
||||||
|
// 若不相交则超出范围
|
||||||
|
else {
|
||||||
|
// 若节点在右方则跳过更新
|
||||||
|
if (this._temp.currNodeRect.xMin > this._selfRect.xMax) {
|
||||||
|
this._temp.updatePosB = true;
|
||||||
|
} else {
|
||||||
|
// (超出范围 / 周长) + 超出视图区域的 1
|
||||||
|
this._temp.outOfRangeMultipleN =
|
||||||
|
Math.floor((this._selfRect.xMin - this._temp.currNodeRect.xMax) / this._perimeterV3.x) + 1;
|
||||||
|
|
||||||
|
// 更新坐标
|
||||||
|
this._temp.currNodeRect.x += this._temp.outOfRangeMultipleN * this._perimeterV3.x;
|
||||||
|
v.worldPosition = cc.v3(
|
||||||
|
this._temp.currNodeRect.x + this._ItemSize.width * this._temp.currTransform.anchorX,
|
||||||
|
v.worldPosition.y
|
||||||
|
);
|
||||||
|
|
||||||
|
// 更新 item 下标
|
||||||
|
this._updateNodeIndex(
|
||||||
|
v,
|
||||||
|
Number(v.name) + this._temp.outOfRangeMultipleN * this.node.children.length
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新节点坐标
|
||||||
|
if (this._temp.updatePosB) {
|
||||||
|
v.worldPosition = cc.v3(
|
||||||
|
this._temp.currNodeRect.x + this._temp.currNodeRect.width * this._temp.currTransform.anchorX,
|
||||||
|
v.worldPosition.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新当前下标
|
||||||
|
this._temp.currIndexN = Number(v.name);
|
||||||
|
|
||||||
|
if (
|
||||||
|
this._temp.currIndexN > this._currIndexN &&
|
||||||
|
cc.Rect.intersection(this._temp3Rect, this._temp.currNodeRect, this._parentCenterRect).width >=
|
||||||
|
this._parentCenterRect.width * 0.5
|
||||||
|
) {
|
||||||
|
this.currIndexN = this._temp.currIndexN;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 滚动子节点
|
* 滚动子节点
|
||||||
* @param distV3_ 距离
|
* @param distV3_ 距离
|
||||||
*/
|
*/
|
||||||
private _scrollChild(distV3_: cc.Vec3): void {
|
private _scrollChild(distV3_: cc.Vec3): void {
|
||||||
// 左右滚动
|
// 左右滚动
|
||||||
if (this.dire === RollingLotteryDirection.HORIZONTAL) {
|
if (this.dire === RollingLotteryDirection.横) {
|
||||||
cc.error('未实现');
|
if (!distV3_.x) {
|
||||||
// ...
|
return;
|
||||||
|
}
|
||||||
|
// 从左往右
|
||||||
|
if (distV3_.x > 0) {
|
||||||
|
this._moveNodeLeftToRight(distV3_.x);
|
||||||
|
}
|
||||||
|
// 从右往左
|
||||||
|
else if (distV3_.x < 0) {
|
||||||
|
this._moveNodeRightToLeft(distV3_.x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 上下滚动
|
// 上下滚动
|
||||||
else {
|
else {
|
||||||
// 从上往下滚动
|
if (!distV3_.y) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 从上往下
|
||||||
if (distV3_.y < 0) {
|
if (distV3_.y < 0) {
|
||||||
this._moveNodeTopToBottom(distV3_.y);
|
this._moveNodeTopToBottom(distV3_.y);
|
||||||
}
|
}
|
||||||
// 从下往上滚动
|
// 从下往上
|
||||||
else if (distV3_.y > 0) {
|
else if (distV3_.y > 0) {
|
||||||
this._moveNodeBottomToTop(distV3_.y);
|
this._moveNodeBottomToTop(distV3_.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新运动距离 */
|
/**
|
||||||
|
* 更新运动距离
|
||||||
|
* @param indexN_ 目标下标
|
||||||
|
*/
|
||||||
private _updateMoveDist(indexN_: number): void {
|
private _updateMoveDist(indexN_: number): void {
|
||||||
/** 当前节点 */
|
/** 当前节点 */
|
||||||
let currNode = this.node.getChildByName(String(this._currIndexN));
|
let currNode = this.node.getChildByName(String(this._currIndexN));
|
||||||
/** 间隔格子 */
|
/** 间隔格子 */
|
||||||
let intervalN = indexN_ - this._currIndexN;
|
let intervalN = indexN_ - this._currIndexN;
|
||||||
/** 格子距离 */
|
/** 格子距离 */
|
||||||
let boxDistN = this.dire === RollingLotteryDirection.HORIZONTAL ? this._ItemSize.width : this._ItemSize.height;
|
let boxDistN = this.dire === RollingLotteryDirection.横 ? this._ItemSize.width : this._ItemSize.height;
|
||||||
/** 当前格子距父节点(0, 0)的偏移坐标 */
|
/** 当前格子距父节点(0, 0)的偏移坐标 */
|
||||||
let offsetDistV3 = this.node.worldPosition.clone().subtract(currNode.worldPosition);
|
let offsetDistV3 = this.node.worldPosition.clone().subtract(currNode.worldPosition);
|
||||||
// 设置总距离
|
// 设置总距离
|
||||||
if (this.dire === RollingLotteryDirection.HORIZONTAL) {
|
if (this.dire === RollingLotteryDirection.横) {
|
||||||
this._totalDistV3 = cc.v3(intervalN * boxDistN + offsetDistV3.x);
|
this._totalDistV3 = cc.v3(-intervalN * boxDistN + offsetDistV3.x);
|
||||||
} else {
|
} else {
|
||||||
this._totalDistV3 = cc.v3(0, intervalN * boxDistN + offsetDistV3.y);
|
this._totalDistV3 = cc.v3(0, intervalN * boxDistN + offsetDistV3.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化数据 */
|
/** 停止循环 */
|
||||||
private _initData(): void {
|
private _stopLoop(): void {
|
||||||
this.curveComp = this.node.getComponent(BezierCurveAnimation);
|
this._loopTween.stop();
|
||||||
|
this._loopTween = null;
|
||||||
// 设置更新事件
|
this._loopScrollB = false;
|
||||||
let updateEvent = new cc.EventHandler();
|
|
||||||
updateEvent.component = cc.js.getClassName(this);
|
|
||||||
updateEvent.handler = '_eventUpdate';
|
|
||||||
updateEvent.target = this.node;
|
|
||||||
this.curveComp.updateEventAS.push(updateEvent);
|
|
||||||
|
|
||||||
// 设置结束事件
|
|
||||||
let endEvent = new cc.EventHandler();
|
|
||||||
endEvent.component = cc.js.getClassName(this);
|
|
||||||
endEvent.handler = '_eventEnd';
|
|
||||||
endEvent.target = this.node;
|
|
||||||
this.curveComp.endEventAS.push(endEvent);
|
|
||||||
|
|
||||||
this._resetData();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 重制数据 */
|
|
||||||
private _resetData(): void {
|
|
||||||
this._currIndexN = 0;
|
|
||||||
this._ItemSize = this.node.children[0].getComponent(cc.UITransform).contentSize.clone();
|
|
||||||
|
|
||||||
// item 大小矩形,中心点在节点 (0, 0) 位置
|
|
||||||
this._parentCenterRect = cc.rect(
|
|
||||||
this.node.worldPosition.x - this._ItemSize.width * 0.5,
|
|
||||||
this.node.worldPosition.y - this._ItemSize.height * 0.5,
|
|
||||||
this._ItemSize.width,
|
|
||||||
this._ItemSize.height
|
|
||||||
);
|
|
||||||
|
|
||||||
// 重置数据
|
|
||||||
this._uiTransformTab = Object.create(null);
|
|
||||||
this._uiTransformTab[this.node.uuid] = this.node.getComponent(cc.UITransform);
|
|
||||||
this._selfRect = this._getBoundingBoxToWorld(this.node);
|
|
||||||
this._perimeterV3.set(cc.Vec3.ZERO);
|
|
||||||
|
|
||||||
// 更新 _uiTransformTab, _perimeterV3
|
|
||||||
let itemSize: cc.Size;
|
|
||||||
this.node.children.forEach((v1) => {
|
|
||||||
this._uiTransformTab[v1.uuid] = v1.getComponent(cc.UITransform);
|
|
||||||
itemSize = this._uiTransformTab[v1.uuid].contentSize;
|
|
||||||
this._perimeterV3.add3f(itemSize.x, itemSize.y, 0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 初始化视图 */
|
|
||||||
private _initView(): void {
|
|
||||||
this.node.getComponent(cc.Layout).enabled = false;
|
|
||||||
|
|
||||||
// 初始化子节点及选中
|
|
||||||
if (this.node.children.length) {
|
|
||||||
// 重置子节点
|
|
||||||
this.node.children.forEach((v, kN) => {
|
|
||||||
v.name = String(kN + this._currIndexN);
|
|
||||||
this.itemUpdateEvent.emit([v, kN + this._currIndexN]);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.jump(this._currIndexN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 重制视图 */
|
|
||||||
private _resetView(): void {
|
|
||||||
if (this.node.children.length) {
|
|
||||||
this.jump(this._currIndexN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 初始化事件 */
|
|
||||||
private _initEvent(): void {
|
|
||||||
this.node.on(cc.Node.EventType.CHILD_ADDED, this._nodeChildAdded, this);
|
|
||||||
this.node.on(cc.Node.EventType.CHILD_REMOVED, this._nodeChildRemoved, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 重置 */
|
|
||||||
reset(): void {
|
|
||||||
this._resetData();
|
|
||||||
this._resetView();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -392,7 +556,7 @@ export class RollingLottery extends Component {
|
|||||||
if (!this.isValid) {
|
if (!this.isValid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.dire === RollingLotteryDirection.HORIZONTAL) {
|
if (this.dire === RollingLotteryDirection.横) {
|
||||||
distV3.x = (target.valueN - target.lastValueN) * speedN_;
|
distV3.x = (target.valueN - target.lastValueN) * speedN_;
|
||||||
} else {
|
} else {
|
||||||
distV3.y = (target.valueN - target.lastValueN) * speedN_;
|
distV3.y = (target.valueN - target.lastValueN) * speedN_;
|
||||||
@ -406,14 +570,16 @@ export class RollingLottery extends Component {
|
|||||||
.start();
|
.start();
|
||||||
if (timeSN_ !== undefined) {
|
if (timeSN_ !== undefined) {
|
||||||
this.scheduleOnce(() => {
|
this.scheduleOnce(() => {
|
||||||
this._loopTween.stop();
|
this._stopLoop();
|
||||||
this._loopTween = null;
|
|
||||||
this._loopScrollB = false;
|
|
||||||
}, timeSN_);
|
}, timeSN_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 跳转到指定下标 */
|
/**
|
||||||
|
* 跳转到指定下标
|
||||||
|
* @param indexN_ 目标下标
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
jump(indexN_: number): void {
|
jump(indexN_: number): void {
|
||||||
if (this._scrollB && !this._loopScrollB) {
|
if (this._scrollB && !this._loopScrollB) {
|
||||||
return;
|
return;
|
||||||
@ -423,9 +589,7 @@ export class RollingLottery extends Component {
|
|||||||
|
|
||||||
// 停止循环滚动
|
// 停止循环滚动
|
||||||
if (this._loopScrollB) {
|
if (this._loopScrollB) {
|
||||||
this._loopTween.stop();
|
this._stopLoop();
|
||||||
this._loopTween = null;
|
|
||||||
this._loopScrollB = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新移动距离
|
// 更新移动距离
|
||||||
@ -438,7 +602,12 @@ export class RollingLottery extends Component {
|
|||||||
this._jumpB = false;
|
this._jumpB = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 滚动到指定下标 */
|
/**
|
||||||
|
* 滚动到指定下标
|
||||||
|
* @param indexN_ 目标下标
|
||||||
|
* @param scrollConfig_ 滚动配置
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
scroll(indexN_: number, scrollConfig_?: RollingLotteryScrollConfig): void {
|
scroll(indexN_: number, scrollConfig_?: RollingLotteryScrollConfig): void {
|
||||||
if (this._scrollB && !this._loopScrollB) {
|
if (this._scrollB && !this._loopScrollB) {
|
||||||
return;
|
return;
|
||||||
@ -448,9 +617,7 @@ export class RollingLottery extends Component {
|
|||||||
|
|
||||||
// 停止循环滚动
|
// 停止循环滚动
|
||||||
if (this._loopScrollB) {
|
if (this._loopScrollB) {
|
||||||
this._loopTween.stop();
|
this._stopLoop();
|
||||||
this._loopTween = null;
|
|
||||||
this._loopScrollB = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._lastCurveYN = 0;
|
this._lastCurveYN = 0;
|
||||||
@ -461,10 +628,8 @@ export class RollingLottery extends Component {
|
|||||||
}
|
}
|
||||||
/* ------------------------------- 自定义事件 ------------------------------- */
|
/* ------------------------------- 自定义事件 ------------------------------- */
|
||||||
private _eventUpdate(yN_: number, indexN_: number): void {
|
private _eventUpdate(yN_: number, indexN_: number): void {
|
||||||
cc.log(yN_, yN_);
|
if (this.dire === RollingLotteryDirection.横) {
|
||||||
if (this.dire === RollingLotteryDirection.HORIZONTAL) {
|
this._scrollChild(cc.v3((yN_ - this._lastCurveYN) * this._totalDistV3.x, 0));
|
||||||
cc.error('未实现');
|
|
||||||
// ...
|
|
||||||
} else {
|
} else {
|
||||||
this._scrollChild(cc.v3(0, (yN_ - this._lastCurveYN) * this._totalDistV3.y));
|
this._scrollChild(cc.v3(0, (yN_ - this._lastCurveYN) * this._totalDistV3.y));
|
||||||
}
|
}
|
||||||
@ -476,13 +641,14 @@ export class RollingLottery extends Component {
|
|||||||
this._scrollB = false;
|
this._scrollB = false;
|
||||||
this.scrollEndEvent.emit([]);
|
this.scrollEndEvent.emit([]);
|
||||||
this._scrollConfig.endCBF?.();
|
this._scrollConfig.endCBF?.();
|
||||||
|
// cc.log('缓动结束');
|
||||||
}
|
}
|
||||||
/* ------------------------------- 节点事件 ------------------------------- */
|
/* ------------------------------- 节点事件 ------------------------------- */
|
||||||
private _nodeChildAdded(): void {
|
private _nodeChildAdded(): void {
|
||||||
this.reset();
|
this._reset();
|
||||||
}
|
}
|
||||||
private _nodeChildRemoved(): void {
|
private _nodeChildRemoved(): void {
|
||||||
this.reset();
|
this._reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
369
assets/RotatingLottery.ts
Normal file
369
assets/RotatingLottery.ts
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
import { _decorator, Component, Node } from 'cc';
|
||||||
|
import * as cc from 'cc';
|
||||||
|
import { BezierCurveAnimation } from './BezierCurveAnimation';
|
||||||
|
const { ccclass, property, requireComponent } = _decorator;
|
||||||
|
|
||||||
|
/** 旋转抽奖方向 */
|
||||||
|
export enum RotatingLotteryDirection {
|
||||||
|
顺时针,
|
||||||
|
逆时针
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 旋转抽奖 */
|
||||||
|
@ccclass('RotatingLottery')
|
||||||
|
@requireComponent(BezierCurveAnimation)
|
||||||
|
export class RotatingLottery extends Component {
|
||||||
|
/* --------------- 属性 --------------- */
|
||||||
|
/** 旋转方向 */
|
||||||
|
@property({ displayName: '旋转方向', type: cc.Enum(RotatingLotteryDirection) })
|
||||||
|
dire: RotatingLotteryDirection = null;
|
||||||
|
|
||||||
|
/** 旋转指针 */
|
||||||
|
@property({ displayName: '旋转指针' })
|
||||||
|
rotateArrowB = false;
|
||||||
|
|
||||||
|
/** 旋转对象 */
|
||||||
|
@property({ displayName: '旋转对象', type: cc.Node })
|
||||||
|
rotateNode: cc.Node = null;
|
||||||
|
|
||||||
|
/** 内容容器 */
|
||||||
|
@property({ displayName: '内容容器', type: cc.Node })
|
||||||
|
contentNode: cc.Node = null;
|
||||||
|
|
||||||
|
/** 当前下标变更事件 */
|
||||||
|
@property({ displayName: '当前下标变更事件', tooltip: '(下标_indexN, 跳过状态_jumpB)', type: cc.EventHandler })
|
||||||
|
indexChangeEvent = new cc.EventHandler();
|
||||||
|
|
||||||
|
/** 旋转结束事件 */
|
||||||
|
@property({ displayName: '旋转结束事件', type: cc.EventHandler })
|
||||||
|
rotateEndEvent = new cc.EventHandler();
|
||||||
|
/* --------------- private --------------- */
|
||||||
|
/** 滚动状态 */
|
||||||
|
private _scrollB = false;
|
||||||
|
/** 循环滚动状态 */
|
||||||
|
private _loopScrollB = false;
|
||||||
|
/** 循环缓动 */
|
||||||
|
private _loopTween: cc.Tween<any>;
|
||||||
|
/** 当前滚动配置 */
|
||||||
|
private _scrollConfig: RotatingLotteryScrollConfig;
|
||||||
|
/** 跳过状态 */
|
||||||
|
private _jumpB = false;
|
||||||
|
/** 目标角度 */
|
||||||
|
private _targetAngleN: number;
|
||||||
|
/** 上次曲线 Y */
|
||||||
|
private _lastCurveYN = 0;
|
||||||
|
/** 内容角度区间 */
|
||||||
|
private _contentAngleNs: number[] = [];
|
||||||
|
/** 特殊角度下标 */
|
||||||
|
private _specialAngleIndexN: number;
|
||||||
|
/** 当前下标 */
|
||||||
|
private _currIndexN = 0;
|
||||||
|
/* --------------- public --------------- */
|
||||||
|
/** 曲线组件 */
|
||||||
|
curveComp: BezierCurveAnimation;
|
||||||
|
/** 当前中心下标 */
|
||||||
|
get currIndexN() {
|
||||||
|
return this._currIndexN;
|
||||||
|
}
|
||||||
|
set currIndexN(valueN_) {
|
||||||
|
this._setCurrIndexN(valueN_);
|
||||||
|
}
|
||||||
|
/* ------------------------------- get/set ------------------------------- */
|
||||||
|
private _setCurrIndexN(valueN_: number) {
|
||||||
|
if (valueN_ === this._currIndexN) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._currIndexN = valueN_;
|
||||||
|
this.indexChangeEvent.emit([this._currIndexN, this._jumpB]);
|
||||||
|
// logger.log('当前选中', this._currIndexN);
|
||||||
|
}
|
||||||
|
/* ------------------------------- 生命周期 ------------------------------- */
|
||||||
|
onLoad() {
|
||||||
|
this._initData();
|
||||||
|
this._initEvent();
|
||||||
|
}
|
||||||
|
/* ------------------------------- 功能 ------------------------------- */
|
||||||
|
/** 初始化数据 */
|
||||||
|
private _initData(): void {
|
||||||
|
this.curveComp = this.getComponent(BezierCurveAnimation);
|
||||||
|
|
||||||
|
// 设置更新事件
|
||||||
|
let updateEvent = new cc.EventHandler();
|
||||||
|
updateEvent.component = cc.js.getClassName(this);
|
||||||
|
updateEvent.handler = '_eventUpdate';
|
||||||
|
updateEvent.target = this.node;
|
||||||
|
this.curveComp.updateEventAS.push(updateEvent);
|
||||||
|
|
||||||
|
// 设置结束事件
|
||||||
|
let endEvent = new cc.EventHandler();
|
||||||
|
endEvent.component = cc.js.getClassName(this);
|
||||||
|
endEvent.handler = '_eventEnd';
|
||||||
|
endEvent.target = this.node;
|
||||||
|
this.curveComp.endEventAS.push(endEvent);
|
||||||
|
|
||||||
|
this._updateAngleRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化事件 */
|
||||||
|
private _initEvent(): void {
|
||||||
|
this.node.on(cc.Node.EventType.CHILD_ADDED, this._nodeChildAdded, this);
|
||||||
|
this.node.on(cc.Node.EventType.CHILD_REMOVED, this._nodeChildRemoved, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置 */
|
||||||
|
private _reset() {
|
||||||
|
this._updateAngleRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新角度区间 */
|
||||||
|
private _updateAngleRange(): void {
|
||||||
|
let leftNode: cc.Node;
|
||||||
|
let rightNode: cc.Node;
|
||||||
|
this.contentNode.children.forEach((v, kN) => {
|
||||||
|
// 获取左右节点
|
||||||
|
leftNode = this.contentNode.children[kN + 1 === this.contentNode.children.length ? 0 : kN + 1];
|
||||||
|
rightNode = this.contentNode.children[kN - 1 < 0 ? this.contentNode.children.length - 1 : kN - 1];
|
||||||
|
|
||||||
|
// 获取当前节点最大角度
|
||||||
|
if (leftNode.angle < v.angle) {
|
||||||
|
this._contentAngleNs[kN] =
|
||||||
|
v.angle + Math.min((360 + leftNode.angle - v.angle) * 0.5, (v.angle - rightNode.angle) * 0.5);
|
||||||
|
} else if (v.angle > rightNode.angle) {
|
||||||
|
this._contentAngleNs[kN] =
|
||||||
|
v.angle + Math.min((leftNode.angle - v.angle) * 0.5, (v.angle - rightNode.angle) * 0.5);
|
||||||
|
} else {
|
||||||
|
this._specialAngleIndexN = kN;
|
||||||
|
this._contentAngleNs[kN] =
|
||||||
|
v.angle + Math.min((leftNode.angle - v.angle) * 0.5, (v.angle + (360 - rightNode.angle)) * 0.5);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取当前下标 */
|
||||||
|
private _getCurrIndex(): number {
|
||||||
|
let angleN = this.rotateNode.angle % 360;
|
||||||
|
if (angleN < 0) {
|
||||||
|
angleN += 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
let resultN: number;
|
||||||
|
for (let kN = 0, lenN = this._contentAngleNs.length; kN < lenN; ++kN) {
|
||||||
|
if (angleN < this._contentAngleNs[kN]) {
|
||||||
|
resultN = kN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resultN === undefined) {
|
||||||
|
resultN = this._specialAngleIndexN;
|
||||||
|
}
|
||||||
|
if (!this.rotateArrowB) {
|
||||||
|
resultN = this._contentAngleNs.length - 1 - resultN;
|
||||||
|
}
|
||||||
|
return resultN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新运动角度
|
||||||
|
* @param indexN_ 目标下标
|
||||||
|
*/
|
||||||
|
private _updateMoveAngle(indexN_: number): void {
|
||||||
|
/** 目标节点角度 */
|
||||||
|
let targetNodeAngleN = this.contentNode.children[indexN_].angle;
|
||||||
|
/** 旋转节点角度 */
|
||||||
|
let rotateNodeAngleN = (this.rotateNode.angle %= 360);
|
||||||
|
|
||||||
|
// 计算最终角度
|
||||||
|
if (this.dire === RotatingLotteryDirection.顺时针) {
|
||||||
|
// 旋转指针
|
||||||
|
if (this.rotateArrowB) {
|
||||||
|
this._targetAngleN = -(360 - targetNodeAngleN) - rotateNodeAngleN;
|
||||||
|
if (this._targetAngleN > rotateNodeAngleN) {
|
||||||
|
this._targetAngleN -= 360;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 旋转转盘
|
||||||
|
else {
|
||||||
|
this._targetAngleN = -targetNodeAngleN - rotateNodeAngleN;
|
||||||
|
if (this._targetAngleN > rotateNodeAngleN) {
|
||||||
|
this._targetAngleN -= 360;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._targetAngleN %= 360;
|
||||||
|
|
||||||
|
// 添加圈数
|
||||||
|
if (!this._jumpB && this._scrollConfig) {
|
||||||
|
this._targetAngleN -= this._scrollConfig.turnN * 360;
|
||||||
|
this._targetAngleN += this._scrollConfig.offsetAngleN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 旋转指针
|
||||||
|
if (this.rotateArrowB) {
|
||||||
|
this._targetAngleN = targetNodeAngleN - rotateNodeAngleN;
|
||||||
|
if (this._targetAngleN < rotateNodeAngleN) {
|
||||||
|
this._targetAngleN += 360;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 旋转转盘
|
||||||
|
else {
|
||||||
|
this._targetAngleN = 360 - targetNodeAngleN - rotateNodeAngleN;
|
||||||
|
if (this._targetAngleN < rotateNodeAngleN) {
|
||||||
|
this._targetAngleN += 360;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._targetAngleN %= 360;
|
||||||
|
|
||||||
|
// 添加圈数
|
||||||
|
if (!this._jumpB && this._scrollConfig) {
|
||||||
|
this._targetAngleN += this._scrollConfig.turnN * 360;
|
||||||
|
this._targetAngleN += this._scrollConfig.offsetAngleN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 停止循环 */
|
||||||
|
private _stopLoop(): void {
|
||||||
|
this._loopTween.stop();
|
||||||
|
this._loopTween = null;
|
||||||
|
this._loopScrollB = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 循环滚动
|
||||||
|
* @param speedN_ 速度/秒
|
||||||
|
* @param timeSN_ 时间(秒),不填则一直滚动
|
||||||
|
*/
|
||||||
|
loop(speedN_: number, timeSN_?: number): void {
|
||||||
|
if (this._scrollB) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._scrollB = true;
|
||||||
|
this._loopScrollB = true;
|
||||||
|
let angleN: number;
|
||||||
|
this._loopTween = cc
|
||||||
|
.tween({ valueN: 0, lastValueN: 0 })
|
||||||
|
.repeatForever(
|
||||||
|
cc.tween().by(
|
||||||
|
1,
|
||||||
|
{
|
||||||
|
valueN: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onUpdate: (target?: any, ratioN?: number) => {
|
||||||
|
if (!this.isValid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
angleN = (target.valueN - target.lastValueN) * speedN_;
|
||||||
|
if (this.rotateArrowB) {
|
||||||
|
if (this.dire === RotatingLotteryDirection.顺时针) {
|
||||||
|
angleN = -angleN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
angleN = -angleN;
|
||||||
|
if (this.dire === RotatingLotteryDirection.逆时针) {
|
||||||
|
angleN = -angleN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.rotateNode.angle += angleN;
|
||||||
|
target.lastValueN = target.valueN;
|
||||||
|
this.currIndexN = this._getCurrIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.start();
|
||||||
|
if (timeSN_ !== undefined) {
|
||||||
|
this.scheduleOnce(() => {
|
||||||
|
this._stopLoop();
|
||||||
|
}, timeSN_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转到指定下标
|
||||||
|
* @param indexN_ 目标下标
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
jump(indexN_: number): void {
|
||||||
|
if (this._scrollB && !this._loopScrollB) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._scrollB = true;
|
||||||
|
this._jumpB = true;
|
||||||
|
|
||||||
|
// 停止循环滚动
|
||||||
|
if (this._loopScrollB) {
|
||||||
|
this._stopLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新角度
|
||||||
|
this._updateMoveAngle(indexN_);
|
||||||
|
|
||||||
|
// 直接跳转
|
||||||
|
this.rotateNode.angle += this._targetAngleN;
|
||||||
|
this.currIndexN = this._getCurrIndex();
|
||||||
|
this._scrollB = false;
|
||||||
|
this._jumpB = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 滚动到指定下标
|
||||||
|
* @param indexN_ 目标下标
|
||||||
|
* @param scrollConfig_ 滚动配置
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
scroll(indexN_: number, scrollConfig_?: RotatingLotteryScrollConfig): void {
|
||||||
|
if (this._scrollB && !this._loopScrollB) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._scrollB = true;
|
||||||
|
this._scrollConfig = new RotatingLotteryScrollConfig(scrollConfig_);
|
||||||
|
|
||||||
|
// 停止循环滚动
|
||||||
|
if (this._loopScrollB) {
|
||||||
|
this._stopLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新角度
|
||||||
|
this._lastCurveYN = 0;
|
||||||
|
this._updateMoveAngle(indexN_);
|
||||||
|
|
||||||
|
// 开始缓动
|
||||||
|
this.curveComp.startTween(this._scrollConfig.tweenIndexNS);
|
||||||
|
}
|
||||||
|
/* ------------------------------- 自定义事件 ------------------------------- */
|
||||||
|
private _eventUpdate(yN_: number, indexN_: number): void {
|
||||||
|
this.rotateNode.angle += this._targetAngleN * (yN_ - this._lastCurveYN);
|
||||||
|
this._lastCurveYN = yN_;
|
||||||
|
this.currIndexN = this._getCurrIndex();
|
||||||
|
// cc.log('缓动更新', yN_, indexN_, y2N_, yN_ - this._lastCurveYN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _eventEnd(): void {
|
||||||
|
this._scrollB = false;
|
||||||
|
this.rotateEndEvent.emit([]);
|
||||||
|
this._scrollConfig.endCBF?.();
|
||||||
|
// cc.log('缓动结束');
|
||||||
|
}
|
||||||
|
/* ------------------------------- 节点事件 ------------------------------- */
|
||||||
|
private _nodeChildAdded(): void {
|
||||||
|
this._reset();
|
||||||
|
}
|
||||||
|
private _nodeChildRemoved(): void {
|
||||||
|
this._reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 滚动配置 */
|
||||||
|
class RotatingLotteryScrollConfig {
|
||||||
|
constructor(init_?: RotatingLotteryScrollConfig) {
|
||||||
|
Object.assign(this, init_);
|
||||||
|
}
|
||||||
|
/** 缓动队列 */
|
||||||
|
tweenIndexNS?: number[];
|
||||||
|
/** 圈数 */
|
||||||
|
turnN? = 1;
|
||||||
|
/** 偏移角度 */
|
||||||
|
offsetAngleN? = 0;
|
||||||
|
/** 结束回调 */
|
||||||
|
endCBF?: () => void;
|
||||||
|
}
|
9
assets/RotatingLottery.ts.meta
Normal file
9
assets/RotatingLottery.ts.meta
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.22",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "584de9ca-d061-471e-b2b7-df6e403fd8ca",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
8773
assets/main.scene
8773
assets/main.scene
File diff suppressed because it is too large
Load Diff
@ -1,36 +1,67 @@
|
|||||||
import { _decorator, Component, Node } from 'cc';
|
import { _decorator, Component, Node } from 'cc';
|
||||||
import * as cc from 'cc';
|
import * as cc from 'cc';
|
||||||
import { RollingLottery } from './RollingLottery';
|
import { RollingLottery } from './RollingLottery';
|
||||||
|
import { RotatingLottery } from './RotatingLottery';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass('main')
|
@ccclass('main')
|
||||||
export class main extends Component {
|
export class main extends Component {
|
||||||
|
/** 横向滚动 */
|
||||||
|
@property({ displayName: '横向滚动', type: RollingLottery })
|
||||||
|
horizontalScroll: RollingLottery = null;
|
||||||
|
|
||||||
|
/** 竖向滚动 */
|
||||||
|
@property({ displayName: '竖向滚动', type: RollingLottery })
|
||||||
|
verticalScroll: RollingLottery = null;
|
||||||
|
|
||||||
|
/** 旋转转盘 */
|
||||||
|
@property({ displayName: '旋转转盘', type: RotatingLottery })
|
||||||
|
rotateTurntable: RotatingLottery = null;
|
||||||
|
|
||||||
|
/** 旋转指针 */
|
||||||
|
@property({ displayName: '旋转指针', type: RotatingLottery })
|
||||||
|
rotateArrow: RotatingLottery = null;
|
||||||
/* ------------------------------- segmentation ------------------------------- */
|
/* ------------------------------- segmentation ------------------------------- */
|
||||||
start() {
|
start() {
|
||||||
let comp = this.node.getComponentInChildren(RollingLottery);
|
let scrollF = async () => {
|
||||||
// comp.loop(1500);
|
let targetIndexN = Math.floor(Math.random() * 100 - 50);
|
||||||
// let indexN = 0;
|
// cc.log('滚动目标', targetIndexN);
|
||||||
// this.node.on(
|
let task = new Promise<void>((resolveF) => {
|
||||||
// cc.Node.EventType.TOUCH_END,
|
this.horizontalScroll.scroll(targetIndexN, {
|
||||||
// () => {
|
endCBF: resolveF
|
||||||
// comp.scroll(0, {});
|
});
|
||||||
// },
|
});
|
||||||
// this
|
let task2 = new Promise<void>((resolveF) => {
|
||||||
// );
|
this.verticalScroll.scroll(targetIndexN, {
|
||||||
comp.scroll(10, {});
|
endCBF: resolveF
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await Promise.all([task, task2]);
|
||||||
|
setTimeout(() => {
|
||||||
|
scrollF();
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
scrollF();
|
||||||
|
|
||||||
// comp.reset();
|
// let rotateF = async () => {
|
||||||
// comp.loop(-1500);
|
// let targetIndexN = Math.floor(Math.random() * 12);
|
||||||
// setTimeout(() => {
|
// cc.log('旋转目标', targetIndexN);
|
||||||
// comp.scroll(-10, {
|
// let task = new Promise<void>((resolveF) => {
|
||||||
// tweenIndexN: 3,
|
// this.rotateTurntable.scroll(targetIndexN, {
|
||||||
// endCBF: () => {
|
// endCBF: resolveF
|
||||||
// // comp.scroll(25, {
|
// });
|
||||||
// // tweenIndexN: 3
|
|
||||||
// // });
|
|
||||||
// }
|
|
||||||
// });
|
// });
|
||||||
// }, 3000);
|
// let task2 = new Promise<void>((resolveF) => {
|
||||||
|
// this.rotateArrow.scroll(targetIndexN, {
|
||||||
|
// endCBF: resolveF
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// await Promise.all([task, task2]);
|
||||||
|
// setTimeout(() => {
|
||||||
|
// rotateF();
|
||||||
|
// }, 1000);
|
||||||
|
// };
|
||||||
|
// rotateF();
|
||||||
}
|
}
|
||||||
/* ------------------------------- segmentation ------------------------------- */
|
/* ------------------------------- segmentation ------------------------------- */
|
||||||
eventItemUpdate(node_: cc.Node, indexN_: number): void {
|
eventItemUpdate(node_: cc.Node, indexN_: number): void {
|
||||||
@ -38,10 +69,10 @@ export class main extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
eventCenterNode(indexN_: number): void {
|
eventCenterNode(indexN_: number): void {
|
||||||
cc.log('当前下标', indexN_);
|
// cc.log('当前下标', indexN_);
|
||||||
}
|
}
|
||||||
|
|
||||||
eventScrollEnd(): void {
|
eventScrollEnd(): void {
|
||||||
cc.log('滚动结束');
|
// cc.log('滚动结束');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user