• papajohn

    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)
    
    
    

    posted in Pythonista read more

Internal error.

Oops! Looks like something went wrong!