Skip to content

Instantly share code, notes, and snippets.

@stenson
Created February 27, 2019 01:21
Show Gist options
  • Save stenson/4b0ed476877f5b31957d532b10edc148 to your computer and use it in GitHub Desktop.
Save stenson/4b0ed476877f5b31957d532b10edc148 to your computer and use it in GitHub Desktop.
recreating the very cool typographics 2019 "speakers announced" gif with drawbot
from furniture.animation import Animation
from furniture.vfont import scale_to_axis
from grafutils.text.lockup import GlyphLockup # currently unavailable publicly, in-development
from drawBot import *
colors = [
[1.0, 0.0, 0.48],
[1.0, 0.89, 0.15],
[0.07, 0.69, 0.94],
[0.14, 0.69, 0.64],
[0.85, 0.07, 0.15],
[0.84, 0.66, 0.1],
[1.0, 0.84, 0.71],
[0.3, 0.71, 0.07],
[0.99, 0.39, 0.25],
[1.0, 0.0, 0.48],
]
colors += list(reversed(colors))[:]
# tried to calculate these automatically but loses some of the hand-made vibe of the original
wghts = (800, 750, 700, 650, 600, 550, 500, 400, 350, 320, 280, 260)
axes1 = (800, 700, 600, 500, 400, 320, 300, 260, 250, 247, 247, 200)
axes2 = (800, 700, 600, 500, 400, 320, 280, 230, 210, 200, 200, 200)
texts = ["SPEAKERS", "ANNOUNCED"]
attrs = dict(font="Obviously Variable", fontSize=280)
fs = FormattedString(**attrs)
axes = fs.listFontVariations()
wdth = axes.get("wdth")
wght = axes.get("wght")
def draw(frame):
li = frame.i//10
lir = frame.i%10
fill(1)
rect(*frame.page)
fill(*colors[li], 0.9)
rect(*frame.page)
inset = frame.page.inset(536, 0)
def slug(i, offset, align, axes, exiting):
stage = li
if exiting:
stage = 10 - (li - 9)
s = texts[i]
if align == "left":
s = s[:stage+1]
mover = stage
if align == "right":
s = s[::-1][:stage+1][::-1]
mover = 0
if stage >= len(s):
mover = 1000 # impossible
if len(s) > 0:
fs = FormattedString(**attrs, align=align)
for i, c in enumerate(s):
_stage = stage
if exiting:
if i == mover:
fs.fontVariations(
wdth=scale_to_axis(wdth, lir/10+0.2),
wght=scale_to_axis(wght, lir/10+0.2))
else:
fs.fontVariations(wdth=axes[9], wght=wghts[9])
else:
if i == mover: _stage += 1
#else: print(axes[_stage], wghts[_stage])
fs.fontVariations(wdth=axes[_stage], wght=wghts[_stage])
fs.append(c)
lockup = GlyphLockup(fs, frame.page.inset(-500, 0))
lockup.center(horizontal=False)
fill(0)
for i, g in enumerate(lockup.glyphs):
g.bp.translate(*offset)
if i == mover:
p = pow((10-lir)/10, 2)
if exiting:
p = (1 - p)*0.85
if align == "left":
g.bp.translate(p*1150)
elif align == "right":
g.bp.translate(-p*1150)
drawPath(g.bp)
else:
drawPath(g.bp)
if frame.i < 100:
slug(0, (1020, 140), "left", axes1, False)
slug(1, (-1020, -140), "right", axes2, False)
else:
slug(0, (1020, 140), "left", axes1, True)
slug(1, (-1020, -140), "right", axes2, True)
animation = Animation(draw, 200, dimensions=(1920, 1080))
animation.storyboard(frames=(45, 50))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment