Day 19 of the Anvil Advent Calendar
Build a web app every day until Christmas, with nothing but Python!
Decorate a Virtual Cookie
Last year, I built an app that uses the Canvas API to make mess-free, no-bake virtual Christmas cookies. This year, I spruced up the app so you can now take a photo of your deliciously real cookies and decorate them virtually. The FileLoader component allows you to upload a photo, or on a device with a camera, you can take your own!
Check out my app and decorate your cookies by following the link below. And keep reading to see how I built the app.
https://cookie-photo-decorator.anvil.app/
Preparing the Image
Images taken or uploaded by the user can be any size, which doesn’t work well for the app. We want to make sure the decorations actually get added on top of the cookie! The first step is then to resize the image before it’s displayed on the Canvas. This is done in a server module using Pillow:
@anvil.server.callable
def resize_img(file):
#convert the file to a Pillow Image
img = Image.open(io.BytesIO(file.get_bytes()))
img = img.resize((300, 300))
#convert to an Anvil media object
bs = io.BytesIO()
img.save(bs, format="PNG")
return anvil.BlobMedia("image/png", bs.getvalue())
Making Lots of Circles
I made a simple cookie decorator using the Canvas component by just building circles and triangles of different sizes and colors. By adding more elements, the app could easily be extended to add more options or be more complicated.
Because my app makes extensive use of circles, I first defined a function to draw a circle. The function takes in the desired x and y coordinates of the circle and its radius as arguments:
def draw_circle(self, x, y, radius):
c = self.canvas_1
c.begin_path()
c.arc(x, y, radius, 0, 2 * math.pi)
c.close_path()
This is called when making the sprinkles and snowman.
Adding Random Sprinkles
In the form_show
event, self.c_width
and self.c_height
are set as the width and height as the Canvas component. The x and y coordinates for the sprinkles are chosen randomly based on the size of the canvas each time the sprinkles_button
is clicked:
import random
...
def sprinkles_button_click(self, **event_args):
"""This method is called when the button is clicked"""
#randomly choose from red, green, blue, and yellow
color = random.choice(('#e62325', '#34bc6e', '#79a6f6', '#ffb000'))
self.canvas_1.fill_style = color
#randomly pick coordinates over the cookie
x_list = list(range(int(self.c_width/2-150), int(self.c_width/2+150)))
x_list = random.sample(x_list, 15)
y_list = list(range(int(self.c_height/2-250), int(self.c_height/2+50)))
y_list = random.sample(y_list, 15)
for x, y in zip(x_list, y_list):
self.draw_circle(x, y, 6)
self.canvas_1.fill()
Christmas Tree Triangles
For the Christmas tree, I just made three overlapping green triangles that get progressively smaller as they move up the y-axis. The following code draws one triangle:
c = self.canvas_1
c.fill_style = '#00884b'
c.begin_path()
c.move_to(self.c_width/2-80, self.c_height/2-20)
c.line_to(self.c_width/2+80, self.c_height/2-20)
c.line_to(self.c_width/2,self.c_height/2-120)
c.close_path()
c.fill()
You can check out the entire source code by cloning the app:
Give the Gift of Python
Share this post: