找回密码
马上加入

QQ登录

只需一步,快速开始

搜索
发新帖

0

收听

0

听众

39

主题

昨晚Q群的旋转容器,有需要的自取

IP属地:四川省成都市
发表于 2024-7-10 14:26:39 | 查看: 1043| 回复: 15
--- What level can you understand my code?Damn!
--- Created by Lua Lee.
--- DateTime: 2024/7/9 20:38
---

TestUi = {}

local _instance = nil
TestUi.__index = TestUi
local BaseUi = SL:Require("alg/dev/ui/Base/BaseUi.lua", true)

-- 创建
function TestUi:new()
    if not _instance then
        _instance = setmetatable(BaseUi:new("TestUi", nil, "测试UI", nil, nil, nil), TestUi)
        _instance.childrens = {} -- 所有子控件
        _instance.nowRadian = {} -- 当前弧度
        _instance.nowWeight = {} -- 当前权重(用来控制每个元素的状态,比如颜色,透明度,大小等)
        _instance.isAutoScrolling = false   -- 是否自动滚动
        _instance.autoScrollSpeed = 20 -- 自动滚动速度
        _instance.changeAngle = 0 -- 改变的角度
        _instance.changeOffset = 0 -- 改变的偏移量
        _instance.endRadian = 0 -- 结束弧度
        _instance.touchStartLocation = 0 -- 接触开始的位置
        _instance.touchMoveStartLocation = 0 -- 滚动位置
        _instance.lastIndex = 0 -- 上一个索引
        _instance.currentIndex = 0 -- 当前下标
        _instance.viewCount = 8 -- 控件数量
        -- 椭圆参数
        _instance.ellipseParam = {
            centerX = _instance.containerSize.width / 2,
            centerY = _instance.containerSize.height / 2,
            a = 300,
            b = 100,
        }

    end
    _instance:init()
    return _instance
end

-- 计算椭圆各个控件的落点坐标
function TestUi:getEllipsePointAt(radian)
    return {
        x = _instance.ellipseParam.a * math.cos(radian) + _instance.ellipseParam.centerX,
        y = _instance.ellipseParam.b * math.sin(radian) + _instance.ellipseParam.centerY,
    }
end

-- 弧度转角度
function TestUi:radianToAngle(radian)
    return radian * 180 / math.pi
end

-- 角度转弧度
function TestUi:angleToRadian(angle)
    return angle * math.pi / 180
end

-- 获取真实角度
function TestUi:getRealAngle(index)
    local realAngle = math.floor(_instance.nowRadian[index] * 180 / math.pi) % 360
    if realAngle < 0 then
        realAngle = 360 - math.abs(realAngle)
    end
    return realAngle
end

-- 计算权重
function TestUi:getWeight(realAngle)
    local weight = realAngle - 90
    weight = 5 - math.abs(weight / 45)
    if realAngle > 180 then
        weight = math.abs(weight - 1)
        weight = weight + 1
    end
    if weight < 1 then
        weight = 1
    end
    return weight
end
-- 跟随权重变化绘制变大变小或者透明
function TestUi:drawEffect(index)
    local realAngle = _instance:getRealAngle(index)
    local weight = _instance:getWeight(realAngle)
    GUI:setScale(_instance.childrens[index], 1 / weight)
    GUI:setLocalZOrder(_instance.childrens[index], 10 - math.abs(weight))
end
-- 初始化界面
function TestUi:initView()
    for i = 1, _instance.viewCount do
        local radian = (math.pi * 2) / _instance.viewCount * i
        local view = GUI:Image_Create(_instance.container, "img" .. i, _instance:getEllipsePointAt(radian).x, _instance:getEllipsePointAt(radian).y, string.format("res/public/word_fubentg_%d.png", i))
        GUI:setAnchorPoint(view, 0.5, 0.5)
        _instance.nowRadian[i] = radian
        _instance.childrens[i] = view
        local angle = _instance:radianToAngle(radian)
        -- 将270°的元素赋值为currentIndex
        if angle >= 269 and angle <= 271 then
            _instance.currentIndex = i
            _instance.lastIndex = _instance.currentIndex
        end
        _instance:drawEffect(i)
    end
end

-- 根据偏移量或者当前弧度
function TestUi:getRadianFromOffset(offset)
    if offset ~= 0 then
        return math.atan(offset / _instance.ellipseParam.b)
    else
        return 0
    end
end
-- 处理鼠标松开
function TestUi:handleMouseRelease()
    local a = 360.0 / (#_instance.childrens * 2)
    local angle = _instance:radianToAngle(_instance.endRadian)
    local p = math.floor(angle / a)

    if p < 0 then
        p = p % 2 ~= 0 and (p - 1) / 2 or p / 2
    else
        p = p % 2 ~= 0 and (p + 1) / 2 or p / 2
    end
    -- 这里用取余的方式保证索引不超过table下标,并且table下标从1开始
    _instance.currentIndex = (_instance.currentIndex - p - 1) % #_instance.childrens + 1
    -- 自动滚动到对应索引
    _instance:scrollToIndex()
end

-- 调整所有子元素的
function TestUi:moveIndexs(offset)
    local offsetRadian = _instance:getRadianFromOffset(offset)
    local length = #_instance.childrens
    for i = 1, length do
        _instance.nowRadian[i] = _instance.nowRadian[i] + offsetRadian
        if i == _instance.currentIndex then
            _instance.endRadian = _instance.endRadian + offsetRadian
        end
        GUI:setPosition(_instance.childrens[i], _instance:getEllipsePointAt(_instance.nowRadian[i]).x, _instance:getEllipsePointAt(_instance.nowRadian[i]).y)
        _instance:drawEffect(i)
    end
end

function TestUi:scrollToIndex()
    _instance.isAutoScrolling = true
    _instance.autoScrollSpeed = 10
    _instance.changeAngle = 270 - _instance:getRealAngle(_instance.currentIndex)
    _instance.changeAngle = _instance:angleToRadian(_instance.changeAngle)
    _instance.changeOffset = _instance.ellipseParam.b * math.tan(_instance.changeAngle)
    _instance.changeOffset = _instance.changeOffset / _instance.autoScrollSpeed
    _instance.changeAngle = _instance.changeAngle / _instance.autoScrollSpeed

    -- 开启定时器 自动滚到到当前记录的控件索引位置
    SL:schedule(_instance.container, function()
        if _instance.isAutoScrolling then
            local realAngle = _instance:getRealAngle(_instance.currentIndex)
            if realAngle <= 271.0 and realAngle >= 269.0 then
                _instance.lastIndex = _instance.currentIndex
                _instance.isAutoScrolling = false
            end
            _instance:moveIndexs(_instance.changeAngle)
        end
    end, 1 / 60)

end
-- 处理鼠标开始移动的逻辑
function TestUi:handleMouseMove(location)
    local moveX = location.x
    local offset = moveX - _instance.touchMoveStartLocation
    _instance.touchMoveStartLocation = moveX
    _instance:moveIndexs(offset)
end
-- 注册事件(这里996我找了很久没有找到鼠标按下拖动获取坐标偏移量的触发事件,不知道有没有大神能搞一个,我这里用的cocos的注册事件,但是非常不好用,这里还需要优化)
function TestUi:registerEvent()
    GUI:setTouchEnabled(_instance.container, true)
    local listener = cc.EventListenerTouchOneByOne:create()
    -- 注册按下(开始)事件处理函数
    listener:registerScriptHandler(function(touch, event)
        local location = touch:getLocation()
        _instance.touchMoveStartLocation = location.x
        _instance.touchStartLocation = _instance.touchMoveStartLocation
        _instance.endRadian = 0
        -- 在此处理按下(开始)事件的逻辑
        return true  -- 返回 true 表示消费了触摸事件,不再传递给下层的节点
    end, cc.Handler.EVENT_TOUCH_BEGAN)

    -- 注册移动事件处理函数
    listener:registerScriptHandler(function(touch, event)
        local location = touch:getLocation()
        -- 在此处理移动事件的逻辑
        _instance:handleMouseMove(location)
    end, cc.Handler.EVENT_TOUCH_MOVED)

    -- 注册抬起(离开)事件处理函数
    listener:registerScriptHandler(function(touch, event)
        local location = touch:getLocation()
        -- 在此处理抬起(离开)事件的逻辑
        SL:release_print("Touch ended at: ", location.x, location.y)
        _instance:handleMouseRelease()
    end, cc.Handler.EVENT_TOUCH_ENDED)

    -- 将监听器添加到精灵节点上
    local eventDispatcher = _instance.container:getEventDispatcher()
    eventDispatcher:addEventListenerWithSceneGraphPriority(listener, _instance.container)

    -- 关闭窗口移除事件
    SL:RegisterLUAEvent(LUA_EVENT_CLOSEWIN, "TestUi", function()
        -- 移除触摸事件监听
        local eventDispatcher = _instance.container:getEventDispatcher()
        eventDispatcher:removeEventListenersForTarget(_instance.container)
    end)

end
function TestUi:init()
    _instance:initView()
    _instance:registerEvent()
end

TestUi:new()
发表于 2024-7-17 17:14:46 IP属地:四川省成都市
还有人看这个贴子么?记得直接用996官方客户端的函数
GUI:addOnTouchEvent(view,function(sender,eventType) end)函数接管我上面写的cocos触摸事件
然后用
GUI:getTouchBeganPosition(sender);可以获取到触摸点起始位置
GUI:getTouchMovePosition(sender); 可以获取到移动的位置
GUI:getTouchEndPosition(sender);可以获取到结束位置
具体使用案例也可以参考一下alg客户端框架的alg/main/ui.lua文件里的写法

回复 显示全部楼层 道具 举报

发表于 2024-7-10 15:01:10 IP属地:江苏省徐州市

大佬牛B

回复 显示全部楼层 道具 举报

发表于 2024-7-10 15:36:17 IP属地:山东省临沂市

:victory:

回复 显示全部楼层 道具 举报

发表于 2024-7-10 18:04:37 IP属地:陕西省西安市
优秀

回复 显示全部楼层 道具 举报

发表于 2024-7-10 18:45:07 IP属地:河南省新乡市

nb

回复 显示全部楼层 道具 举报

发表于 2024-7-10 18:53:00 IP属地:广东省深圳市

感谢分享,论坛有你真棒

回复 显示全部楼层 道具 举报

发表于 2024-7-10 21:18:19 IP属地:江苏省徐州市
感谢分享,论坛有你真棒

回复 显示全部楼层 道具 举报

发表于 2024-7-11 10:39:24 IP属地:辽宁省大连市

感谢分享,论坛有你真棒

回复 显示全部楼层 道具 举报

发表于 2024-7-11 12:52:49 IP属地:湖南省邵阳市

大佬牛逼

回复 显示全部楼层 道具 举报

发表于 2024-7-16 17:33:49 IP属地:山东省济南市

有没有大佬发个gif看看效果。现在没法开游戏,

回复 显示全部楼层 道具 举报

您需要登录后才可以回帖 登录 | 马上加入

QQ|Archiver|手机版|小黑屋|alg阿灵戈社区 ( 苏ICP备2023026137号-1|苏ICP备2023026137号-1 )

GMT+8, 2025-3-13 03:33 , Processed in 1.996886 second(s), 33 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表