最简单的拖拽实现
基本上只要有一个 draggroup 以及一个被拖拽的 drag 元素,就能够开始拖拽了。drag 元素需要有个 xpos 以及 ypos 进行定位。
screen drag_demo_a():
draggroup:
drag:
drag_name "item-a"
xpos 100
ypos 100
text "ITEM A"
当然只是这样的话,没有什么用处。还需要使用 dragged 或者 dropped 函数,去处理拖拽之后的逻辑。
让卡牌自动回到原位
如果卡牌没有拖到正确的位置,让它自己回到原位置。
思路是,当一个 drag 元素被拖拽时,检查目标位置是否存在一个 drop,如果没有,则回到原点。
init python:
def handle_drag(drags, drop):
# 下面没有东西接着
if not drop:
drags[0].snap(drags[0].start_x, drags[0].start_y, delay = .2)
return
值得注意的是,这里的 start_x 以及 start_y 是拖拽开始的时候的位置。
如果想要拖拽一叠纸牌
This is called with the current Drag as an argument. It’s expected to return a list of [ (drag, x, y) ] tuples, giving the draggables to drag as a unit. x and y are the offsets of the drags relative to each other, they are not relative to the corner of this drag. drag is either the Drag object to be joined or the drag_name of such a Drag.
所以如果需要让 b 和 a 一起移动,那么就需要把 b 以及位置偏移也放进 list 里面。比如下面这样,当 a 被拖拽的时候,也会查找 b 然后让它跟随自己一起动。
init python:
def handle_a_drag_joined(drag):
join_list = [(drag, 0, 0)]
for _, d in drag.drag_group.children:
if d.name == "item-b":
join_list.append((d, 0, 20))
return join_list
当然,这样的话 b 起始并不是被拖动,也就是说它的 start_x 和 start_y 都是 0. 如果需要让 a 和 b 都回归原位,需要单独为 b 指定 snap 的目标坐标。
同时兼顾点击
空当接龙游戏中,如果点击一张牌,它会尝试自动移动。
好在,drag 同时支持 clicked 这个事件,并且 snap 也依然可以使用。所以只要在 clicked 事件中,调用 snap 就可以移动牌到指定位置了。
还有一件事——什么时候更新数据
要实现纸牌游戏,还需要有个全局的 object 存储纸牌的位置关系,比如某个纸牌位于哪个 list, 再计算出每张纸牌的坐标。
调用 snap 的时候,为了优雅,肯定会有个延迟。那么应该在何时更新卡牌的位置,比如从一个 list 移动到另一个 list?
嘛,还有个 snapped 回调函数,在动画结束后触发。
总结
理论上完全可行,不过做起来感觉好麻烦,有各种状态要考虑。
╮(╯_╰)╭