【cocos creator】拖拽排序列表

news2025/2/14 3:53:54

请添加图片描述

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
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2297688.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设备智能化无线通信,ESP32-C2物联网方案,小尺寸芯片实现大功能

在科技飞速发展的当下&#xff0c;我们的生活正被各类智能设备悄然改变&#xff0c;它们如同一位位无声的助手&#xff0c;渗透到我们生活的每一个角落&#xff0c;让生活变得更加便捷和丰富多彩。 智能插座、智能照明和简单家电设备在家居领域的应用&#xff0c;为我们的生活…

Unity 增量打包AssetBundle

背景 打包太慢了&#xff0c;想要没改动的资源不重新打包浪费时间。 来源 官方文章&#xff1a;https://forum.unity.com/threads/about-incremental-build-and-asset-bundle-hashes.1436032/ 官网AB介绍&#xff1a;https://learn.unity.com/tutorial/assets-resources-and…

MindStudio制作MindSpore TBE算子(四)算子测试(ST测试-Ascend910B/ModelArts)--失败尝试

上一节&#xff0c;MindStudio制作MindSpore TBE算子&#xff08;三&#xff09;算子测试&#xff08;ST测试&#xff09;&#xff0c;因此缺乏对应的硬件环境导致无法进行ST测试&#xff0c;导致难以自安&#xff0c;今天搞来Ascend910B服务器来填坑&#xff0c;看看是否是硬件…

transformer 基础知识

概要&#xff1a;简要记录 Encoder-Decoder 架构、seq2seq 模型、Attention 机制 Encoder & Decoder encoder 接收输入&#xff0c;生成一个固定长度的上下文向量&#xff08;编码器生成的最终隐藏状态&#xff09;&#xff1b;decoder 接收上下文向量&#xff08;或状态…

机器学习(李宏毅)——self-Attention

一、前言 本文章作为学习2023年《李宏毅机器学习课程》的笔记&#xff0c;感谢台湾大学李宏毅教授的课程&#xff0c;respect&#xff01;&#xff01;&#xff01; 二、大纲 何为self-Attention&#xff1f;原理剖析self-Attention VS CNN、RNN、GNN 三、何为self-Attenti…

实现限制同一个账号最多只能在3个客户端(有电脑、手机等)登录(附关键源码)

如上图&#xff0c;我的百度网盘已登录设备列表&#xff0c;有一个手机&#xff0c;2个windows客户端。手机设备有型号、最后登录时间、IP等。windows客户端信息有最后登录时间、操作系统类型、IP地址等。这些具体是如何实现的&#xff1f;下面分别给出android APP中采集手机信…

伺服报警的含义

前言&#xff1a; 大家好&#xff0c;我是上位机马工&#xff0c;硕士毕业4年年入40万&#xff0c;目前在一家自动化公司担任软件经理&#xff0c;从事C#上位机软件开发8年以上&#xff01;我们在开发C#的运动控制程序的时候&#xff0c;一个必要的步骤就是设置伺服报警信号的…

蓝桥杯-洛谷刷题-day5(C++)(为未完成)

1.P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布 i.题目 ii.代码 #include <iostream> #include <string> using namespace std;int N, Na, Nb; //0-"剪刀", 1-"石头", 2-"布", 3-"蜥", 4-"斯"&#xff1…

LVS 负载均衡集群(NAT模式)

一、环境准备 四台主机&#xff08;一台 LVS、两台 RS、一台客户端&#xff09; 1.1.LVS 主机 LVS 主机&#xff08;两块网卡&#xff09; 第一块&#xff1a;NAT模式&#xff08;内网&#xff09; 第二块&#xff1a;添加网卡&#xff08;仅主机模式&#xff09;&#xff0…

解决 DeepSeek 官网服务器繁忙的实用方案

解决 DeepSeek 官网服务器繁忙的实用方案 大家在使用 DeepSeek 时&#xff0c;是不是经常遇到官网服务器繁忙&#xff0c;等半天都加载不出来的情况&#xff1f;别担心&#xff0c;今天就给大家分享一个用 DeepSeek 硅基流动 Cherry Studio 解决这个问题的实用方案&#xff…

嵌入式八股文面试题(二)C语言算法

相关概念请查看文章&#xff1a;C语言概念。 1. 如何实现一个简单的内存池&#xff1f; 简单实现&#xff1a; #include <stdio.h> #include <stdlib.h>//内存块 typedef struct MemoryBlock {void *data; // 内存块起始地址struct MemoryBlock *next; // 下一个内…

#渗透测试#批量漏洞挖掘#LiveBos UploadFile 任意文件上传漏洞

免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停止本文章读。 目录 漏洞背景 漏洞成因 影响评估 检测方案 …

ds-download-link 插件:以独特图标选择,打造文章下载链接

源码介绍 “ds-download-link”插件为 WordPress 网站提供了在文章编辑器中添加下载链接的功能&#xff0c;每个下载链接都支持图标选择&#xff0c;并能将这些链接以美观的样式展示在文章前端页面。以下是该插件的主要特性和功能&#xff1a; 后台功能 在文章编辑器下方添加…

判断函数是否为react组件或lazy包裹的组件

function Modal(){return <p>123</p> } 实参里填入函数名,是false 实参里填入标签形式的函数,是true isValidElement(Modal)//false isValidElement(<Modal></Modal>)//true 官方说明 isValidElement – React 中文文档 但是官方并不建议用isValidE…

PHP 中的除以零错误

除以零错误&#xff08;Division by zero&#xff09;是指数字除以零的情况&#xff0c; 这在数学上是未定义的。在 PHP 中&#xff0c;处理这种错误的方式取决于 PHP 版本&#xff1a; PHP 7&#xff1a; 使用 / 运算符会产生一个警告 (E_WARNING) 并返回 false。 使用 intd…

【QT】控件 -- 多元素类 | 容器类 | 布局类

&#x1f525; 目录 一、多元素类1. List Widget -- 列表2. Table Widget -- 表格3. Tree Widget -- 树形 二、容器类1. Group Box -- 分组框2. Tab Widget -- 标签页 三、布局类1. 垂直布局【使用 QVBoxLayout 管理多个控件】【创建两个 QVBoxLayout】 2. 水平布局【使用 QHBo…

NO.15十六届蓝桥杯备战|while循环|六道练习(C++)

while循环 while语法形式 while 语句的语法结构和 if 语句⾮常相似&#xff0c;但不同的是 while 是⽤来实现循环的&#xff0c; if 是⽆法实现循环的。 下⾯是 while 循环的语法形式&#xff1a; //形式1 while ( 表达式 )语句; //形式2 //如果循环体想包含更多的语句&a…

kotlin标准库里面也有很多java类

Kotlin 标准库中确实存在许多与 Java 类直接关联或基于 Java 类封装的结构&#xff0c;但这并不是“问题”&#xff0c;而是 Kotlin 与 JVM 生态深度兼容和互操作性的体现。以下从技术原理和设计哲学的角度详细解释&#xff1a; 一、Kotlin 与 JVM 的底层关系 Kotlin 代码最终…

Flutter 双屏双引擎通信插件加入 GitCode:解锁双屏开发新潜能

在双屏设备应用场景日益丰富的当下&#xff0c;移动应用开发领域迎来了新的机遇与挑战。如何高效利用双屏设备优势&#xff0c;为用户打造更优质的交互体验&#xff0c;成为开发者们关注的焦点。近日&#xff0c;一款名为 Flutter 双屏双引擎通信插件的创新项目正式入驻 GitCod…

01、单片机上电后没有正常运行怎么办

单片机上电后没有运转, 首先要检查什么? 1、单片机供电是否正常? &电路焊接检查 如果连最基本的供电都没有,其它都是空谈啊!检查电路断路了没有?短路了没有?电源合适吗?有没有虚焊? 拿起万用表之前,预想一下测量哪里?供电电压应该是多少?对PCB上电压测量点要…