Pantograph is a library for writing HTML5 canvas animations and games in Python. It is meant to provide a simple and easy-to-use Python interface to the canvas for beginning programmers who have not yet learned Javascript.
Pantograph uses the Tornado networking library to send drawing commands and receive input events from the browser through websockets. Thus, Tornado is the only dependency.
import pantograph
import math
# Animate a spinning wheel on the canvas
class Rotary(pantograph.PantographHandler):
def setup(self):
self.angle = 0
self.radius = min(self.width, self.height) / 2
def update(self):
cx = self.radius
cy = self.radius
self.clear_rect(0, 0, self.width, self.height)
# draw the circle for the "rim" of the wheel
self.draw_circle(self.radius, self.radius, self.radius, "#f00")
# draw eight evenly-spaced "spokes" from the center to the edge
for i in range(0, 8):
angle = self.angle + i * math.pi / 4
x = cx + self.radius * math.cos(angle)
y = cy + self.radius * math.sin(angle)
self.draw_line(cx, cy, x, y, "#f00")
self.angle += math.pi / 64
if __name__ == '__main__':
app = pantograph.SimplePantographApplication(Rotary)
app.run()
This program is located at "examples/rotary/start.py".
This class is the main application, which can hold one or more handlers. The required constructor argument is a list of 3-tuples containing the name of the handler, the url, and the handler class. For instance,
pantograph.PantographApplication([
("Pantograph", "/", pantograph.PantographHandler)
])
It has one public method run
which starts the application server.
By default, the server runs on port 8080 and is bound to localhost.
You can, however, override these defaults by providing extra arguments.
For instance, if you replaced app.run()
with app.run("0.0.0.0", 8000)
,
the server would be publically accessible on port 8000.
A subclass of PantographApplication
which takes in a single handler and
sets up a route to it from the root url. The name is take from the class name
of the handler.
This class contains event handlers for various mouse and keyboard events,
a continuous timer, and methods for drawing on the canvas.
Create a subclass of PantographHandler
to implement your application.
setup()
- Called once when the handler is initialized. Override this method
to put in any one-off setup code.
update()
- Called in the main loop of the application. Override this method to
put in any update code, such as redrawing a frame.
draw_rect(x, y, width, height, color = "#000")
- Draw a hollow rectangle
on the canvas. The color argument is the line color and takes any valid CSS
color definition as a string. The other arguments are self-explanatory.
fill_rect(x, y, width, height, color = "#000")
- Draw a filled rectangle on
the canvas. The color argument here is the fill color.
clear_rect(x, y, width, height)
- Clear a rectangular area of the canvas.
draw_oval(x, y, width, height, color = "#000")
- Draw a hollow oval on the
canvas.
fill_oval(x, y, width, height, color = "#000")
- Draw a filled oval on the
canvas.
draw_circle(x, y, radius, color = "#000")
- Draw a hollow circle on the
canvas. The x and y are the x and y or the center of the circle.
fill_circle(x, y, radius, color = "#000")
- Draw a filled circle on the
canvas.
draw_line(self, startX, startY, endX, endY, color = "#000")
- Draw a line
from (startX, startY) to (endX, endY).
draw_polygon(self, points, color = "#000")
- Draw a hollow polygon on the
canvas. The points
argument is a list of (x, y) pairs.
fill_polygon(self, points, color = "#000")
- Draw a filled polygon on the
canvas.
draw_image(self, name, x, y, width=None, height=None)
- Draw an image on
the canvas. The name
parameter is the name of the image, pantograph will
search for an image by that name in your current directory at
"images/handler_name/name" and then at "images/name" where handler_name
is the name of your handler, and name is the name passed the function.
If you do not supply a width or a height, the actual width and height of the
image will be used.
All event callbacks are passed an InputEvent
object which contains the
following fields.
x
- The x position of the mousey
- The y position of the mousebutton
- Which button on the mouse was pressed (0 - left, 1 - middle, 2 - right)?alt_key
- Was the alt key held down?ctrl_key
- Was the ctrl key held down?meta_key
- Was the meta (Windows) key held down?shift_key
- Was the shift key held down?key_code
- The key code
The following are the callback methods which can be overloaded. The callbacks correspond directly to HTML DOM events.
on_mouse_down
- Called when a mouse button is pressed downon_mouse_up
- Called when a mouse button is releasedon_mouse_move
- Called when the mouse is moved across the canvason_click
- Called when the mouse is clicked (pressed and released)on_dbl_click
- Called when the mouse is double-clickedon_key_down
- Called when a keyboard key is pushed downon_key_up
- Called when a key is releasedon_key_press
- Called periodically while key is held down
width
- The width of the canvasheight
- The height of the canvas
Pantograph also provides a set of shape classes to represent your animation
in an object oriented manner. The shape objects correspond to the draw_*
methods in the handler class.
Rect(x, y, width, height, fill_color=None, line_color=None)
- If no values are provided forfill_color
orline_color
, the fill or line will be transparentOval(x, y, width, height, fill_color=None, line_color=None)
Circle(x, y, radius, fill_color=None, line_color=None)
Image(img_name, x, y, width=None, height=None)
Line(startx, starty, endx, endy, color = None)
Polygon(points, fill_color=None, line_color=None)
CompoundShape(shapes)
-shapes
is a list of other shape objects
draw(canvas)
- Draw the shape on thecanvas
, which is an instance ofPantographHandler
.translate(dx, dy)
- Move the shape across the screenrotate(theta)
- Rotate the shape to the angletheta
, which is in radians. The angletheta = 0
would be facing directly to the right, and increases in the clockwise direction.intersects(other)
- Determine if this shape intersects with theother
shapecontains(other)
- Determine if this shape wholly encompasses theother
shape
You can configure your application by putting a "config.json" file in your current directory. The json file should contain a dictionary which can have any of the following keys.
timer_interval
- The number of milliseconds between each call to theupdate
method.width
- The width of the canvas on the screen. This can be an integer or the string "fullWidth" to fill up the entire width of the browser.height
- The height of the canvas on the screen. This can be an integer or the string "fullHeight" to fill up the entire height of the browser.
If you have multiple handlers in your application, you can configure each handler separately by associating a key with the handler's name to a nested dictionary containing any of the variables above.