Tutorial Request: Delay Animation



  • I'm trying to learn DrawBot (and Python) and I'm having a hard time trying to replicate an animation I saw on Twitter. Here it is: https://tixy.land (it's the first one)

    Here is what I wrote so far:

    canvasSize = 500
    circleCount = 10
    circleSize = canvasSize / circleCount
    offset = circleCount * circleSize
    frameCount = 24
    rowCount = 10
    
    for frame in range(frameCount):
        newPage(canvasSize, canvasSize)
        frameDuration(1/frameCount)
        circleScale = cos(pi * frame / frameCount)
    
        translate(canvasSize/2, circleSize/2)
        
        for row in range(rowCount):
            save()
            for i in range(circleCount + 1):
                save()
                translate(i * circleSize)
                scale(circleScale, center=(-circleSize/2 - offset/2, 0))
                oval(-circleSize - offset/2, -circleSize/2, circleSize, circleSize)
                restore()
            restore()
            translate(0, circleSize)
            
    saveImage("~/Desktop/circleTest.gif")
    

    And this is the output:
    circleTest.gif

    I'm not sure how to make the animation for each row start at a different frame so that it has that wave effect. Is it possible to progressively delay the start of each row animation? Or is that not the right approach here?


  • admin

    a lot is happening at the same time 🙂

    I hope the example is clear enough!

    # seperate width and height
    canvasWidth = 300
    rowCount = 10
    circleCount = 10
    # calculate circleSize based on the width and the amount circles
    circleSize = canvasWidth / circleCount
    # must be even
    frameCount = 24
    # calcualte the height based on the circle size and rows
    canvasHeight = circleSize * rowCount
    
    
    # start loop
    for frame in range(frameCount-1):    
        # calculate a factor, number between 0 - 1
        # going from 0 - 1 - 0
        frameFactor = frame / (frameCount) * 2        
        if frameFactor > 1:
           frameFactor = 2 - frameFactor 
        # create a page
        newPage(canvasWidth, canvasHeight)
        # draw a white background
        with savedState():
            fill(1)
            rect(0, 0, canvasWidth, canvasHeight)
        # translate half of the circle size
        translate(circleSize/2, circleSize/2)
        # start a loop for each row
        for row in range(rowCount):
            # get the scale base factor, a number between 0 - 1
            circleScale = row / (rowCount - 1)
            # add the frame factor
            circleScale += frameFactor
            # normalize the circle size
            if circleScale > 1:
                circleScale = 2 - circleScale
            # adding some easein
            circleScale = circleScale * circleScale
            # start loop for each column
            for i in range(circleCount):
                # save and restore        
                with savedState():
                    # translate to the x, y of the oval
                    translate(i * circleSize, row * circleSize)
                    # scale
                    scale(circleScale)
                    # draw the oval
                    oval(-circleSize/2, -circleSize/2, circleSize, circleSize)
    # save the image
    saveImage("test.gif")
    

  • admin

    test.gif

    the resulting animated gif



  • I found this very interesting so I tried to do it without a lot of success, I ended with something like this:

    w, h = 1000, 1000
    divs = 10
    colSize, rowSize = w//divs, h//divs
    fps = 12
    seconds = 1
    duration = 1 / fps
    totalFrames = seconds * fps
    
    def circles(step):
        for x in range(0, w, colSize):
            for y in range(0, h, rowSize):
                d = rowSize * sin(y/(divs/2)+step)
                if d > 0:
                    fill(1)
                else:
                    fill(1, 0, 0)
                oval(x + colSize/2 - d/2, y + rowSize/2 - d/2 , d, d)
     
    for frame in range(totalFrames):
        newPage(w, h)
        frameDuration(duration)
        fill(0)
        rect(0, 0, w, h)
        circles(frame)
            
    saveImage("~/Desktop/circleTest.gif")
    

    I'm not understanding how the time works in the reference to achieve the smooth variation



  • Thank you frederik and eduairet! It's nice to see your approach. I tried a few more times after submiting the topic and this is what I ended up with:

    CANVAS = 500
    MARGIN = 60
    CIRCLES = 10
    CSIZE = (CANVAS / CIRCLES) - (MARGIN / CIRCLES)
    FRAMES = 96
    ROWS = CIRCLES
    
    for frame in range(FRAMES):
        newPage(CANVAS, CANVAS)
        fill(0)
        rect(0, 0, CANVAS, CANVAS)
        frameDuration(1 / 24)
        translate(0, CSIZE / 2)
        fill(1)
        
        for row in range(ROWS):
            for circle in range(CIRCLES):
                save()
                translate(circle * CSIZE)
                scale(sin(pi * frame / FRAMES + circle / CIRCLES), center=(CSIZE / 2 + MARGIN / 2, MARGIN / 2))
                oval(MARGIN / 2, -CSIZE / 2 + MARGIN / 2, CSIZE, CSIZE)
                restore()
            translate(0, CSIZE)
            
    saveImage("~/Desktop/circleTest.gif")
    

    The resulting .gif:
    circleTest.gif


  • admin

    cool !



  • @vitorcarvalho wow, this is lovely!!!


Log in to reply