DEMO下载
GameCtrl.ts
import ItemCtrl from "./ItemCtrl";
const { ccclass, property } = cc._decorator;
@ccclass
export default class GameCtrl extends cc.Component {
@property(cc.Node)
content: cc.Node = null;
@property(cc.Node)
prefab: cc.Node = null;
arr = []
//移动速度
moveSpeed = 0.15
//排序x间距
spacingX = 10
nodePool: cc.Node[] = []
tempId = 0
touchId = null
lastTouchId = null
isAni = false
start() {
//列表数量
let count = 8
//初始化列表
this.isAni = true
for (let i = 0; i < count; i++) {
this.scheduleOnce(() => {
this.addOne()
}, i * 0.1)
}
this.scheduleOnce(() => {
this.isAni = false
}, count * 0.1 + this.moveSpeed)
}
onAddBtnClick() {
this.addOne()
}
onRemoveBtnClick() {
if (!this.arr.length) return
let id = this.lastTouchId
let index = this.arr.findIndex((value) => { return value.id == id })
if (index == -1) id = this.arr[0].id
this.removeOneById(id)
this.upDateIndexByX(true)
}
removeOneById(id) {
let index = this.arr.findIndex((value) => { return value.id == id })
if (index == -1) return
let data = this.arr.splice(index, 1)
let node: cc.Node = data[0].node
let toPos = node.position
if (index == 0) toPos = cc.v3(node.position.x - this.prefab.width / 2, node.position.y)
cc.tween(node)
.to(this.moveSpeed, { position: toPos, scale: 1, opacity: 0 })
.call(() => {
node.stopAllActions()
node.active = false
this.nodePool.push(data[0].node)
})
.start()
}
addOne(waitTime = 0) {
let node: cc.Node = this.nodePool.shift()
if (!node) {
node = cc.instantiate(this.prefab)
node.parent = this.content
}
node.opacity = 0;
node.scale = 1
let pos = this.getItemPos(this.arr.length, this.arr.length + 1)
let id = this.tempId
let data = {
name: id,
id: id,
index: id,
node: node,
originPos: pos,
checkPos: pos
}
this.arr.push(data);
node.getComponent(ItemCtrl).initData(data, this)
node.setPosition(pos)
node.x = pos.x + this.prefab.width
node.active = true
cc.tween(node)
.delay(waitTime)
.call(() => {
this.upDateIndexByX(true)
})
.to(this.moveSpeed, { position: node.position, scale: 1, opacity: 255 })
.start()
this.tempId++
}
/**
* 获取item排序位置
* @param i
* @param totalCount
* @returns
*/
getItemPos(i, totalCount) {
let startX = -(totalCount - 1) * (this.prefab.width + this.spacingX) / 2
let pos = cc.v2(0, 0)
pos.x = startX + (this.prefab.width + this.spacingX) * i
return pos
}
getSidePos() {
let totalCount = this.arr.length
let startX = -(totalCount - 1) * (this.prefab.width + this.spacingX) / 2
let pos = cc.v2(0, 0)
let minX = startX
let maxX = startX + (this.prefab.width + this.spacingX) * (totalCount - 1)
return { minPos: cc.v2(minX, pos.y), maxPos: cc.v2(maxX, pos.y) }
}
/**
* 按照x轴大小排序
* @param isEnd 为true时候强制刷新位置
*/
upDateIndexByX(isEnd = false) {
this.arr.sort(this.sortData)
let count = this.arr.length;
for (let i = 0; i < count; i++) {
let data = this.arr[i]
if (!isEnd && data.index == i) continue;
data.index = i
let pos = this.getItemPos(i, count)
data.originPos = pos
if (data.node.getComponent(ItemCtrl).isTouch) {
continue;
}
data.checkPos = pos
cc.tween(data.node)
.to(this.moveSpeed, { position: pos })
.start()
}
}
//获取按照x轴大小
sortData(a, b) {
return a.checkPos.x - b.checkPos.x
}
}
ItemCtrl.ts
import GameCtrl from "./GameCtrl";
const { ccclass, property } = cc._decorator;
@ccclass
export default class ItemCtrl extends cc.Component {
@property(cc.Label)
desc: cc.Label = null;
data: any = {};
gameCtrl: GameCtrl = null
private _originPos: cc.Vec2;
private _startPos: any;
private oginPos: any;
isTouch = false;
start() {
this.node.zIndex = 0;
this.oginPos = this.node.position;
this.regiestNodeEvent(this.node);
}
/** 节点注册事件 */
regiestNodeEvent(node: cc.Node) {
if (!node) return;
node.on(cc.Node.EventType.TOUCH_START, this.touchStartEvent, this);
node.on(cc.Node.EventType.TOUCH_END, this.touchCancel, this);
node.on(cc.Node.EventType.TOUCH_CANCEL, this.touchCancel, this);
node.on(cc.Node.EventType.TOUCH_MOVE, this.touchMoveEvent, this);
}
/**
* 传入数据
* @param data 数据
* @param index 顺序
* @param extData 额外数据
*/
initData(data, gameCtrl) {
this.data = data;
this.desc.string = data.id + "";
this.gameCtrl = gameCtrl
}
touchStartEvent(event) {
if (this.gameCtrl.isAni) return
this.isTouch = true
console.log('touch start--------')
this._originPos = this.node.getPosition();
this._startPos = event.getLocation();
this.node.zIndex = 999;
this.node.opacity = 200;
this.gameCtrl.getComponent(GameCtrl).touchId = this.data.id
this.gameCtrl.getComponent(GameCtrl).lastTouchId = this.data.id
}
touchMoveEvent(event) {
let pos = event.getLocation();
if (!this._startPos) {
return;
}
//控制横轴移动
let offset_x = pos.x - this._startPos.x;
let toPosX = this._originPos.x + offset_x;
let getSidePos = this.gameCtrl.getSidePos()
if (toPosX < getSidePos.minPos.x) {
toPosX = getSidePos.minPos.x
}
if (toPosX > getSidePos.maxPos.x) {
toPosX = getSidePos.maxPos.x
}
this.node.x = toPosX
//控制纵轴移动
// let offset_y = pos.y - this._startPos.y;
// this.node.y = this._originPos.y + offset_y;
let isRight = this.node.x > this.data.originPos.x
let x = isRight ? (this.node.x + this.node.width / 2) : (this.node.x - this.node.width / 2)
//检测重叠超过1/2,判断为移动
this.data.checkPos = cc.v2(x, this.data.originPos.y)
this.gameCtrl.getComponent(GameCtrl).upDateIndexByX()
}
touchCancel() {
this.isTouch = false
this.gameCtrl.getComponent(GameCtrl).upDateIndexByX(true)
this.node.opacity = 255;
this.node.zIndex = 0;
this.gameCtrl.getComponent(GameCtrl).touchId = null
}
}