I'd like to animate color changes for many rectangles at once in response to touch events. In particular, I'd like a large number of rectangles (~1000) to all be transitioning among hues in a spectrum from blue to yellow.
As a first attempt, I created a ShapeNode
for each rectangle and changed each one's fill_color
to a new value on every touch_moved
. The program runs, but only at 2 FPS on an iPad Pro.
I suspect there's a fast way to do this, perhaps using a Shader
. I couldn't figure out how to instantiate a Shader
just for the purpose of animating color changes.
My code is below, but my specific question is how I would make a rectangle gradually transition between two hues (e.g. blue to yellow) in a performant way, so that I can have many such rectangles. Thanks!
from scene import *
from ui import Path
import math
import random
from colorsys import hsv_to_rgb
YELLOW = 1/6
BLUE = 2/3
S = 24
class Grid(Scene):
def setup(self):
width = int(self.bounds.width) // S
height = int(self.bounds.height) // S
self.cells = [Cell(i, j, parent=self) for i in range(width) for j in range(height)]
def touch_moved(self, touch):
for cell in self.cells:
cell.touched += S/abs(cell.frame.center() - touch.location)**2
cell.update()
class Cell(ShapeNode):
def __init__(self, i, j, **vargs):
self.touched = 0
super().__init__(Path.rect(0, 0, S, S), 'white', position=(i*S, j*S), **vargs)
def cell_color(self):
scale = min(1, self.touched)
hue = scale * YELLOW + (1-scale) * BLUE
return hsv_to_rgb(hue, 1, 1)
def update(self):
self.fill_color = self.cell_color()
if __name__ == '__main__':
run(Grid(), show_fps=True)