cocoscreator

cocoscreator循环滚动控件,选择日期选择时间

在网上找了一下没看到有人分享这种类型的控件,都是无限滚动的控件。所以自己动手写了一个,效果大概这样在这里插入图片描述

//循环滚动组件,实现循环滚动效果
const {ccclass, property} = cc._decorator;

const biggistRotation = 90
//摩擦力
const friction = 0.98
//自动滚动时间
const autoMoveTime = 0.05
@ccclass
export default class LoopScrow extends cc.Component
{
    @property({tooltip:"滚动节点",type:cc.Node})
    item:cc.Node = null
    @property({tooltip:"滚动节点父节点",type:cc.Node})
    content:cc.Node = null
    @property({tooltip:"显示节点数,最好为奇数"})
    showItemNum = 0
    @property({tooltip:"惯性大小,取值0~1"})
    inertiaScale = 1

    //触摸事件ID
    _touchId = null
    //滚动节点初始化时开始位置
    _startPosY = 0
    //上次触摸位置
    _lastPos = null
    //滚动节点列表
    _scrollItem:Array<cc.Node> = []
    //中间item位置
    _centerItemIndex = 0
    //更新节点回调
    _onUpdateItem!:(data, item: cc.Node) => void
    //滚动视图数据
    _dataList = []
    //中心位置数据索引
    _dataIndex = 0
    //滚动速度
    _scrollSpeed = 0
    //开始触摸时间
    _startTouchTime = 0
    //开始滚动
    _startMove = false
    //自动滚动
    _startAutoMove = false
    //是否循环滚动
    _isLoopScroll = true
    //不是循环滚动的话,滑动回弹上限
    _scrollBiggestLength = 0

    onLoad(){
        this.item.active = false
        if(this.inertiaScale < 0){
            this.inertiaScale = 0
        }else if(this.inertiaScale > 1){
            this.inertiaScale = 1
        }
    }

    start(){
        this.node.on(cc.Node.EventType.TOUCH_START,this.onEventStart,this);
        this.node.on(cc.Node.EventType.TOUCH_END,this.onEventEnd,this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE,this.onEventMove,this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL,this.onEventCancel,this)
        this._startPosY = this.content.height/2 + this.item.height/2
        this._centerItemIndex = Math.floor((this.showItemNum+2)/2)
        this._scrollBiggestLength = Math.floor(this.showItemNum/2)*this.item.height
        this.init()
    }

    update(dt){
        for (let i = 0; i < this._scrollItem.length; i++) {
            const element = this._scrollItem[i];
            this.updateItemVal(element)
        }
        if(this._scrollSpeed > 0){
            this._scrollSpeed -= friction*dt
            if(this._scrollSpeed <= 0){
                this._scrollSpeed = 0
            }
        }else if(this._scrollSpeed < 0){
            this._scrollSpeed += friction*dt
            if(this._scrollSpeed >= 0){
                this._scrollSpeed = 0
            }
        }else{
            if(this._startMove){
                this.scrollEnd()
                this._startMove = false
            }
        }
        if(this._scrollSpeed !== 0){
            this.scrollMove(this._scrollSpeed*dt*1000)
        }
    }

    onEventStart(event:cc.Touch){
        if(event.getID() != this._touchId && this._touchId != null){
            return
        }
        if(this._startAutoMove){
            return
        }
        this._touchId = event.getID()
        this._lastPos = event.getLocation()
        this._startTouchTime = new Date().getTime()
        this._scrollSpeed = 0
    }
 
    onEventEnd(event:cc.Touch){
        if(event.getID() != this._touchId){
            return
        }
        if(this._startAutoMove){
            return
        }
        this._touchId = null
        let nowPos = event.getLocation()
        let startPos = event.getStartLocation()
        this._scrollSpeed = (nowPos.y - startPos.y)/(new Date().getTime()-this._startTouchTime)
        if(this._scrollSpeed > 1.4){
            this._scrollSpeed = 1.4
        }else if(this._scrollSpeed < -1.4){
            this._scrollSpeed = -1.4
        }
        this._scrollSpeed *= this.inertiaScale
        this._startMove = true
    }
 
    onEventMove(event:cc.Touch){
        if(event.getID() != this._touchId){
            return
        }
        if(this._startAutoMove){
            return
        }
        this.scrollMove(event.getLocation().y - this._lastPos.y)
        this._lastPos = event.getLocation()
    }
 
    onEventCancel(event:cc.Touch){
        if(event.getID() != this._touchId){
            return
        }
        if(this._startAutoMove){
            return
        }
        this._touchId = null
        let nowPos = event.getLocation()
        let startPos = event.getStartLocation()
        this._scrollSpeed = (nowPos.y - startPos.y)/(new Date().getTime()-this._startTouchTime)
        if(this._scrollSpeed > 1.4){
            this._scrollSpeed = 1.4
        }else if(this._scrollSpeed < -1.4){
            this._scrollSpeed = -1.4
        }
        this._scrollSpeed *= this.inertiaScale
        this._startMove = true
    }

    init(){
        for (let i = 0; i < this.showItemNum + 2; i++) {
            let item = cc.instantiate(this.item)
            item.active = true
            item.parent = this.content
            item.position = cc.v3(0,this._startPosY - i*this.item.height,0)
            this._scrollItem[this._scrollItem.length] = item
            //初始化节点数据
            this.updateItem(i,item)
        }
    }

    /**
     * 初始化数据
     * @param dataList 数据列表
     * @param onUpdateItem 更新节点回调 (节点数据,节点)
     * @param startIndex 滚动节点开始的位置
     */
    initData(dataList,onUpdateItem:(data, item: cc.Node) => void,startIndex:number = 0){
        if(!onUpdateItem){
            cc.error("LoopScrow.initData:","滚动更新节点回调为空")
        }
        if(!dataList || dataList.length === 0){
            cc.error("LoopScrow.initData:","dataList为空")
        }
        if(startIndex<0||startIndex>=dataList.length){
            cc.error("LoopScrow.initData:","startIndex取值不正确,应该在数据列表长度范围内")
        }
        this._dataList = dataList
        this._onUpdateItem = onUpdateItem
        this._dataIndex = startIndex
        if(this._dataList.length <= this.showItemNum){
            this._isLoopScroll = false
        }
    }

    /**
     * 滚动视图
     * @param dir 向上滚动dir>0,向下滚动dir<0
     */
    scrollMove(dir){
        let tempDir = dir
        while (tempDir > 5) {
            this.moveItem(dir,5)
            tempDir -= 5
        }
        this.moveItem(dir,tempDir)
    }

    moveItem(dir,length){
        if(this._isLoopScroll){
            for (let i = 0; i < this._scrollItem.length; i++) {
                const element = this._scrollItem[i];
                element.y += length
            }
            if(dir>0){
                if(this._scrollItem[this._centerItemIndex + 1].y >= 0){
                    //调整节点位置
                    this.changeItem(dir,this._scrollItem[this._centerItemIndex + 1].y)
                }
            }else{
                if(this._scrollItem[this._centerItemIndex - 1].y <= 0){
                    //调整节点位置
                    this.changeItem(dir,this._scrollItem[this._centerItemIndex - 1].y)
                }
            }
        }else{
            if((this._dataIndex === 0 && dir<=0)||
            (this._dataIndex === this._dataList.length - 1 && dir>=0)){
                this._scrollSpeed = 0
                if(this._scrollItem[this._centerItemIndex].y > -this._scrollBiggestLength && 
                    this._scrollItem[this._centerItemIndex].y < this._scrollBiggestLength){
                        for (let i = 0; i < this._scrollItem.length; i++) {
                            const element = this._scrollItem[i];
                            element.y += length
                        }
                    }
                return
            }
            for (let i = 0; i < this._scrollItem.length; i++) {
                const element = this._scrollItem[i];
                element.y += length
            }
            if(dir>0){
                if(this._scrollItem[this._centerItemIndex + 1].y >= 0){
                    //调整节点位置
                    this.changeItem(dir,this._scrollItem[this._centerItemIndex + 1].y)
                }
            }else{
                if(this._scrollItem[this._centerItemIndex - 1].y <= 0){
                    //调整节点位置
                    this.changeItem(dir,this._scrollItem[this._centerItemIndex - 1].y)
                }
            }
        }
    }

    /**
     * 调整节点位置(向上滚动的时候,将头部节点移动到尾部,向下滚动的时候,将尾部节点移动到头部)
     * @param dir 向上滚动dir>0,向下滚动dir<0
     * @param middleItemPos 中心节点的位置
     */
    changeItem(dir,middleItemPos){
        if(dir>0){
            let item = this._scrollItem.shift()
            this._scrollItem[this._scrollItem.length] = item
            item.y = this._startPosY - (this._scrollItem.length - 1)*this.item.height + middleItemPos
            this._dataIndex++
            if(this._dataIndex >= this._dataList.length){
                this._dataIndex = 0
            }
            this.updateItem(this._scrollItem.length - 1,item)
        }else{
            let item = this._scrollItem.pop()
            this._scrollItem.splice(0,0,item)
            item.y = this._startPosY + middleItemPos
            this._dataIndex--
            if(this._dataIndex < 0){
                this._dataIndex = this._dataList.length - 1
            }
            this.updateItem(0,item)
        }
    }

    /**
     * 更新节点数据
     * @param i 索引
     * @param item 节点
     */
    updateItem(i,item){
        let index = i - this._centerItemIndex + this._dataIndex
        if(this._isLoopScroll){
            if(index < 0){
                index += this._dataList.length
            }else if(index >= this._dataList.length){
                index -= this._dataList.length
            }
        }
        if(this._onUpdateItem){
            this._onUpdateItem(this._dataList[index],item)
        }
    }

    updateItemVal(item:cc.Node){
        let y = item.y
        if(y > this._startPosY){
            y = this._startPosY
        }else if(y < -this._startPosY){
            y = -this._startPosY
        }
        item.eulerAngles = cc.v3((y/this._startPosY)*biggistRotation,0,0)
        item.opacity = 255 - Math.abs(y)
        item.scale = 1 - Math.abs(y/this._startPosY)*0.3
    }

    /**滚动停止 */
    scrollEnd(){
        this._startAutoMove = true
        let moveLength = this.item.height - Math.abs(this._scrollItem[this._centerItemIndex].y)
        if(this._isLoopScroll){
            if(this._scrollItem[this._centerItemIndex].y > this.item.height/2){  //向上自动滚动一格
                for (let i = 0; i < this._scrollItem.length; i++) {
                    const element = this._scrollItem[i];
                    if(i === this._scrollItem.length - 1){
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y + moveLength,element.position.z)})
                        .call(()=>{
                            this.changeItem(1,0)
                            this._startAutoMove = false
                        })
                        .start()
                    }else{
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y + moveLength,element.position.z)}).start()
                    }
                }
            }else if(this._scrollItem[this._centerItemIndex].y < -this.item.height/2){  //向下自动滚动一格
                for (let i = 0; i < this._scrollItem.length; i++) {
                    const element = this._scrollItem[i];
                    if(i === this._scrollItem.length - 1){
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y - moveLength,element.position.z)})
                        .call(()=>{
                            this.changeItem(-1,0)
                            this._startAutoMove = false
                        })
                        .start()
                    }else{
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y - moveLength,element.position.z)}).start()
                    }
                }
            }else{   //滚动回中间
                for (let i = 0; i < this._scrollItem.length; i++) {
                    const element = this._scrollItem[i];
                    if(i === this._scrollItem.length - 1){
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y - this._scrollItem[this._centerItemIndex].y,element.position.z)})
                        .call(()=>{
                            this._startAutoMove = false
                        })
                        .start()
                    }else{
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y - this._scrollItem[this._centerItemIndex].y,element.position.z)}).start()
                    }
                }
            }
        }else{
            if(this._scrollItem[this._centerItemIndex].y > this.item.height/2 && this._dataIndex < this._dataList.length - 1){  //向上自动滚动一格
                for (let i = 0; i < this._scrollItem.length; i++) {
                    const element = this._scrollItem[i];
                    if(i === this._scrollItem.length - 1){
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y + moveLength,element.position.z)})
                        .call(()=>{
                            this.changeItem(1,0)
                            this._startAutoMove = false
                        })
                        .start()
                    }else{
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y + moveLength,element.position.z)}).start()
                    }
                }
            }else if(this._scrollItem[this._centerItemIndex].y < -this.item.height/2 && this._dataIndex > 0){  //向下自动滚动一格
                for (let i = 0; i < this._scrollItem.length; i++) {
                    const element = this._scrollItem[i];
                    if(i === this._scrollItem.length - 1){
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y - moveLength,element.position.z)})
                        .call(()=>{
                            this.changeItem(-1,0)
                            this._startAutoMove = false
                        })
                        .start()
                    }else{
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y - moveLength,element.position.z)}).start()
                    }
                }
            }else{   //滚动回中间
                for (let i = 0; i < this._scrollItem.length; i++) {
                    const element = this._scrollItem[i];
                    if(i === this._scrollItem.length - 1){
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y - this._scrollItem[this._centerItemIndex].y,element.position.z)})
                        .call(()=>{
                            this._startAutoMove = false
                        })
                        .start()
                    }else{
                        cc.tween(element).to(autoMoveTime,{position:cc.v3(element.position.x,element.position.y - this._scrollItem[this._centerItemIndex].y,element.position.z)}).start()
                    }
                }
            }
        }
    }
}



应用代码

import LoopScrow from "./LoopScrow";


const {ccclass, property} = cc._decorator;

@ccclass
export default class LoopScrowTest extends cc.Component {
    @property(LoopScrow)
    loopScrow:LoopScrow = null;

    onLoad () {
        let onUpdateItem:any = (data, item: cc.Node) =>
        {
            if (data == null) 
            {
                item.active = false
                return;
            }
            item.active = true
            let label = item.getComponent(cc.Label);
            label.string = data;
        }
        let dataList = []
        for (let i = 0; i < 30; i++) {
            dataList[dataList.length] = i
        }
        this.loopScrow.initData(dataList,onUpdateItem,0)
    }

    start () {

    }

    // update (dt) {}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值