Introduction
If you are familiar with using the Canvas with JavaScript, then you will quickly know how to draw on the Canvas with Python knowing a couple of minor items. If you are a Python developer new to drawing inside a browser, the example in this article will show you the basics. This example is the classic clock. Credit goes to W3 Schools for the source code that I ported to Python for this example.
The key to drawing graphics in the browser is the Canvas API [link]. I will not go into detail as there are many excellent articles on the Internet. The code should help understand what the Python interfaces are. I find it a lot easier to understand an API when I can play with working code.
The first item is to declare a region to draw within using the tag <canvas>
. This tag sets the size, location, and background of the canvas. There are many more attributes [link].
This example creates a 300×300 canvas to draw in:
1 2 3 |
<canvas id="canvas" width="300" height="300" style="background-color:#333"> </canvas> |
Next, you need to get a handle and context to the canvas:
1 2 3 |
from js import document canvas = document.getElementById("canvas") ctx = canvas.getContext("2d") |
Let’s say that you want to write a green box on the canvas:
1 2 3 4 5 |
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); ctx.fillStyle = 'green'; ctx.fillRect(10, 10, 150, 100); |
Pyscript Example
The primary function to review is drawClock
. This function does three things every second:
- Draws the clock face
- Draws the numbers on the clock face
- Draws the hands of time
1 2 3 4 |
def drawClock(ctx, radius): drawFace(ctx, radius) drawNumbers(ctx, radius) drawTime(ctx, radius) |
Complete Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
<!DOCTYPE html> <html> <head> <title>PyScript Clock Example</title> <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" /> <script defer src="https://pyscript.net/alpha/pyscript.js"></script> </head> <body> <div id="status">Loading page ...</div> <br> <canvas id="canvas" width="300" height="300" style="background-color:#333"> </canvas> <py-script> from datetime import datetime from js import document, Math, setInterval from pyodide import create_proxy def set_running(): document.getElementById("status").innerHTML = 'Python loaded and running ...' def drawClock(ctx, radius): drawFace(ctx, radius) drawNumbers(ctx, radius) drawTime(ctx, radius) def drawFace(ctx, radius): ctx.beginPath() ctx.arc(0, 0, radius, 0, 2 * Math.PI) ctx.fillStyle = 'white' ctx.fill() grad = ctx.createRadialGradient(0,0,radius*0.95, 0,0,radius*1.05) grad.addColorStop(0, '#333') grad.addColorStop(0.5, 'white') grad.addColorStop(1, '#333') ctx.strokeStyle = grad ctx.lineWidth = radius * 0.1 ctx.stroke() ctx.beginPath() ctx.arc(0, 0, radius*0.1, 0, 2 * Math.PI) ctx.fillStyle = '#333' ctx.fill() def drawNumbers(ctx, radius): ctx.font = str(radius * 0.15) + "px arial" ctx.textBaseline = "middle" ctx.textAlign = "center" for num in range(1, 13): ang = num * Math.PI / 6 ctx.rotate(ang) ctx.translate(0, -radius * 0.85) ctx.rotate(-ang) ctx.fillText(str(num), 0, 0) ctx.rotate(ang) ctx.translate(0, radius * 0.85) ctx.rotate(-ang) def drawTime(ctx, radius): now = datetime.now() hour = now.hour minute = now.minute second = now.second # hour hour = hour % 12 hour = (hour * Math.PI / 6) hour += (minute * Math.PI / (6*60)) hour += (second * Math.PI / (360 * 60)) drawHand(ctx, hour, radius*0.5, radius*0.07) # minute minute = (minute * Math.PI / 30) minute += (second * Math.PI / (30 * 60)) drawHand(ctx, minute, radius * 0.8, radius * 0.07) # second second = second * Math.PI / 30 drawHand(ctx, second, radius * 0.9, radius * 0.02) def drawHand(ctx, pos, length, width): ctx.beginPath() ctx.lineWidth = width ctx.lineCap = "round" ctx.moveTo(0,0) ctx.rotate(pos) ctx.lineTo(0, -length) ctx.stroke() ctx.rotate(-pos) def main(): set_running() canvas = document.getElementById("canvas") ctx = canvas.getContext("2d") radius = canvas.height / 2 ctx.translate(radius, radius) radius = radius * 0.90 drawClock(ctx, radius) drawClock_proxy = create_proxy(drawClock) interval_id = setInterval(drawClock_proxy, 1000, ctx, radius) main() </py-script> </body> </html> |
More Information
- Other articles that I have written on Pyscript
- W3 Schools Canvas Clock Start
- MDN: Canvas API
- MDN: <canvas>: The Graphics Canvas element
Photography Credit
I write free articles about technology. Recently, I learned about Pexels.com which provides free images. The image in this article is courtesy of Pixabay at Pexels.
I design software for enterprise-class systems and data centers. My background is 30+ years in storage (SCSI, FC, iSCSI, disk arrays, imaging) virtualization. 20+ years in identity, security, and forensics.
For the past 14+ years, I have been working in the cloud (AWS, Azure, Google, Alibaba, IBM, Oracle) designing hybrid and multi-cloud software solutions. I am an MVP/GDE with several.
Leave a Reply