Как создать анимацию перемещения обьекта tkinter
Никак не могу создать функцию для анимации объекта. Надо, что бы она перемещалась от начальной точки, до конечной, которые указываются кликом мышки по полотну.
Изначально пробовал использовать matplotlib в интерфейсе tkinter(в задании указано использовать какой-то интерфейс, по этому так странно), но там тоже беда с анимацией, никак не мог разобраться. Решил попробовать сразу в tkinter`е сделать, теперь просто не могу написать функцию для плавного перемещения от одной точки к другой. Может кто-то поможет, или скажет где лучше выполнить это.
Вот как должна выглядеть анимация:
from tkinter import *
root = Tk()
# Tkinter settings
root.geometry ('400x400')
# Creating canvas and OX and OY axis
canvas = Canvas(root,width = 400, height = 400,bg = 'white')
canvas.grid(column = 4, row = 6)
canvas.create_line(200,400,200,0,width=2,arrow=LAST)
canvas.create_line(0,200,400,200,width=2,arrow=LAST)
mss_x,mss_y = [],[] #cordinates of all x`s` and y`s` separetly
coords= [] #cordinates of start and end
# To create circle
def create_circle(x, y, r, canvasName):
x0 = x - r
y0 = y - r
x1 = x + r
y1 = y + r
return canvasName.create_oval(x0, y0, x1, y1)
# To get coordinates from click and draw bresenham line
def callback(event):
if len(coords)<4:
coords.append(int(event.x))
coords.append(int(event.y))
if len(coords)==4:
DrawLine(coords[0], coords[1], coords[2], coords[3])
# Function to draw current pixel
def draw_pixel(mss_x,mss_y, i):
return canvas.create_rectangle(mss_x[i-1], mss_y[i-1], mss_x[i-1], mss_y[i-1], fill="red", outline="red")
# Bresenham algorithm
def DrawLine(x1,y1,x2,y2):
dx = abs(x2-x1)
dy = abs(y2-y1)
x=x1
y=y1
xs = 1 if x<x2 else -1
ys = 1 if y<y2 else -1
if dx>dy:
p=2*dy-dx
while x!=x2:
x=x+xs
if p > 0:
y=y+ys
p=p+2*dy-2*dx
else:
p=p+2*dy
mss_x.append(x)
mss_y.append(y)
else:
p=2*dx-dy
while y!=y2:
y+=ys
if p > 0:
x+=xs
p+=2*dx-2*dy
else:
p+=2*dx
mss_x.append(x)
mss_y.append(y)
for i in range(len(mss_x)):
draw_pixel(mss_x,mss_y,i)
def Animation(mss_x,mss_y):
c = create_circle(mss_x[0],mss_y[0], 7,canvas)
for i in range(len(mss_x)):
canvas.move(c, mss_x[i-1], mss_y[i-1])
i+=1
# while i < len(mss_x):
# canvas.move(c, mss_x[i-1], mss_y[i-1])
# root.after(40)
# i-=1
root.bind('<Button 1>',callback)
root.mainloop()
Ответы (1 шт):
Вариант реализации: берем координаты начала и конца, определяем длину отрезка, исходя из нужной длины шага считаем на какую долю от полного вертикального и горизонтального перемещения нужно сместиться на каждом шаге, далее через метод after планируем выполнение функции, которая фактически перемещает ваш кружок.
def callback(event):
if len(coords)<4:
coords.append(int(event.x))
coords.append(int(event.y))
if len(coords)==4:
DrawLine(coords[0], coords[1], coords[2], coords[3])
Animation(coords[0], coords[1], coords[2], coords[3])
...
def Animation(x1, y1, x2, y2):
dx = x2 - x1
dy = y2 - y1
length = (dx ** 2 + dy ** 2) ** .5
step = 10 # перемещение вдоль линии на 10 пикселей за раз
step_x = step / length * dx
step_y = step / length * dy
r = 7
c = create_circle(x1, y1, r, canvas)
progress = 0
def animate():
nonlocal progress
progress += step
if progress < length:
canvas.move(c, step_x, step_y) # Относительное смещение на step_x, step_y
root.after(40, animate) # Планируем выполнение функции animate через 40ms
else:
# Последнее перемещение делаем точно на конец отрезка
canvas.coords(c, x2-r, y2-r, x2+r, y2+r)
animate()

