ipycanvas
¶
stellt die Web-Canvas-API zur Verfügung. Es gibt jedoch einige Unterschiede:
Das Canvas-Widget macht die CanvasRenderingContext2D-API direkt verfügbar
Die gesamte API ist in
snake_case
anstatt incamelCase
geschrieben, sodass beispielsweise das in Python geschriebenecanvas.fillStyle = "red"
in JavaScript zucanvas.fill_style = 'red'
wird.
Installation¶
$ pipenv install ipycanvas
Installing ipycanvas…
…
Erstellen von Canvas-Elementen¶
Bevor wir mit dem Erstellen von Canvas-Elementen beginnen können, zunächst ein Hinweis zum Canvas-Raster. Der Ursprung eines Gitters befindet sich in der oberen linken Ecke bei der Koordinate (0,0). Alle Elemente werden relativ zu diesem Ursprung platziert.
Es gibt vier Methoden zum Zeichnen von Rechtecken:
fill_rect(x, y, width, height=None)
zeichnet ein gefülltes Rechteckstroke_rect(x, y, width, height=None)
zeichnet einen rechteckigen Umrissfill_rects(x, y, width, height=None)
zeichnet gefüllte Rechteckestroke_rects(x, y, width, height=None)
zeichnet rechteckige Umrisse
Mit height=None
wird derselbe Wert verwendet wie bei width
.
Bei *_rects
sind x
, y
, width
und height
ganze Zahlen, Listen von ganzen Zahlen oder NumPy-Arrays.
[1]:
from ipycanvas import Canvas
canvas = Canvas(size=(120, 100))
canvas.fill_style = "lime"
canvas.stroke_style = "green"
canvas.fill_rect(10, 20, 100, 50)
canvas.stroke_rect(10, 20, 100, 50)
canvas
[2]:
from ipycanvas import MultiCanvas
# Create a multi-layer canvas with 2 layers
multi_canvas = MultiCanvas(2, size=(165, 115))
multi_canvas[0] # Access first layer (background)
multi_canvas[0].fill_style = "lime"
multi_canvas[0].stroke_style = "green"
multi_canvas[0].fill_rect(10, 20, 100, 50)
multi_canvas[0].stroke_rect(10, 20, 100, 50)
multi_canvas[1] # Access last layer
multi_canvas[1].fill_style = "red"
multi_canvas[1].stroke_style = "brown"
multi_canvas[1].fill_rect(55, 45, 100, 50)
multi_canvas[1].stroke_rect(55, 45, 100, 50)
multi_canvas
[3]:
import numpy as np
from ipycanvas import Canvas
n_particles = 75_000
x = np.array(np.random.rayleigh(350, n_particles), dtype=np.int32)
y = np.array(np.random.rayleigh(150, n_particles), dtype=np.int32)
size = np.random.randint(1, 3, n_particles)
canvas = Canvas(size=(1000, 500))
canvas.fill_style = "green"
canvas.fill_rects(x, y, size)
canvas
Da
Canvas
ein ipywidget ist, kann es
mehrfach in einem Notebook vorkommen
die Attribute ändern
geänderte Attribute auf andere Widget-Attribute verlinken
Canvas löschen¶
[4]:
from ipycanvas import Canvas
canvas = Canvas(size=(120, 100))
# Perform some drawings…
canvas.clear()
[5]:
from ipycanvas import Canvas
canvas = Canvas(size=(165, 115))
canvas.fill_style = "lime"
canvas.stroke_style = "brown"
canvas.fill_rect(10, 20, 100, 50)
canvas.clear_rect(52, 42, 100, 50)
canvas.stroke_rect(55, 45, 100, 50)
canvas
Formen¶
Die verfügbaren Zeichenkommandos sind:
move_to(x, y)
:line_to(x, y)
:arc(x, y, radius, start_angle, end_angle, anticlockwise=False)
:arc_to(x1, y1, x2, y2, radius)
:quadratic_curve_to(cp1x, cp1y, x, y)
:bezier_curve_to(cp1x, cp1y, cp2x, cp2y, x, y)
:rect(x, y, width, height)
:
Kreise zeichnen¶
Es gibt vier verschiedene Arten, Kreise zu zeichnen:
fill_arc(x, y, radius, start_angle, end_angle, anticlockwise=False)
stroke_arc(x, y, radius, start_angle, end_angle, anticlockwise=False)
fill_arcs(x, y, radius, start_angle, end_angle, anticlockwise=False)
stroke_arcs(x, y, radius, start_angle, end_angle, anticlockwise=False)
Bei *_arcs
sind x
, y
und radius
NumPy-Arrays, Listen oder skalare Werte.
[6]:
from math import pi
from ipycanvas import Canvas
canvas = Canvas(size=(200, 200))
canvas.fill_style = "red"
canvas.stroke_style = "green"
canvas.fill_arc(60, 60, 50, 0, pi)
canvas.stroke_arc(60, 60, 40, 0, 2 * pi)
canvas
Zeichenpfade¶
Ein Pfad ist eine Liste von Punkten, die durch Liniensegmente verbunden sind, die unterschiedliche Formen, gerade oder gekrümmt, geschlossen oder offen, unterschiedlich breit und farbig sein können. Dabei stehen die folgenden Funktionen zur Verfügung:
begin_path()
erstellt einen neuen Pfadclose_path()
fügt dem Pfad eine gerade Linie hinzu, die zum Anfang des aktuellen Pfads führtstroke()
zeichnet die Form entlang der Konturfill(rule)
zeichnet die Form durch eine Füllung innerhalb des Pfades
[7]:
from ipycanvas import Canvas
canvas = Canvas(size=(100, 100))
# Draw simple triangle shape
canvas.begin_path()
canvas.move_to(75, 50)
canvas.line_to(100, 75)
canvas.line_to(100, 25)
canvas.fill()
canvas
Beispiele¶
arc
¶
[8]:
from math import pi
from ipycanvas import Canvas
canvas = Canvas(size=(200, 200))
# Draw smiley face
canvas.begin_path()
canvas.arc(75, 75, 50, 0, pi * 2, True) # Outer circle
canvas.move_to(110, 75)
canvas.arc(75, 75, 35, 0, pi, False) # Mouth (clockwise)
canvas.move_to(65, 65)
canvas.arc(60, 65, 5, 0, pi * 2, True) # Left eye
canvas.move_to(95, 65)
canvas.arc(90, 65, 5, 0, pi * 2, True) # Right eye
canvas.stroke()
canvas
bezier_curve_to
¶
[9]:
from ipycanvas import Canvas
canvas = Canvas(size=(200, 200))
# Cubic curves example
canvas.begin_path()
canvas.move_to(75, 40)
canvas.bezier_curve_to(75, 37, 70, 25, 50, 25)
canvas.bezier_curve_to(20, 25, 20, 62.5, 20, 62.5)
canvas.bezier_curve_to(20, 80, 40, 102, 75, 120)
canvas.bezier_curve_to(110, 102, 130, 80, 130, 62.5)
canvas.bezier_curve_to(130, 62.5, 130, 25, 100, 25)
canvas.bezier_curve_to(85, 25, 75, 37, 75, 40)
canvas.fill()
canvas
Stile und Farben¶
Farben¶
Canvas
hat zwei Farbattribute, eines für Striche und eines für Flächen; zudem kann die Transparenz geändert werden.
stroke_style
erwartet eine gültige HTML-Farbe. Der Standardwert ist schwarz.fill_style
erwartet eine gültige HTML-Farbe. Der Standardwert ist schwarz.global_alpha
gibt die Transparenz an. Der Standardwert ist1.0
.
Linien¶
Linienart¶
Linien lassen sich durch folgende Attribute beschreiben:
line_width
line_cap
line_join
miter_limit
get_line_dash()
set_line_dash(segments)
line_dash_offset
Linienbreite¶
[10]:
from ipycanvas import Canvas
canvas = Canvas(size=(400, 280))
canvas.scale(2)
for i in range(10):
width = 1 + i
x = 5 + i * 20
canvas.line_width = width
canvas.fill_text(str(width), x - 5, 15)
canvas.begin_path()
canvas.move_to(x, 20)
canvas.line_to(x, 140)
canvas.stroke()
canvas
Linienende¶
[11]:
from ipycanvas import Canvas
canvas = Canvas(size=(320, 360))
# Possible line_cap values
line_caps = ["butt", "round", "square"]
canvas.scale(2)
# Draw guides
canvas.stroke_style = "#09f"
canvas.begin_path()
canvas.move_to(10, 30)
canvas.line_to(140, 30)
canvas.move_to(10, 140)
canvas.line_to(140, 140)
canvas.stroke()
# Draw lines
canvas.stroke_style = "black"
canvas.font = "15px serif"
for i in range(len(line_caps)):
line_cap = line_caps[i]
x = 25 + i * 50
canvas.fill_text(line_cap, x - 15, 15)
canvas.line_width = 15
canvas.line_cap = line_cap
canvas.begin_path()
canvas.move_to(x, 30)
canvas.line_to(x, 140)
canvas.stroke()
canvas
Linienverbindung¶
legt das Erscheinungsbild der Ecken fest, an denen sich Linien treffen.
[12]:
from ipycanvas import Canvas
canvas = Canvas(size=(320, 360))
# Possible line_join values
line_joins = ["round", "bevel", "miter"]
min_y = 40
max_y = 80
spacing = 45
canvas.line_width = 10
canvas.scale(2)
for i in range(len(line_joins)):
line_join = line_joins[i]
y1 = min_y + i * spacing
y2 = max_y + i * spacing
canvas.line_join = line_join
canvas.fill_text(line_join, 60, y1 - 10)
canvas.begin_path()
canvas.move_to(-5, y1)
canvas.line_to(35, y2)
canvas.line_to(75, y1)
canvas.line_to(115, y2)
canvas.line_to(155, y1)
canvas.stroke()
canvas
Strichmuster¶
[13]:
from ipycanvas import Canvas
canvas = Canvas(size=(400, 280))
canvas.scale(2)
line_dashes = [[5, 10], [10, 5], [5, 10, 20], [10, 20], [20, 10], [20, 20]]
canvas.line_width = 2
for i in range(len(line_dashes)):
x = 5 + i * 20
canvas.set_line_dash(line_dashes[i])
canvas.begin_path()
canvas.move_to(x, 0)
canvas.line_to(x, 140)
canvas.stroke()
canvas
Text¶
Es gibt zwei Methoden zur Gestaltung von Text:
fill_text(text, x, y, max_width=None)
stroke_text(text, x, y, max_width=None)
[14]:
from ipycanvas import Canvas
canvas = Canvas(size=(400, 50))
canvas.font = "32px serif"
canvas.fill_text("Drawing from Python is cool!", 10, 32)
canvas
[15]:
from ipycanvas import Canvas
canvas = Canvas(size=(400, 50))
canvas.font = "32px serif"
canvas.stroke_text("Hello There!", 10, 32)
canvas
font
gibt den aktuellen Textstil an. Der Standardwert ist"12px sans-serif"
.text_align
gibt die Textausrichtung an. Mögliche Werte sind"start"
,"end"
,"left"
,"right"
oder"center"
.text_baseline
gibt die Ausrichtung an der Grundlinie an. Mögliche Werte sind"top"
,"hanging"
,"middle"
,"alphabetic"
,"ideographic"
und"bottom"
. Der Standardwert ist"alphabetic"
.direction
gibt die Textrichtung an. Mögliche Werte sind"ltr"
,"rtl"
,"inherit"
. Der Standardwert ist"inherit"
.
Selbstverständlich kann auch fill_style
und stroke_style
zum EInfürben der Text verwendet werden.
Bilder¶
aus einem NumPy-Array¶
Mit put_image_data(image_data, dx, dy)
lässt sich ein Bild darstellen wobei image_data
ein NumPy-Array angibt und dx
und dy
das obere linke Eck des Bildes.
[16]:
import numpy as np
from ipycanvas import Canvas
x = np.linspace(-1, 1, 600)
y = np.linspace(-1, 1, 600)
x_grid, y_grid = np.meshgrid(x, y)
blue_channel = np.array(
np.sin(x_grid**2 + y_grid**2) * 255, dtype=np.int32
)
red_channel = np.zeros_like(blue_channel) + 200
green_channel = np.zeros_like(blue_channel) + 50
image_data = np.stack((red_channel, blue_channel, green_channel), axis=2)
canvas = Canvas(size=(image_data.shape[0], image_data.shape[1]))
canvas.put_image_data(image_data, 0, 0)
canvas
Status¶
Der Status kann mit zwei Werten angegeben werden:
save()
speichert den Status des Canvas-Elementsrestore()
stellt den zuletzt gespeicherten Status des Canvas-Elements wieder her wobei diese Methode beliebig oft aufgerufen werden kann.
Transformationen¶
translate(x, y)
verschiebt das Canvas-Elementrotate(angle)
rotiert das Canvas-Element im Uhrzeigersinnscale(x, y=None)
skaliert das Canvas-Element
Siehe auch: