from ipycanvas import Canvas, hold_canvas
import numpy as np
from math import pi, cos, sin
def draw(canvas, t):
size = 1000
step = 20
t1 = t / 1000.0
x = 0
while x < size + step:
y = 0
while y < size + step:
x_angle = y_angle = 2 * pi
angle = x_angle * (x / size) + y_angle * (y / size)
particle_x = x + 20 * cos(2 * pi * t1 + angle)
particle_y = y + 20 * sin(2 * pi * t1 + angle)
canvas.fill_circle(particle_x, particle_y, 6)
y = y + step
x = x + step
def fast_draw(canvas, t):
"""Same as draw, but using NumPy and the vectorized version of fill_circle: fill_circles"""
size = 1000
step = 20
t1 = t / 1000.0
x = np.linspace(0, size, int(size / step))
y = np.linspace(0, size, int(size / step))
xv, yv = np.meshgrid(x, y)
x_angle = y_angle = 2 * pi
angle = x_angle * (xv / size) + y_angle * (yv / size)
particle_x = xv + 20 * np.cos(2 * pi * t1 + angle)
particle_y = yv + 20 * np.sin(2 * pi * t1 + angle)
canvas.fill_circles(particle_x, particle_y, 6)
size = 1000
canvas = Canvas(width=size, height=size)
canvas.fill_style = "#fcba03"
canvas
from time import sleep
and fill_circle
¶Worst approach: Slow locally, slow using a remote server (MyBinder)
from time import sleep
for i in range(200):
with hold_canvas():
canvas.clear()
draw(canvas, i * 20.0)
sleep(20 / 1000.0)
canvas.sleep
and fill_circle
¶This caches the entire animation before sending it to the front-end. This results in a slow execution (caching), but it ensure a smooth animation on the front-end whichever the context (local or remote server).
Slow to execute, smooth animation
with hold_canvas():
for i in range(200):
canvas.clear()
draw(canvas, i * 20.0)
canvas.sleep(20)
canvas
from time import sleep
and the vectorized fill_circles
¶Super fast locally, can be fast on a remote server if the latency is correct
from time import sleep
for i in range(200):
with hold_canvas():
canvas.clear()
fast_draw(canvas, i * 20.0)
sleep(20 / 1000.0)
canvas.sleep
and the vectorized fill_circles
¶Best approach: Super fast locally, super fast on a remote server
with hold_canvas():
for i in range(200):
canvas.clear()
fast_draw(canvas, i * 20.0)
canvas.sleep(20)
Always use hold_canvas
!
As much as possible, try to use the vectorized version of the base methods if you want to exectute them multiple times (fill_circles
, fill_rects
etc).
If you can, make use of canvas.sleep
instead of from time import sleep
so that the entire animation is sent at once to the front-end, making a smoother animation whatever the server latency.