4.12.4
The canvas
element
- Categories:
- Flow content.
- Phrasing content.
- Embedded content.
- Palpable content.
- Contexts in which this element can be used:
- Where embedded content is expected.
- Content model:
-
Transparent, but with no interactive content descendants except for
a
elements,img
elements withusemap
attributes,button
elements,input
elements whosetype
attribute are in the Checkbox or Radio Button states,input
elements that are buttons,select
elements with amultiple
attribute or a display size greater than 1, sorting interfaceth
elements, and elements that would not be interactive content except for having thetabindex
attribute specified. - Tag omission in text/html:
- Neither tag is omissible.
- Content attributes:
- Global attributes
-
width
— Horizontal dimension -
height
— Vertical dimension - DOM interface:
-
typedef (CanvasRenderingContext2D or WebGLRenderingContext) RenderingContext; interface HTMLCanvasElement : HTMLElement { attribute unsigned long width; attribute unsigned long height; RenderingContext? getContext(DOMString contextId, any... arguments); boolean probablySupportsContext(DOMString contextId, any... arguments); void setContext(RenderingContext context); CanvasProxy transferControlToProxy(); DOMString toDataURL(optional DOMString type, any... arguments); void toBlob(FileCallback? _callback, optional DOMString type, any... arguments); };
The canvas
element provides scripts with a resolution-dependent bitmap canvas,
which can be used for rendering graphs, game graphics, art, or other visual images on the fly.
Authors should not use the canvas
element in a document when a more suitable
element is available. For example, it is inappropriate to use a canvas
element to
render a page heading: if the desired presentation of the heading is graphically intense, it
should be marked up using appropriate elements (typically h1
) and then styled using
CSS and supporting technologies such as Web Components.
When authors use the canvas
element, they must also provide content that, when
presented to the user, conveys essentially the same function or purpose as the
canvas
' bitmap. This content may be placed as content of the canvas
element. The contents of the canvas
element, if any, are the element's fallback
content.
In interactive visual media, if scripting is enabled for
the canvas
element, and if support for canvas
elements has been enabled,
the canvas
element represents embedded content consisting
of a dynamically created image, the element's bitmap.
In non-interactive, static, visual media, if the canvas
element has been
previously associated with a rendering context (e.g. if the page was viewed in an interactive
visual medium and is now being printed, or if some script that ran during the page layout process
painted on the element), then the canvas
element represents
embedded content with the element's current bitmap and size. Otherwise, the element
represents its fallback content instead.
In non-visual media, and in visual media if scripting is
disabled for the canvas
element or if support for canvas
elements
has been disabled, the canvas
element represents its fallback
content instead.
When a canvas
element represents embedded content, the
user can still focus descendants of the canvas
element (in the fallback
content). When an element is focused, it is the target of keyboard interaction events (even
though the element itself is not visible). This allows authors to make an interactive canvas
keyboard-accessible: authors should have a one-to-one mapping of interactive regions to focusable
areas in the fallback content. (Focus has no effect on mouse interaction events.)
[DOMEVENTS]
An element whose nearest canvas
element ancestor is being rendered
and represents embedded content is an element that is being used as
relevant canvas fallback content.
The canvas
element has two attributes to control the size of the element's bitmap:
width
and height
. These attributes, when specified, must have
values that are valid non-negative integers. The width
attribute defaults to 300, and the height
attribute
defaults to 150.
The intrinsic dimensions of the canvas
element when it represents
embedded content are equal to the dimensions of the element's bitmap.
The user agent must use a square pixel density consisting of one pixel of image data per
coordinate space unit for the bitmaps of a canvas
and its rendering contexts.
A canvas
element can be sized arbitrarily by a style sheet, its
bitmap is then subject to the 'object-fit' CSS property. [CSSIMAGES]
-
context = canvas .
getContext
(contextId [, ... ] ) -
Returns an object that exposes an API for drawing on the canvas. The first argument specifies the desired API, either "
2d
" or "webgl
". Subsequent arguments are handled by that API.This specification defines the "
2d
" context below. There is also a specification that defines a "webgl
" context. [WEBGL]Returns null if the given context ID is not supported, if the canvas has already been initialised with the other context type (e.g. trying to get a "
2d
" context after getting a "webgl
" context).Throws an
InvalidStateError
exception if thesetContext()
ortransferControlToProxy()
methods have been used. -
supported = canvas .
probablySupportsContext
(contextId [, ... ] ) -
Returns false if calling
getContext()
with the same arguments would definitely return null, and true otherwise.This return value is not a guarantee that
getContext()
will or will not return an object, as conditions (e.g. availability of system resources) can vary over time.Throws an
InvalidStateError
exception if thesetContext()
ortransferControlToProxy()
methods have been used. -
canvas .
setContext
(context) -
Sets the
canvas
' rendering context to the given object.Throws an
InvalidStateError
exception if thegetContext()
ortransferControlToProxy()
methods have been used.
-
url = canvas .
toDataURL
( [ type, ... ] ) -
Returns a
data:
URL for the image in the canvas.The first argument, if provided, controls the type of the image to be returned (e.g. PNG or JPEG). The default is
image/png
; that type is also used if the given type isn't supported. The other arguments are specific to the type, and control the way that the image is generated, as given in the table below.When trying to use types other than "
image/png
", authors can check if the image was really returned in the requested format by checking to see if the returned string starts with one of the exact strings "data:image/png,
" or "data:image/png;
". If it does, the image is PNG, and thus the requested type was not supported. (The one exception to this is if the canvas has either no height or no width, in which case the result might simply be "data:,
".) -
canvas .
toBlob
(callback [, type, ... ] ) -
Creates a
Blob
object representing a file containing the image in the canvas, and invokes a callback with a handle to that object.The second argument, if provided, controls the type of the image to be returned (e.g. PNG or JPEG). The default is
image/png
; that type is also used if the given type isn't supported. The other arguments are specific to the type, and control the way that the image is generated, as given in the table below.
4.12.4.1 Proxying canvases to workers
Since DOM nodes cannot be accessed across worker boundaries, a proxy object is needed to enable
workers to render to canvas
elements in Document
s.
[Exposed=Window,Worker] interface CanvasProxy { void setContext(RenderingContext context); }; // CanvasProxy implements Transferable;
-
canvasProxy = canvas .
transferControlToProxy
() -
Returns a
CanvasProxy
object that can be used to transfer control for this canvas over to another document (e.g. aniframe
from another origin) or to a worker.Throws an
InvalidStateError
exception if thegetContext()
orsetContext()
methods have been used. -
canvasProxy .
setContext
(context) -
Sets the
CanvasProxy
object'scanvas
element's rendering context to the given object.Throws an
InvalidStateError
exception if theCanvasProxy
has been transfered.
The transferControlToProxy()
method of the canvas
element, when invoked, must run the following steps:
If the
canvas
element's canvas context mode is not none, throw anInvalidStateError
exception and abort these steps.Set the
canvas
element's context mode to proxied.Return a
CanvasProxy
object bound to thiscanvas
element.
A CanvasProxy
object can be neutered (like any Transferable
object),
meaning it can no longer be transferred, and
can be disabled, meaning it can no longer be bound
to rendering contexts. When first created, a CanvasProxy
object must be neither.
A CanvasProxy
is created with a link to a canvas
element. A
CanvasProxy
object that has not been disabled must have a strong reference to its canvas
element.
The setContext(context)
method of CanvasProxy
objects, when invoked,
must run the following steps:
If the
CanvasProxy
object has been disabled, throw anInvalidStateError
exception and abort these steps.If the
CanvasProxy
object has not been neutered, then neuter it.If context's context bitmap mode is fixed, then throw an
InvalidStateError
exception and abort these steps.If context's context bitmap mode is bound, then run context's unbinding steps and set its context's context bitmap mode to unbound.
Run context's binding steps to bind it to this
CanvasProxy
object'scanvas
element.Set the context's context bitmap mode to bound.
To transfer a
CanvasProxy
object old to a new owner owner,
a user agent must create a new CanvasProxy
object linked to the same
canvas
element as old, thus obtaining new,
must neuter and disable the old object, and must
finally return new.
Here is a clock implemented on a worker. First, the main page:
<!DOCTYPE HTML> <title>Clock</title> <canvas></canvas> <script> var canvas = document.getElementsByTagName('canvas')[0]; var proxy = canvas.transferControlToProxy(); var worker = new Worker('clock.js'); worker.postMessage(proxy, [proxy]); </script>
Second, the worker:
onmessage = function (event) { var context = new CanvasRenderingContext2D(); event.data.setContext(context); // event.data is the CanvasProxy object setInterval(function () { context.clearRect(0, 0, context.width, context.height); context.fillText(new Date(), 0, 100); context.commit(); }, 1000); };
4.12.4.2 The 2D rendering context
typedef (HTMLImageElement or HTMLVideoElement or HTMLCanvasElement or CanvasRenderingContext2D or ImageBitmap) CanvasImageSource; enum CanvasFillRule { "nonzero", "evenodd" }; [Constructor(optional unsigned long width, unsigned long height), Exposed=Window,Worker] interface CanvasRenderingContext2D { // back-reference to the canvas readonly attribute HTMLCanvasElement canvas; // canvas dimensions attribute unsigned long width; attribute unsigned long height; // for contexts that aren't directly fixed to a specific canvas void commit(); // push the image to the output bitmap // state void save(); // push state on state stack void restore(); // pop state stack and restore state // transformations (default transform is the identity matrix) attribute SVGMatrix currentTransform; void scale(unrestricted double x, unrestricted double y); void rotate(unrestricted double angle); void translate(unrestricted double x, unrestricted double y); void transform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f); void setTransform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f); void resetTransform(); // compositing attribute unrestricted double globalAlpha; // (default 1.0) attribute DOMString globalCompositeOperation; // (default source-over) // image smoothing attribute boolean imageSmoothingEnabled; // (default true) // colors and styles (see also the CanvasDrawingStyles interface) attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black) attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black) CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1); CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1); CanvasPattern createPattern(CanvasImageSource image, [TreatNullAs=EmptyString] DOMString repetition); // shadows attribute unrestricted double shadowOffsetX; // (default 0) attribute unrestricted double shadowOffsetY; // (default 0) attribute unrestricted double shadowBlur; // (default 0) attribute DOMString shadowColor; // (default transparent black) // rects void clearRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h); void fillRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h); void strokeRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h); // path API (see also CanvasPathMethods) void beginPath(); void fill(optional CanvasFillRule fillRule = "nonzero"); void fill(Path2D path, optional CanvasFillRule fillRule = "nonzero"); void stroke(); void stroke(Path2D path); void drawSystemFocusRing(Element element); void drawSystemFocusRing(Path2D path, Element element); boolean drawCustomFocusRing(Element element); boolean drawCustomFocusRing(Path2D path, Element element); void scrollPathIntoView(); void scrollPathIntoView(Path2D path); void clip(optional CanvasFillRule fillRule = "nonzero"); void clip(Path2D path, optional CanvasFillRule fillRule = "nonzero"); void resetClip(); boolean isPointInPath(unrestricted double x, unrestricted double y, optional CanvasFillRule fillRule = "nonzero"); boolean isPointInPath(Path2D path, unrestricted double x, unrestricted double y, optional CanvasFillRule fillRule = "nonzero"); boolean isPointInStroke(unrestricted double x, unrestricted double y); boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y); // text (see also the CanvasDrawingStyles interface) void fillText(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth); void strokeText(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth); TextMetrics measureText(DOMString text); // drawing images void drawImage(CanvasImageSource image, unrestricted double dx, unrestricted double dy); void drawImage(CanvasImageSource image, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh); void drawImage(CanvasImageSource image, unrestricted double sx, unrestricted double sy, unrestricted double sw, unrestricted double sh, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh); // hit regions void addHitRegion(optional HitRegionOptions options); void removeHitRegion(DOMString id); // pixel manipulation ImageData createImageData(double sw, double sh); ImageData createImageData(ImageData imagedata); ImageData getImageData(double sx, double sy, double sw, double sh); void putImageData(ImageData imagedata, double dx, double dy); void putImageData(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight); }; CanvasRenderingContext2D implements CanvasDrawingStyles; CanvasRenderingContext2D implements CanvasPathMethods; [NoInterfaceObject, Exposed=Window,Worker] interface CanvasDrawingStyles { // line caps/joins attribute unrestricted double lineWidth; // (default 1) attribute DOMString lineCap; // "butt", "round", "square" (default "butt") attribute DOMString lineJoin; // "round", "bevel", "miter" (default "miter") attribute unrestricted double miterLimit; // (default 10) // dashed lines void setLineDash(sequence<unrestricted double> segments); // default empty sequence<unrestricted double> getLineDash(); attribute unrestricted double lineDashOffset; // text attribute DOMString font; // (default 10px sans-serif) attribute DOMString textAlign; // "start", "end", "left", "right", "center" (default: "start") attribute DOMString textBaseline; // "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" (default: "alphabetic") attribute DOMString direction; // "ltr", "rtl", "inherit" (default: "inherit") }; [NoInterfaceObject, Exposed=Window,Worker] interface CanvasPathMethods { // shared path API methods void closePath(); void moveTo(unrestricted double x, unrestricted double y); void lineTo(unrestricted double x, unrestricted double y); void quadraticCurveTo(unrestricted double cpx, unrestricted double cpy, unrestricted double x, unrestricted double y); void bezierCurveTo(unrestricted double cp1x, unrestricted double cp1y, unrestricted double cp2x, unrestricted double cp2y, unrestricted double x, unrestricted double y); void arcTo(unrestricted double x1, unrestricted double y1, unrestricted double x2, unrestricted double y2, unrestricted double radius); void arcTo(unrestricted double x1, unrestricted double y1, unrestricted double x2, unrestricted double y2, unrestricted double radiusX, unrestricted double radiusY, unrestricted double rotation); void rect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h); void arc(unrestricted double x, unrestricted double y, unrestricted double radius, unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false); void ellipse(unrestricted double x, unrestricted double y, unrestricted double radiusX, unrestricted double radiusY, unrestricted double rotation, unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false); }; [Exposed=Window,Worker] interface CanvasGradient { // opaque object void addColorStop(double offset, DOMString color); }; [Exposed=Window,Worker] interface CanvasPattern { // opaque object void setTransform(SVGMatrix transform); }; [Exposed=Window,Worker] interface TextMetrics { // x-direction readonly attribute double width; // advance width readonly attribute double actualBoundingBoxLeft; readonly attribute double actualBoundingBoxRight; // y-direction readonly attribute double fontBoundingBoxAscent; readonly attribute double fontBoundingBoxDescent; readonly attribute double actualBoundingBoxAscent; readonly attribute double actualBoundingBoxDescent; readonly attribute double emHeightAscent; readonly attribute double emHeightDescent; readonly attribute double hangingBaseline; readonly attribute double alphabeticBaseline; readonly attribute double ideographicBaseline; }; dictionary HitRegionOptions { Path2D? path = null; CanvasFillRule fillRule = "nonzero"; DOMString id = ""; DOMString? parentID = null; DOMString cursor = "inherit"; // for control-backed regions: Element? control = null; // for unbacked regions: DOMString? label = null; DOMString? role = null; }; [Constructor(unsigned long sw, unsigned long sh), Constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh), Exposed=Window,Worker] interface ImageData { readonly attribute unsigned long width; readonly attribute unsigned long height; readonly attribute Uint8ClampedArray data; }; [Constructor(optional Element scope), Exposed=Window,Worker] interface DrawingStyle { }; DrawingStyle implements CanvasDrawingStyles; [Constructor, Constructor(Path2D path), Constructor(Path2D[] paths, optional CanvasFillRule fillRule = "nonzero"), Constructor(DOMString d), Exposed=Window,Worker] interface Path2D { void addPath(Path2D path, optional SVGMatrix? transformation = null); void addPathByStrokingPath(Path2D path, CanvasDrawingStyles styles, optional SVGMatrix? transformation = null); void addText(DOMString text, CanvasDrawingStyles styles, SVGMatrix? transformation, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth); void addPathByStrokingText(DOMString text, CanvasDrawingStyles styles, SVGMatrix? transformation, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth); void addText(DOMString text, CanvasDrawingStyles styles, SVGMatrix? transformation, Path2D path, optional unrestricted double maxWidth); void addPathByStrokingText(DOMString text, CanvasDrawingStyles styles, SVGMatrix? transformation, Path2D path, optional unrestricted double maxWidth); }; Path2D implements CanvasPathMethods;
-
context = canvas .
getContext
('2d') -
Returns a
CanvasRenderingContext2D
object that is permanently bound to a particularcanvas
element. -
context = new
CanvasRenderingContext2D
( [ width, height ] ) -
Returns an unbound
CanvasRenderingContext2D
object with an implied bitmap with the given dimensions in CSS pixels (300x150, if the arguments are omitted). -
context .
canvas
-
Returns the
canvas
element, if the rendering context was obtained using thegetContext()
method. -
context .
width
-
context .
height
-
Return the dimensions of the bitmap, in CSS pixels.
Can be set, to update the bitmap's dimensions. If the rendering context is bound to a canvas, this will also update the canvas' intrinsic dimensions.
-
context .
commit
() -
If the rendering context is bound to a
canvas
, display the current frame.
The CanvasFillRule
enumeration is used to select the fill rule
algorithm by which to determine if a point is inside or outside a path.
The value "nonzero
" value
indicates the non-zero winding rule, wherein
a point is considered to be outside a shape if the number of times a half-infinite straight
line drawn from that point crosses the shape's path going in one direction is equal to the
number of times it crosses the path going in the other direction.
The "evenodd
" value indicates
the even-odd rule, wherein
a point is considered to be outside a shape if the number of times a half-infinite straight
line drawn from that point crosses the shape's path is even.
If a point is not outside a shape, it is inside the shape.
4.12.4.2.1 Implementation notes
Although the way the specification is written it might sound like an implementation needs to
track up to four bitmaps per canvas or rendering context — one scratch bitmap,
one output bitmap for the rendering context, one bitmap for the canvas
,
and one bitmap for the actually currently rendered image — user agents can in fact generally
optimise this to only one or two.
The scratch bitmap, when it isn't the same bitmap as the output
bitmap, is only directly observable if it is read, and therefore implementations can,
instead of updating this bitmap, merely remember the sequence of drawing operations that have been
applied to it until such time as the bitmap's actual data is needed (for example because of a call
to commit()
, drawImage()
, or the createImageBitmap()
factory method). In many cases, this will be more memory efficient.
The bitmap of a canvas
element is the one bitmap that's pretty much always going
to be needed in practice. The output bitmap of a rendering context, when it has one,
is always just an alias to a canvas
element's bitmap.
Additional bitmaps are sometimes needed, e.g. to enable fast drawing when the canvas is being painted at a different size than its intrinsic size, or to enable double buffering so that the rendering commands from the scratch bitmap can be applied without the rendering being updated midway.
4.12.4.2.2 The canvas state
Each CanvasRenderingContext2D
rendering context maintains a stack of drawing
states. Drawing states consist of:
- The current transformation matrix.
- The current clipping region.
- The current values of the following attributes:
strokeStyle
,fillStyle
,globalAlpha
,lineWidth
,lineCap
,lineJoin
,miterLimit
,lineDashOffset
,shadowOffsetX
,shadowOffsetY
,shadowBlur
,shadowColor
,globalCompositeOperation
,font
,textAlign
,textBaseline
,direction
,imageSmoothingEnabled
. - The current dash list.
The current default path and the rendering context's bitmaps are not
part of the drawing state. The current default path is persistent, and can only be
reset using the beginPath()
method. The bitmaps
depend on whether and how the rendering context is bound to a canvas
element.
-
context .
save
() -
Pushes the current state onto the stack.
-
context .
restore
() -
Pops the top state on the stack, restoring the context to that state.
4.12.4.2.3
DrawingStyle
objects
All the line styles (line width, caps, joins, and dash patterns) and text styles (fonts)
described in the next two sections apply to CanvasRenderingContext2D
objects and to
DrawingStyle
objects. This section defines the constructor used to obtain a
DrawingStyle
object. This object is then used by methods on Path2D
objects to control how text and paths are rasterised and stroked.
-
styles = new
DrawingStyle
( [ element ] ) -
Creates a new
DrawingStyle
object, optionally using a specific element for resolving relative keywords and sizes in font specifications.
4.12.4.2.4 Line styles
-
context .
lineWidth
[ = value ] -
styles .
lineWidth
[ = value ] -
Returns the current line width.
Can be set, to change the line width. Values that are not finite values greater than zero are ignored.
-
context .
lineCap
[ = value ] -
styles .
lineCap
[ = value ] -
Returns the current line cap style.
Can be set, to change the line cap style.
The possible line cap styles are
butt
,round
, andsquare
. Other values are ignored. -
context .
lineJoin
[ = value ] -
styles .
lineJoin
[ = value ] -
Returns the current line join style.
Can be set, to change the line join style.
The possible line join styles are
bevel
,round
, andmiter
. Other values are ignored. -
context .
miterLimit
[ = value ] -
styles .
miterLimit
[ = value ] -
Returns the current miter limit ratio.
Can be set, to change the miter limit ratio. Values that are not finite values greater than zero are ignored.
-
context .
setLineDash
(segments) -
styles .
setLineDash
(segments) -
Sets the current line dash pattern (as used when stroking). The argument is a list of distances for which to alternately have the line on and the line off.
-
segments = context .
getLineDash
() -
segments = styles .
getLineDash
() -
Returns a copy of the current line dash pattern. The array returned will always have an even number of entries (i.e. the pattern is normalized).
-
context .
lineDashOffset
-
styles .
lineDashOffset
-
Returns the phase offset (in the same units as the line dash pattern).
Can be set, to change the phase offset. Values that are not finite values are ignored.
4.12.4.2.5 Text styles
-
context .
font
[ = value ] -
styles .
font
[ = value ] -
Returns the current font settings.
Can be set, to change the font. The syntax is the same as for the CSS 'font' property; values that cannot be parsed as CSS font values are ignored.
Relative keywords and lengths are computed relative to the font of the
canvas
element. -
context .
textAlign
[ = value ] -
styles .
textAlign
[ = value ] -
Returns the current text alignment settings.
Can be set, to change the alignment. The possible values are and their meanings are given below. Other values are ignored. The default is
start
. -
context .
textBaseline
[ = value ] -
styles .
textBaseline
[ = value ] -
Returns the current baseline alignment settings.
Can be set, to change the baseline alignment. The possible values and their meanings are given below. Other values are ignored. The default is
alphabetic
. -
context .
direction
[ = value ] -
styles .
direction
[ = value ] -
Returns the current directionality.
Can be set, to change the directionality. The possible values and their meanings are given below. Other values are ignored. The default is
inherit
.
The textAlign
attribute's allowed keywords are
as follows:
-
start
Align to the start edge of the text (left side in left-to-right text, right side in right-to-left text).
-
end
Align to the end edge of the text (right side in left-to-right text, left side in right-to-left text).
-
left
Align to the left.
-
right
Align to the right.
-
center
Align to the center.
The textBaseline
attribute's allowed keywords correspond to alignment points in the
font:
The keywords map to these alignment points as follows:
-
top
- The top of the em square
-
hanging
- The hanging baseline
-
middle
- The middle of the em square
-
alphabetic
- The alphabetic baseline
-
ideographic
- The ideographic baseline
-
bottom
- The bottom of the em square
The direction
attribute's allowed keywords are
as follows:
-
ltr
Treat input to the text preparation algorithm as left-to-right text.
-
rtl
Treat input to the text preparation algorithm as right-to-left text.
-
inherit
Default to the directionality of the
canvas
element orDocument
as appropriate.
The text preparation algorithm is as follows. It takes as input a string text, a CanvasDrawingStyles
object target, and an
optional length maxWidth. It returns an array of glyph shapes, each positioned
on a common coordinate space, a physical alignment whose value is one of
left, right, and center, and an inline box. (Most callers of this
algorithm ignore the physical alignment and the inline box.)
If maxWidth was provided but is less than or equal to zero, return an empty array.
Replace all the space characters in text with U+0020 SPACE characters.
Let font be the current font of target, as given by that object's
font
attribute.-
Apply the appropriate step from the following list to determine the value of direction:
- If the target object's
direction
attribute has the value "ltr
" - Let direction be 'ltr'.
- If the target object's
direction
attribute has the value "rtl
" - Let direction be 'rtl'.
- If the target object's font style source object is an element
- Let direction be the directionality of the target object's font style source object.
- If the target object's font style source object is a
Document
and thatDocument
has a root element child - Let direction be the directionality of the target object's font style source object's root element child.
- Otherwise
- Let direction be 'ltr'.
- If the target object's
Form a hypothetical infinitely-wide CSS line box containing a single inline box containing the text text, with all the properties at their initial values except the 'font' property of the inline box set to font, the 'direction' property of the inline box set to direction, and the 'white-space' property set to 'pre'. [CSS]
If maxWidth was provided and the hypothetical width of the inline box in the hypothetical line box is greater than maxWidth CSS pixels, then change font to have a more condensed font (if one is available or if a reasonably readable one can be synthesized by applying a horizontal scale factor to the font) or a smaller font, and return to the previous step.
-
The anchor point is a point on the inline box, and the physical alignment is one of the values left, right, and center. These variables are determined by the
textAlign
andtextBaseline
values as follows:Horizontal position:
- If
textAlign
isleft
- If
textAlign
isstart
and direction is 'ltr' - If
textAlign
isend
and direction is 'rtl' - Let the anchor point's horizontal position be the left edge of the inline box, and let physical alignment be left.
- If
textAlign
isright
- If
textAlign
isend
and direction is 'ltr' - If
textAlign
isstart
and direction is 'rtl' - Let the anchor point's horizontal position be the right edge of the inline box, and let physical alignment be right.
- If
textAlign
iscenter
- Let the anchor point's horizontal position be half way between the left and right edges of the inline box, and let physical alignment be center.
Vertical position:
- If
textBaseline
istop
- Let the anchor point's vertical position be the top of the em box of the first available font of the inline box.
- If
textBaseline
ishanging
- Let the anchor point's vertical position be the hanging baseline of the first available font of the inline box.
- If
textBaseline
ismiddle
- Let the anchor point's vertical position be half way between the bottom and the top of the em box of the first available font of the inline box.
- If
textBaseline
isalphabetic
- Let the anchor point's vertical position be the alphabetic baseline of the first available font of the inline box.
- If
textBaseline
isideographic
- Let the anchor point's vertical position be the ideographic baseline of the first available font of the inline box.
- If
textBaseline
isbottom
- Let the anchor point's vertical position be the bottom of the em box of the first available font of the inline box.
- If
-
Let result be an array constructed by iterating over each glyph in the inline box from left to right (if any), adding to the array, for each glyph, the shape of the glyph as it is in the inline box, positioned on a coordinate space using CSS pixels with its origin is at the anchor point.
Return result, physical alignment, and the inline box.
4.12.4.2.6 Building paths
Each object implementing the CanvasPathMethods
interface has a path. A path has a list of zero or
more subpaths. Each subpath consists of a list of one or more points, connected by straight or
curved line segments, and a flag indicating whether the subpath is closed or not. A
closed subpath is one where the last point of the subpath is connected to the first point of the
subpath by a straight line. Subpaths with only one point are ignored when painting the path.
Paths have a need new subpath flag. When this flag is set, certain APIs create a new subpath rather than extending the previous one. When a path is created, its need new subpath flag must be set.
When an object implementing the CanvasPathMethods
interface is created, its path must be initialised to zero subpaths.
-
context .
moveTo
(x, y) -
path .
moveTo
(x, y) -
Creates a new subpath with the given point.
-
context .
closePath
() -
path .
closePath
() -
Marks the current subpath as closed, and starts a new subpath with a point the same as the start and end of the newly closed subpath.
-
context .
lineTo
(x, y) -
path .
lineTo
(x, y) -
Adds the given point to the current subpath, connected to the previous one by a straight line.
-
context .
quadraticCurveTo
(cpx, cpy, x, y) -
path .
quadraticCurveTo
(cpx, cpy, x, y) -
Adds the given point to the current subpath, connected to the previous one by a quadratic Bézier curve with the given control point.
-
context .
bezierCurveTo
(cp1x, cp1y, cp2x, cp2y, x, y) -
path .
bezierCurveTo
(cp1x, cp1y, cp2x, cp2y, x, y) -
Adds the given point to the current subpath, connected to the previous one by a cubic Bézier curve with the given control points.
-
context .
arcTo
(x1, y1, x2, y2, radiusX [, radiusY, rotation ] ) -
path .
arcTo
(x1, y1, x2, y2, radiusX [, radiusY, rotation ] ) -
Adds an arc with the given control points and radius to the current subpath, connected to the previous point by a straight line.
If two radii are provided, the first controls the width of the arc's ellipse, and the second controls the height. If only one is provided, or if they are the same, the arc is from a circle. In the case of an ellipse, the rotation argument controls the clockwise inclination of the ellipse relative to the x-axis.
Throws an
IndexSizeError
exception if the given radius is negative. -
context .
arc
(x, y, radius, startAngle, endAngle [, anticlockwise ] ) -
path .
arc
(x, y, radius, startAngle, endAngle [, anticlockwise ] ) -
Adds points to the subpath such that the arc described by the circumference of the circle described by the arguments, starting at the given start angle and ending at the given end angle, going in the given direction (defaulting to clockwise), is added to the path, connected to the previous point by a straight line.
Throws an
IndexSizeError
exception if the given radius is negative. -
context .
ellipse
(x, y, radiusX, radiusY, rotation, startAngle, endAngle [, anticlockwise] ) -
path .
ellipse
(x, y, radiusX, radiusY, rotation, startAngle, endAngle [, anticlockwise] ) -
Adds points to the subpath such that the arc described by the circumference of the ellipse described by the arguments, starting at the given start angle and ending at the given end angle, going in the given direction (defaulting to clockwise), is added to the path, connected to the previous point by a straight line.
Throws an
IndexSizeError
exception if the given radius is negative. -
context .
rect
(x, y, w, h) -
path .
rect
(x, y, w, h) -
Adds a new closed subpath to the path, representing the given rectangle.
4.12.4.2.7
Path2D
objects
Path2D
objects can be used to declare paths that are then later used on
CanvasRenderingContext2D
objects. In addition to many of the APIs described in
earlier sections, Path2D
objects have methods to combine paths, and to add text to
paths.
-
path = new
Path2D
() -
Creates a new empty
Path2D
object. -
path = new
Path2D
(path) -
Creates a new
Path2D
object that is a copy of the argument. -
path = new
Path2D
(paths [, fillRule ] ) -
Creates a new
Path2D
object that describes a path that outlines the given paths, using the given fill rule. -
path = new
Path2D
(d) -
Creates a new path with the path described by the argument, interpreted as SVG path data. [SVG]
-
path .
addPath
(path [, transform ] ) -
path .
addPathByStrokingPath
(path, styles [, transform ] ) -
Adds to the path the path given by the argument.
In the case of the stroking variants, the line styles are taken from the styles argument, which can be either a
DrawingStyle
object or aCanvasRenderingContext2D
object. -
path .
addText
(text, styles, transform, x, y [, maxWidth ] ) -
path .
addText
(text, styles, transform, path [, maxWidth ] ) -
path .
addPathByStrokingText
(text, styles, transform, x, y [, maxWidth ] ) -
path .
addPathByStrokingText
(text, styles, transform, path [, maxWidth ] ) -
Adds to the path a series of subpaths corresponding to the given text. If the arguments give a coordinate, the text is drawn horizontally at the given coordinates. If the arguments give a path, the text is drawn along the path. If a maximum width is provided, the text will be scaled to fit that width if necessary.
The font, and in the case of the stroking variants, the line styles, are taken from the styles argument, which can be either a
DrawingStyle
object or aCanvasRenderingContext2D
object.
4.12.4.2.8 Transformations
Each CanvasRenderingContext2D
object has a current transformation matrix,
as well as methods (described in this section) to manipulate it. When a
CanvasRenderingContext2D
object is created, its transformation matrix must be
initialised to the identity transform.
The transformation matrix is applied to coordinates when creating the current default
path, and when painting text, shapes, and Path2D
objects, on
CanvasRenderingContext2D
objects.
Most of the API uses SVGMatrix
objects rather than this API. This API
remains mostly for historical reasons.
-
context .
currentTransform
[ = value ] -
Returns the transformation matrix, as an
SVGMatrix
object.Can be set, to change the transformation matrix.
-
context .
scale
(x, y) -
Changes the transformation matrix to apply a scaling transformation with the given characteristics.
-
context .
rotate
(angle) -
Changes the transformation matrix to apply a rotation transformation with the given characteristics. The angle is in radians.
-
context .
translate
(x, y) -
Changes the transformation matrix to apply a translation transformation with the given characteristics.
-
context .
transform
(a, b, c, d, e, f) -
Changes the transformation matrix to apply the matrix given by the arguments as described below.
-
context .
setTransform
(a, b, c, d, e, f) -
Changes the transformation matrix to the matrix given by the arguments as described below.
-
context .
resetTransform
() -
Changes the transformation matrix to the identity transform.
a | c | e |
b | d | f |
0 | 0 | 1 |
The arguments a, b, c, d, e, and f are sometimes called m11, m12, m21, m22, dx, and dy or m11, m21, m12, m22, dx, and dy. Care should be taken in particular with the order of the second and third arguments (b and c) as their order varies from API to API and APIs sometimes use the notation m12/m21 and sometimes m21/m12 for those positions.
4.12.4.2.9 Image sources for 2D rendering contexts
Several methods in the CanvasRenderingContext2D
API take the union type
CanvasImageSource
as an argument.
This union type allows objects implementing any of the following interfaces to be used as image sources:
-
HTMLImageElement
(img
elements) -
HTMLVideoElement
(video
elements) -
HTMLCanvasElement
(canvas
elements) CanvasRenderingContext2D
ImageBitmap
The ImageBitmap
interface can be created from a number of other
image-representing types, including ImageData
.
When a user agent is required to check the usability of the image
argument, where image is a CanvasImageSource
object, the
user agent must run these steps, which return either good, bad, or
aborted:
-
If the image argument is an
HTMLImageElement
object that is in the broken state, then throw anInvalidStateError
exception, return aborted, and abort these steps. If the image argument is an
HTMLImageElement
object that is not fully decodable, or if the image argument is anHTMLVideoElement
object whosereadyState
attribute is eitherHAVE_NOTHING
orHAVE_METADATA
, then return bad and abort these steps.-
If the image argument is an
HTMLImageElement
object with an intrinsic width or intrinsic height (or both) equal to zero, then return bad and abort these steps. -
If the image argument is an
HTMLCanvasElement
object with either a horizontal dimension or a vertical dimension equal to zero, then return bad and abort these steps. Return good.
When a CanvasImageSource
object represents an HTMLImageElement
, the
element's image must be used as the source image.
Specifically, when a CanvasImageSource
object represents an animated image in an
HTMLImageElement
, the user agent must use the default image of the animation (the
one that the format defines is to be used when animation is not supported or is disabled), or, if
there is no such image, the first frame of the animation, when rendering the image for
CanvasRenderingContext2D
APIs.
When a CanvasImageSource
object represents an HTMLVideoElement
, then
the frame at the current playback position when the method with the argument is
invoked must be used as the source image when rendering the image for
CanvasRenderingContext2D
APIs, and the source image's dimensions must be the intrinsic width and intrinsic height of the media resource
(i.e. after any aspect-ratio correction has been applied).
When a CanvasImageSource
object represents an HTMLCanvasElement
, the
element's bitmap must be used as the source image.
When a CanvasImageSource
object represents a CanvasRenderingContext2D
, the
object's scratch bitmap must be used as the source image.
When a CanvasImageSource
object represents an element that is being
rendered and that element has been resized, the original image data of the source image
must be used, not the image as it is rendered (e.g. width
and
height
attributes on the source element have no effect on how
the object is interpreted when rendering the image for CanvasRenderingContext2D
APIs).
When a CanvasImageSource
object represents an ImageBitmap
, the
object's bitmap image data must be used as the source image.
The image argument is not origin-clean if it is an
HTMLImageElement
or HTMLVideoElement
whose origin is not
the same as the origin specified by the entry
settings object, or if it is an HTMLCanvasElement
whose bitmap's origin-clean flag is false, or if it is a
CanvasRenderingContext2D
object whose scratch bitmap's origin-clean flag is false.
4.12.4.2.10 Fill and stroke styles
-
context .
fillStyle
[ = value ] -
Returns the current style used for filling shapes.
Can be set, to change the fill style.
The style can be either a string containing a CSS color, or a
CanvasGradient
orCanvasPattern
object. Invalid values are ignored. -
context .
strokeStyle
[ = value ] -
Returns the current style used for stroking shapes.
Can be set, to change the stroke style.
The style can be either a string containing a CSS color, or a
CanvasGradient
orCanvasPattern
object. Invalid values are ignored.
There are two types of gradients, linear gradients and radial gradients, both represented by
objects implementing the opaque CanvasGradient
interface.
Once a gradient has been created (see below), stops are placed along it to define how the colors are distributed along the gradient.
-
gradient .
addColorStop
(offset, color) -
Adds a color stop with the given color to the gradient at the given offset. 0.0 is the offset at one end of the gradient, 1.0 is the offset at the other end.
Throws an
IndexSizeError
exception if the offset is out of range. Throws aSyntaxError
exception if the color cannot be parsed. -
gradient = context .
createLinearGradient
(x0, y0, x1, y1) -
Returns a
CanvasGradient
object that represents a linear gradient that paints along the line given by the coordinates represented by the arguments. -
gradient = context .
createRadialGradient
(x0, y0, r0, x1, y1, r1) -
Returns a
CanvasGradient
object that represents a radial gradient that paints along the cone given by the circles represented by the arguments.If either of the radii are negative, throws an
IndexSizeError
exception.
Patterns are represented by objects implementing the opaque CanvasPattern
interface.
-
pattern = context .
createPattern
(image, repetition) -
Returns a
CanvasPattern
object that uses the given image and repeats in the direction(s) given by the repetition argument.The allowed values for repetition are
repeat
(both directions),repeat-x
(horizontal only),repeat-y
(vertical only), andno-repeat
(neither). If the repetition argument is empty, the valuerepeat
is used.If the image isn't yet fully decoded, then nothing is drawn. If the image is a canvas with no data, throws an
InvalidStateError
exception. -
pattern .
setTransform
(transform) -
Sets the transformation matrix that will be used when rendering the pattern during a fill or stroke painting operation.
4.12.4.2.11 Drawing rectangles to the bitmap
There are three methods that immediately draw rectangles to the bitmap. They each take four arguments; the first two give the x and y coordinates of the top left of the rectangle, and the second two give the width w and height h of the rectangle, respectively.
-
context .
clearRect
(x, y, w, h) -
Clears all pixels on the bitmap in the given rectangle to transparent black.
-
context .
fillRect
(x, y, w, h) -
Paints the given rectangle onto the bitmap, using the current fill style.
-
context .
strokeRect
(x, y, w, h) -
Paints the box that outlines the given rectangle onto the bitmap, using the current stroke style.
4.12.4.2.12 Drawing text to the bitmap
-
context .
fillText
(text, x, y [, maxWidth ] ) -
context .
strokeText
(text, x, y [, maxWidth ] ) -
Fills or strokes (respectively) the given text at the given position. If a maximum width is provided, the text will be scaled to fit that width if necessary.
-
metrics = context .
measureText
(text) -
Returns a
TextMetrics
object with the metrics of the given text in the current font. -
metrics .
width
-
metrics .
actualBoundingBoxLeft
-
metrics .
actualBoundingBoxRight
-
metrics .
fontBoundingBoxAscent
-
metrics .
fontBoundingBoxDescent
-
metrics .
actualBoundingBoxAscent
-
metrics .
actualBoundingBoxDescent
-
metrics .
emHeightAscent
-
metrics .
emHeightDescent
-
metrics .
hangingBaseline
-
metrics .
alphabeticBaseline
-
metrics .
ideographicBaseline
-
Returns the measurement described below.
-
width
attribute The width of that inline box, in CSS pixels. (The text's advance width.)
-
actualBoundingBoxLeft
attribute -
The distance parallel to the baseline from the alignment point given by the
textAlign
attribute to the left side of the bounding rectangle of the given text, in CSS pixels; positive numbers indicating a distance going left from the given alignment point.The sum of this value and the next (
actualBoundingBoxRight
) can be wider than the width of the inline box (width
), in particular with slanted fonts where characters overhang their advance width. -
actualBoundingBoxRight
attribute -
The distance parallel to the baseline from the alignment point given by the
textAlign
attribute to the right side of the bounding rectangle of the given text, in CSS pixels; positive numbers indicating a distance going right from the given alignment point. -
fontBoundingBoxAscent
attribute -
The distance from the horizontal line indicated by the
textBaseline
attribute to the top of the highest bounding rectangle of all the fonts used to render the text, in CSS pixels; positive numbers indicating a distance going up from the given baseline.This value and the next are useful when rendering a background that must have a consistent height even if the exact text being rendered changes. The
actualBoundingBoxAscent
attribute (and its corresponding attribute for the descent) are useful when drawing a bounding box around specific text. -
fontBoundingBoxDescent
attribute The distance from the horizontal line indicated by the
textBaseline
attribute to the bottom of the lowest bounding rectangle of all the fonts used to render the text, in CSS pixels; positive numbers indicating a distance going down from the given baseline.-
actualBoundingBoxAscent
attribute -
The distance from the horizontal line indicated by the
textBaseline
attribute to the top of the bounding rectangle of the given text, in CSS pixels; positive numbers indicating a distance going up from the given baseline.This number can vary greatly based on the input text, even if the first font specified covers all the characters in the input. For example, the
actualBoundingBoxAscent
of a lowercase "o" from an alphabetic baseline would be less than that of an uppercase "F". The value can easily be negative; for example, the distance from the top of the em box (textBaseline
value "top
") to the top of the bounding rectangle when the given text is just a single comma ",
" would likely (unless the font is quite unusual) be negative. -
actualBoundingBoxDescent
attribute The distance from the horizontal line indicated by the
textBaseline
attribute to the bottom of the bounding rectangle of the given text, in CSS pixels; positive numbers indicating a distance going down from the given baseline.-
emHeightAscent
attribute The distance from the horizontal line indicated by the
textBaseline
attribute to the highest top of the em squares in the line box, in CSS pixels; positive numbers indicating that the given baseline is below the top of that em square (so this value will usually be positive). Zero if the given baseline is the top of that em square; half the font size if the given baseline is the middle of that em square.-
emHeightDescent
attribute The distance from the horizontal line indicated by the
textBaseline
attribute to the lowest bottom of the em squares in the line box, in CSS pixels; positive numbers indicating that the given baseline is below the bottom of that em square (so this value will usually be negative). (Zero if the given baseline is the top of that em square.)-
hangingBaseline
attribute The distance from the horizontal line indicated by the
textBaseline
attribute to the hanging baseline of the line box, in CSS pixels; positive numbers indicating that the given baseline is below the hanging baseline. (Zero if the given baseline is the hanging baseline.)-
alphabeticBaseline
attribute The distance from the horizontal line indicated by the
textBaseline
attribute to the alphabetic baseline of the line box, in CSS pixels; positive numbers indicating that the given baseline is below the alphabetic baseline. (Zero if the given baseline is the alphabetic baseline.)-
ideographicBaseline
attribute The distance from the horizontal line indicated by the
textBaseline
attribute to the ideographic baseline of the line box, in CSS pixels; positive numbers indicating that the given baseline is below the ideographic baseline. (Zero if the given baseline is the ideographic baseline.)
Glyphs rendered using fillText()
and
strokeText()
can spill out of the box given by the
font size (the em square size) and the width returned by measureText()
(the text width). Authors are encouraged
to use the bounding box values described above if this is an issue.
A future version of the 2D context API may provide a way to render fragments of documents, rendered using CSS, straight to the canvas. This would be provided in preference to a dedicated way of doing multiline layout.
4.12.4.2.13 Drawing paths to the canvas
The context always has a current default path. There is only one current default path, it is not part of the drawing state. The current default path is a path, as described above.
-
context .
beginPath
() -
Resets the current default path.
-
context .
fill
( [ fillRule ] ) -
context .
fill
(path [, fillRule ] ) -
Fills the subpaths of the current default path or the given path with the current fill style, obeying the given fill rule.
-
context .
stroke
() -
context .
stroke
(path) -
Strokes the subpaths of the current default path or the given path with the current stroke style.
-
context .
drawSystemFocusRing
(element) -
context .
drawSystemFocusRing
(path, element) -
If the given element is focused, draws a focus ring around the current default path or the given path, following the platform conventions for focus rings.
-
shouldDraw = context .
drawCustomFocusRing
(element) -
shouldDraw = context .
drawCustomFocusRing
(path, element) -
If the given element is focused, and the user has configured his system to draw focus rings in a particular manner (for example, high contrast focus rings), draws a focus ring around the current default path or the given path and returns false.
Otherwise, returns true if the given element is focused, and false otherwise. This can thus be used to determine when to draw a focus ring (see the example below).
-
context .
scrollPathIntoView
() -
context .
scrollPathIntoView
(path) -
Scrolls the current default path or the given path into view. This is especially useful on devices with small screens, where the whole canvas might not be visible at once.
-
context .
clip
( [ fillRule ] ) -
context .
clip
(path [, fillRule ] ) -
Further constrains the clipping region to the current default path or the given path, using the given fill rule to determine what points are in the path.
-
context .
resetClip
() -
Unconstrains the clipping region.
-
context .
isPointInPath
(x, y [, fillRule ] ) -
context .
isPointInPath
(path, x, y [, fillRule ] ) -
Returns true if the given point is in the current default path or the given path, using the given fill rule to determine what points are in the path.
-
context .
isPointInStroke
(x, y) -
context .
isPointInStroke
(path, x, y) -
Returns true if the given point would be in the region covered by the stroke of the current default path or the given path, given the current stroke style.
This canvas
element has a couple of checkboxes. The path-related commands are
highlighted:
<canvas height=400 width=750> <label><input type=checkbox id=showA> Show As</label> <label><input type=checkbox id=showB> Show Bs</label> <!-- ... --> </canvas> <script> function drawCheckbox(context, element, x, y, paint) { context.save(); context.font = '10px sans-serif'; context.textAlign = 'left'; context.textBaseline = 'middle'; var metrics = context.measureText(element.labels[0].textContent); if (paint) { context.beginPath(); context.strokeStyle = 'black'; context.rect(x-5, y-5, 10, 10); context.stroke(); context.addHitRegion({ control: element }); if (element.checked) { context.fillStyle = 'black'; context.fill(); } context.fillText(element.labels[0].textContent, x+5, y); } context.beginPath(); context.rect(x-7, y-7, 12 + metrics.width+2, 14); if (paint && context.drawCustomFocusRing(element)) { context.strokeStyle = 'silver'; context.stroke(); } context.restore(); } function drawBase() { /* ... */ } function drawAs() { /* ... */ } function drawBs() { /* ... */ } function redraw() { var canvas = document.getElementsByTagName('canvas')[0]; var context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); drawCheckbox(context, document.getElementById('showA'), 20, 40, true); drawCheckbox(context, document.getElementById('showB'), 20, 60, true); drawBase(); if (document.getElementById('showA').checked) drawAs(); if (document.getElementById('showB').checked) drawBs(); } function processClick(event) { var canvas = document.getElementsByTagName('canvas')[0]; var context = canvas.getContext('2d'); var x = event.clientX; var y = event.clientY; var node = event.target; while (node) { x -= node.offsetLeft - node.scrollLeft; y -= node.offsetTop - node.scrollTop; node = node.offsetParent; } drawCheckbox(context, document.getElementById('showA'), 20, 40, false); if (context.isPointInPath(x, y)) document.getElementById('showA').checked = !(document.getElementById('showA').checked); drawCheckbox(context, document.getElementById('showB'), 20, 60, false); if (context.isPointInPath(x, y)) document.getElementById('showB').checked = !(document.getElementById('showB').checked); redraw(); } document.getElementsByTagName('canvas')[0].addEventListener('focus', redraw, true); document.getElementsByTagName('canvas')[0].addEventListener('blur', redraw, true); document.getElementsByTagName('canvas')[0].addEventListener('change', redraw, true); document.getElementsByTagName('canvas')[0].addEventListener('click', processClick, false); redraw(); </script>
4.12.4.2.14 Drawing images
To draw images, the drawImage
method
can be used.
-
context .
drawImage
(image, dx, dy) -
context .
drawImage
(image, dx, dy, dw, dh) -
context .
drawImage
(image, sx, sy, sw, sh, dx, dy, dw, dh) -
Draws the given image onto the canvas. The arguments are interpreted as follows:
If the image isn't yet fully decoded, then nothing is drawn. If the image is a canvas with no data, throws an
InvalidStateError
exception.
4.12.4.2.15 Hit regions
A hit region list is a list of hit regions for a bitmap.
Each hit region consists of the following information:
A set of pixels on the bitmap for which this region is responsible.
A bounding circumference on the bitmap that surrounds the hit region's set of pixels as they stood when it was created.
Optionally, a non-empty string representing an ID for distinguishing the region from others.
Optionally, a reference to another region that acts as the parent for this one.
A count of regions that have this one as their parent, known as the hit region's child count.
A cursor specification, in the form of either a CSS cursor value, or the string "
inherit
" meaning that the cursor of the hit region's parent, if any, or of thecanvas
element, if not, is to be used instead.-
Optionally, either a control, or an unbacked region description.
A control is a reference to an
Element
node, to which, in certain conditions, the user agent will route events, and from which the user agent will determine the state of the hit region for the purposes of accessibility tools. (The control is ignored when it is not a descendant of thecanvas
element.)An unbacked region description consists of the following:
-
Optionally, a label.
An ARIA role, which, if the unbacked region description also has a label, could be the empty string.
-
-
context .
addHitRegion
(options) -
Adds a hit region to the bitmap. The argument is an object with the following members:
-
path
(default null) - A
Path2D
object that describes the pixels that form part of the region. If this member is not provided or is set to null, the current default path is used instead. -
fillRule
(default "nonzero
") - The fill rule to use when determining which pixels are inside the path.
-
id
(default empty string) - The ID to use for this region. This is used in
MouseEvent
events on thecanvas
(event.region
) and as a way to reference this region in later calls toaddHitRegion()
. -
parentID
(default null) - The ID of the parent region, for purposes of navigation by accessibility tools and for cursor fallback.
-
cursor
(default "inherit
") - The cursor to use when the mouse is over this region. The value "
inherit
" means to use the cursor for the parent region (as specified by theparentID
member), if any, or to use thecanvas
element's cursor if the region has no parent. -
control
(default null) - An element (that is a descendant of the
canvas
) to which events are to be routed, and which accessibility tools are to use as a surrogate for describing and interacting with this region. -
label
(default null) - A text label for accessibility tools to use as a description of this region, if there is no control.
-
role
(default null) - An ARIA role for accessibility tools to use to determine how to represent this region, if there is no control.
Hit regions can be used for a variety of purposes:
- With an ID, they can make hit detection easier by having the user agent check which region the mouse is over and include the ID in the mouse events.
- With a control, they can make routing events to DOM elements automatic, allowing e.g.
clicks on a
canvas
to automatically submit a form via abutton
element. - With a label, they can make it easier for users to explore a
canvas
without seeing it, e.g. by touch on a mobile device. - With a cursor, they can make it easier for different regions of the
canvas
to have different cursors, with the user agent automatically switching between them.
-
-
context .
removeHitRegion
(id) -
Removes a hit region (and all its descendants) from the canvas bitmap. The argument is the ID of a region added using
addHitRegion()
.The pixels that were covered by this region and its descendants are effectively cleared by this operation, leaving the regions non-interactive. In particular, regions that occupied the same pixels before the removed regions were added, overlapping them, do not resume their previous role.
The MouseEvent
interface is extended to support hit regions:
partial interface MouseEvent { readonly attribute DOMString? region; }; partial dictionary MouseEventInit { DOMString? region; };
-
event .
region
-
If the mouse was over a hit region, then this returns the hit region's ID, if it has one.
Otherwise, returns null.
The Touch
interface is extended to support hit regions also: [TOUCH]
partial interface Touch { readonly attribute DOMString? region; };
-
touch .
region
-
If the touch point was over a hit region when it was first placed on the surface, then this returns the hit region's ID, if it has one.
Otherwise, returns null.
4.12.4.2.16 Pixel manipulation
-
imagedata = new
ImageData
(sw, sh) -
imagedata = context .
createImageData
(sw, sh) -
Returns an
ImageData
object with the given dimensions. All the pixels in the returned object are transparent black.Throws an
IndexSizeError
exception if either of the width or height arguments are zero. -
imagedata = context .
createImageData
(imagedata) -
Returns an
ImageData
object with the same dimensions as the argument. All the pixels in the returned object are transparent black. -
imagedata = new
ImageData
(data, sw [, sh ] ) -
Returns an
ImageData
object using the data provided in theUint8ClampedArray
argument, interpreted using the given dimensions.As each pixel in the data is represented by four numbers, the length of the data needs to be a multiple of four times the given width. If the height is provided as well, then the length needs to be exactly the width times the height times 4.
Throws an
IndexSizeError
exception if the given data and dimensions can't be interpreted consistently, or if either dimension is zero. -
imagedata = context .
getImageData
(sx, sy, sw, sh) -
Returns an
ImageData
object containing the image data for the given rectangle of the bitmap.Throws an
IndexSizeError
exception if the either of the width or height arguments are zero. -
imagedata .
width
-
imagedata .
height
-
Returns the actual dimensions of the data in the
ImageData
object, in pixels. -
imagedata .
data
-
Returns the one-dimensional array containing the data in RGBA order, as integers in the range 0 to 255.
-
context .
putImageData
(imagedata, dx, dy [, dirtyX, dirtyY, dirtyWidth, dirtyHeight ] ) -
Paints the data from the given
ImageData
object onto the bitmap. If a dirty rectangle is provided, only the pixels from that rectangle are painted.The
globalAlpha
andglobalCompositeOperation
attributes, as well as the shadow attributes, are ignored for the purposes of this method call; pixels in the canvas are replaced wholesale, with no composition, alpha blending, no shadows, etc.Throws a
NotSupportedError
exception if any of the arguments are not finite.Throws an
InvalidStateError
exception if the imagedata object's data has been neutered.
In the following example, the script generates an ImageData
object so that it can
draw onto it.
// canvas is a reference to a <canvas> element var context = canvas.getContext('2d'); // create a blank slate var data = context.createImageData(canvas.width, canvas.height); // create some plasma FillPlasma(data, 'green'); // green plasma // add a cloud to the plasma AddCloud(data, data.width/2, data.height/2); // put a cloud in the middle // paint the plasma+cloud on the canvas context.putImageData(data, 0, 0); // support methods function FillPlasma(data, color) { ... } function AddCloud(data, x, y) { ... }
Here is an example of using getImageData()
and putImageData()
to implement an edge detection
filter.
<!DOCTYPE HTML> <html> <head> <title>Edge detection demo</title> <script> var image = new Image(); function init() { image.onload = demo; image.src = "image.jpeg"; } function demo() { var canvas = document.getElementsByTagName('canvas')[0]; var context = canvas.getContext('2d'); // draw the image onto the canvas context.drawImage(image, 0, 0); // get the image data to manipulate var input = context.getImageData(0, 0, canvas.width, canvas.height); // get an empty slate to put the data into var output = context.createImageData(canvas.width, canvas.height); // alias some variables for convenience // notice that we are using input.width and input.height here // as they might not be the same as canvas.width and canvas.height // (in particular, they might be different on high-res displays) var w = input.width, h = input.height; var inputData = input.data; var outputData = output.data; // edge detection for (var y = 1; y < h-1; y += 1) { for (var x = 1; x < w-1; x += 1) { for (var c = 0; c < 3; c += 1) { var i = (y*w + x)*4 + c; outputData[i] = 127 + -inputData[i - w*4 - 4] - inputData[i - w*4] - inputData[i - w*4 + 4] + -inputData[i - 4] + 8*inputData[i] - inputData[i + 4] + -inputData[i + w*4 - 4] - inputData[i + w*4] - inputData[i + w*4 + 4]; } outputData[(y*w + x)*4 + 3] = 255; // alpha } } // put the image data back after manipulation context.putImageData(output, 0, 0); } </script> </head> <body onload="init()"> <canvas></canvas> </body> </html>
4.12.4.2.17 Compositing
-
context .
globalAlpha
[ = value ] -
Returns the current alpha value applied to rendering operations.
Can be set, to change the alpha value. Values outside of the range 0.0 .. 1.0 are ignored.
-
context .
globalCompositeOperation
[ = value ] -
Returns the current composition operation, from the values defined in the Compositing and Blending specification. [COMPOSITE].
Can be set, to change the composition operation. Unknown values are ignored.
4.12.4.2.18 Image smoothing
-
context .
imageSmoothingEnabled
[ = value ] -
Returns whether pattern fills and the
drawImage()
method will attempt to smooth images if their pixels don't line up exactly with the display, when scaling images up.Can be set, to change whether images are smoothed (true) or not (false).
4.12.4.2.19 Shadows
All drawing operations are affected by the four global shadow attributes.
-
context .
shadowColor
[ = value ] -
Returns the current shadow color.
Can be set, to change the shadow color. Values that cannot be parsed as CSS colors are ignored.
-
context .
shadowOffsetX
[ = value ] -
context .
shadowOffsetY
[ = value ] -
Returns the current shadow offset.
Can be set, to change the shadow offset. Values that are not finite numbers are ignored.
-
context .
shadowBlur
[ = value ] -
Returns the current level of blur applied to shadows.
Can be set, to change the blur level. Values that are not finite numbers greater than or equal to zero are ignored.
If the current composition operation is copy
, shadows
effectively won't render (since the shape will overwrite the shadow).
4.12.4.2.20 Best practices
When a canvas is interactive, authors should include focusable elements in the element's fallback content corresponding to each focusable part of the canvas, as in the example above.
To expose text and interactive content on a canvas
to users of accessibility
tools, authors should use the addHitRegion()
API. When rendering focus rings, to ensure that focus rings have the appearance of native focus
rings, authors should use the drawSystemFocusRing()
method, passing it the
element for which a ring is being drawn. This method only draws the focus ring if the element is
focused, so that it can simply be called whenever drawing the element, without
checking whether the element is focused or not first.
Authors should avoid implementing text editing controls
using the canvas
element. Doing so has a large number of disadvantages:
- Mouse placement of the caret has to be reimplemented.
- Keyboard movement of the caret has to be reimplemented (possibly across lines, for multiline text input).
- Scrolling of the text field has to be implemented (horizontally for long lines, vertically for multiline input).
- Native features such as copy-and-paste have to be reimplemented.
- Native features such as spell-checking have to be reimplemented.
- Native features such as drag-and-drop have to be reimplemented.
- Native features such as page-wide text search have to be reimplemented.
- Native features specific to the user, for example custom text services, have to be reimplemented. This is close to impossible since each user might have different services installed, and there is an unbounded set of possible such services.
- Bidirectional text editing has to be reimplemented.
- For multiline text editing, line wrapping has to be implemented for all relevant languages.
- Text selection has to be reimplemented.
- Dragging of bidirectional text selections has to be reimplemented.
- Platform-native keyboard shortcuts have to be reimplemented.
- Platform-native input method editors (IMEs) have to be reimplemented.
- Undo and redo functionality has to be reimplemented.
- Accessibility features such as magnification following the caret or selection have to be reimplemented.
This is a huge amount of work, and authors are most strongly encouraged to avoid doing any of
it by instead using the input
element, the textarea
element, or the
contenteditable
attribute.
4.12.4.2.21 Examples
Here is an example of a script that uses canvas to draw pretty glowing lines.
<canvas width="800" height="450"></canvas> <script> var context = document.getElementsByTagName('canvas')[0].getContext('2d'); var lastX = context.canvas.width * Math.random(); var lastY = context.canvas.height * Math.random(); var hue = 0; function line() { context.save(); context.translate(context.canvas.width/2, context.canvas.height/2); context.scale(0.9, 0.9); context.translate(-context.canvas.width/2, -context.canvas.height/2); context.beginPath(); context.lineWidth = 5 + Math.random() * 10; context.moveTo(lastX, lastY); lastX = context.canvas.width * Math.random(); lastY = context.canvas.height * Math.random(); context.bezierCurveTo(context.canvas.width * Math.random(), context.canvas.height * Math.random(), context.canvas.width * Math.random(), context.canvas.height * Math.random(), lastX, lastY); hue = hue + 10 * Math.random(); context.strokeStyle = 'hsl(' + hue + ', 50%, 50%)'; context.shadowColor = 'white'; context.shadowBlur = 10; context.stroke(); context.restore(); } setInterval(line, 50); function blank() { context.fillStyle = 'rgba(0,0,0,0.1)'; context.fillRect(0, 0, context.canvas.width, context.canvas.height); } setInterval(blank, 40); </script>
The 2D rendering context for canvas
is often used for sprite-based games. The
following example demonstrates this:
Here is the source for this example:
<!DOCTYPE HTML> <title>Blue Robot Demo</title> <base href="http://www.whatwg.org/demos/canvas/blue-robot/"> <style> html { overflow: hidden; min-height: 200px; min-width: 380px; } body { height: 200px; position: relative; margin: 8px; } .buttons { position: absolute; bottom: 0px; left: 0px; margin: 4px; } </style> <canvas width="380" height="200"></canvas> <script> var Landscape = function (context, width, height) { this.offset = 0; this.width = width; this.advance = function (dx) { this.offset += dx; }; this.horizon = height * 0.7; // This creates the sky gradient (from a darker blue to white at the bottom) this.sky = context.createLinearGradient(0, 0, 0, this.horizon); this.sky.addColorStop(0.0, 'rgb(55,121,179)'); this.sky.addColorStop(0.7, 'rgb(121,194,245)'); this.sky.addColorStop(1.0, 'rgb(164,200,214)'); // this creates the grass gradient (from a darker green to a lighter green) this.earth = context.createLinearGradient(0, this.horizon, 0, height); this.earth.addColorStop(0.0, 'rgb(81,140,20)'); this.earth.addColorStop(1.0, 'rgb(123,177,57)'); this.paintBackground = function (context, width, height) { // first, paint the sky and grass rectangles context.fillStyle = this.sky; context.fillRect(0, 0, width, this.horizon); context.fillStyle = this.earth; context.fillRect(0, this.horizon, width, height-this.horizon); // then, draw the cloudy banner // we make it cloudy by having the draw text off the top of the // canvas, and just having the blurred shadow shown on the canvas context.save(); context.translate(width-((this.offset+(this.width*3.2)) % (this.width*4.0))+0, 0); context.shadowColor = 'white'; context.shadowOffsetY = 30+this.horizon/3; // offset down on canvas context.shadowBlur = '5'; context.fillStyle = 'white'; context.textAlign = 'left'; context.textBaseline = 'top'; context.font = '20px sans-serif'; context.fillText('WHATWG ROCKS', 10, -30); // text up above canvas context.restore(); // then, draw the background tree context.save(); context.translate(width-((this.offset+(this.width*0.2)) % (this.width*1.5))+30, 0); context.beginPath(); context.fillStyle = 'rgb(143,89,2)'; context.lineStyle = 'rgb(10,10,10)'; context.lineWidth = 2; context.rect(0, this.horizon+5, 10, -50); // trunk context.fill(); context.stroke(); context.beginPath(); context.fillStyle = 'rgb(78,154,6)'; context.arc(5, this.horizon-60, 30, 0, Math.PI*2); // leaves context.fill(); context.stroke(); context.restore(); }; this.paintForeground = function (context, width, height) { // draw the box that goes in front context.save(); context.translate(width-((this.offset+(this.width*0.7)) % (this.width*1.1))+0, 0); context.beginPath(); context.rect(0, this.horizon - 5, 25, 25); context.fillStyle = 'rgb(220,154,94)'; context.lineStyle = 'rgb(10,10,10)'; context.lineWidth = 2; context.fill(); context.stroke(); context.restore(); }; }; </script> <script> var BlueRobot = function () { this.sprites = new Image(); this.sprites.src = 'blue-robot.png'; // this sprite sheet has 8 cells this.targetMode = 'idle'; this.walk = function () { this.targetMode = 'walk'; }; this.stop = function () { this.targetMode = 'idle'; }; this.frameIndex = { 'idle': [0], // first cell is the idle frame 'walk': [1,2,3,4,5,6], // the walking animation is cells 1-6 'stop': [7], // last cell is the stopping animation }; this.mode = 'idle'; this.frame = 0; // index into frameIndex this.tick = function () { // this advances the frame and the robot // the return value is how many pixels the robot has moved this.frame += 1; if (this.frame >= this.frameIndex[this.mode].length) { // we've reached the end of this animation cycle this.frame = 0; if (this.mode != this.targetMode) { // switch to next cycle if (this.mode == 'walk') { // we need to stop walking before we decide what to do next this.mode = 'stop'; } else if (this.mode == 'stop') { if (this.targetMode == 'walk') this.mode = 'walk'; else this.mode = 'idle'; } else if (this.mode == 'idle') { if (this.targetMode == 'walk') this.mode = 'walk'; } } } if (this.mode == 'walk') return 8; return 0; }, this.paint = function (context, x, y) { if (!this.sprites.complete) return; // draw the right frame out of the sprite sheet onto the canvas // we assume each frame is as high as the sprite sheet // the x,y coordinates give the position of the bottom center of the sprite context.drawImage(this.sprites, this.frameIndex[this.mode][this.frame] * this.sprites.height, 0, this.sprites.height, this.sprites.height, x-this.sprites.height/2, y-this.sprites.height, this.sprites.height, this.sprites.height); }; }; </script> <script> var canvas = document.getElementsByTagName('canvas')[0]; var context = canvas.getContext('2d'); var landscape = new Landscape(context, canvas.width, canvas.height); var blueRobot = new BlueRobot(); // paint when the browser wants us to, using requestAnimationFrame() function paint() { context.clearRect(0, 0, canvas.width, canvas.height); landscape.paintBackground(context, canvas.width, canvas.height); blueRobot.paint(context, canvas.width/2, landscape.horizon*1.1); landscape.paintForeground(context, canvas.width, canvas.height); requestAnimationFrame(paint); } paint(); // but tick every 150ms, so that we don't slow down when we don't paint setInterval(function () { var dx = blueRobot.tick(); landscape.advance(dx); }, 100); </script> <p class="buttons"> <input type=button value="Walk" onclick="blueRobot.walk()"> <input type=button value="Stop" onclick="blueRobot.stop()"> <footer> <small> Blue Robot Player Sprite by <a href="http://johncolburn.deviantart.com/">JohnColburn</a>. Licensed under the terms of the Creative Commons Attribution Share-Alike 3.0 Unported license.</small> <small> This work is itself licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</small> </footer>
4.12.4.3 Serializing bitmaps to a file
Type | Other arguments | Reference |
---|---|---|
image/jpeg
|
The second argument is a number in the range 0.0 to 1.0 inclusive treated as the desired quality level. |
4.13 Common idioms without dedicated elements
4.13.1 The main part of the content
The main content of a page — not including headers and footers, navigation links, sidebars, advertisements, and so forth — can be marked up in a variety of ways, depending on the needs of the author.
The simplest solution is to not mark up the main content at all, and just leave it as implicit.
Another way to think of this is that the body
elements marks up the main content of
the page, and the bits that aren't main content are excluded through the use of more appropriate
elements like aside
and nav
.
Here is a short Web page marked up along this minimalistic school of thought. The main content
is highlighted. Notice how all the other content in the body
is marked up
with elements to indicate that it's not part of the main content, in this case
header
, nav
, and footer
.
<!DOCTYPE HTML> <html> <head> <title> My Toys </title> </head> <body> <header> <h1>My toys</h1> </header> <nav> <p><a href="/">Home</a></p> <p><a href="/contact">Contact</a></p> </nav> <p>I really like my chained book and my telephone. I'm not such a fan of my big ball.</p> <p>Another toy I like is my mirror.</p> <footer> <p>© copyright 2010 by the boy</p> </footer> </body> </html>
If the main content is an independent unit of content that one could imagine syndicating
independently, then the article
element would be appropriate to mark up the main
content of the document.
The document in the previous example is here recast as a blog post:
<!DOCTYPE HTML> <html> <head> <title> The Boy Blog: My Toys </title> </head> <body> <header> <h1>The Boy Blog</h1> </header> <nav> <p><a href="/">Home</a></p> <p><a href="/contact">Contact</a></p> </nav> <article> <header> <h1>My toys</h1> <p>Published August 4th</p> </header> <p>I really like my chained book and my telephone. I'm not such a fan of my big ball.</p> <p>Another toy I like is my mirror.</p> </article> <footer> <p>© copyright 2010 by the boy</p> </footer> </body> </html>
If the main content is not an independent unit of content so much as a section of a larger
work, for instance a chapter, then the section
element would be appropriate to mark
up the main content of the document.
Here is the same document, but as a chapter in an online book:
<!DOCTYPE HTML> <html> <head> <title> Chapter 2: My Toys — The Book of the Boy </title> </head> <body> <header> <hgroup> <h1>The Book of the Boy</h1> <h2>A book about boy stuff</h2> </hgroup> </header> <nav> <p><a href="/">Front Page</a></p> <p><a href="/toc">Table of Contents</a></p> <p><a href="/c1">Chapter 1</a> — <a href="/c3">Chapter 3</a></p> </nav> <section> <h1>Chapter 2: My Toys</h1> <p>I really like my chained book and my telephone. I'm not such a fan of my big ball.</p> <p>Another toy I like is my mirror.</p> </section> </body> </html>
If neither article
nor section
would be appropriate, but the main
content still needs an explicit element, for example for styling purposes, then the
main
element can be used.
This is the same as the original example, but using main
for the main content
instead of leaving it implied:
<!DOCTYPE HTML> <html> <head> <title> My Toys </title> <style> body > main { background: navy; color: yellow; } </style> </head> <body> <header> <h1>My toys</h1> </header> <nav> <p><a href="/">Home</a></p> <p><a href="/contact">Contact</a></p> </nav> <main> <p>I really like my chained book and my telephone. I'm not such a fan of my big ball.</p> <p>Another toy I like is my mirror.</p> </main> <footer> <p>© copyright 2010 by the boy</p> </footer> </body> </html>
4.13.2 Bread crumb navigation
This specification does not provide a machine-readable way of describing bread-crumb navigation
menus. Authors are encouraged to just use a series of links in a paragraph. The nav
element can be used to mark the section containing these paragraphs as being navigation
blocks.
In the following example, the current page can be reached via two paths.
<nav> <p> <a href="/">Main</a> ▸ <a href="/products/">Products</a> ▸ <a href="/products/dishwashers/">Dishwashers</a> ▸ <a>Second hand</a> </p> <p> <a href="/">Main</a> ▸ <a href="/second-hand/">Second hand</a> ▸ <a>Dishwashers</a> </p> </nav>
4.13.3 Tag clouds
This specification does not define any markup specifically for marking up lists
of keywords that apply to a group of pages (also known as tag clouds). In general, authors
are encouraged to either mark up such lists using ul
elements with explicit inline
counts that are then hidden and turned into a presentational effect using a style sheet, or to use
SVG.
Here, three tags are included in a short tag cloud:
<style> @media screen, print, handheld, tv { /* should be ignored by non-visual browsers */ .tag-cloud > li > span { display: none; } .tag-cloud > li { display: inline; } .tag-cloud-1 { font-size: 0.7em; } .tag-cloud-2 { font-size: 0.9em; } .tag-cloud-3 { font-size: 1.1em; } .tag-cloud-4 { font-size: 1.3em; } .tag-cloud-5 { font-size: 1.5em; } } </style> ... <ul class="tag-cloud"> <li class="tag-cloud-4"><a title="28 instances" href="/t/apple">apple</a> <span>(popular)</span> <li class="tag-cloud-2"><a title="6 instances" href="/t/kiwi">kiwi</a> <span>(rare)</span> <li class="tag-cloud-5"><a title="41 instances" href="/t/pear">pear</a> <span>(very popular)</span> </ul>
The actual frequency of each tag is given using the title
attribute. A CSS style sheet is provided to convert the markup into a cloud of differently-sized
words, but for user agents that do not support CSS or are not visual, the markup contains
annotations like "(popular)" or "(rare)" to categorise the various tags by frequency, thus
enabling all users to benefit from the information.
The ul
element is used (rather than ol
) because the order is not
particularly important: while the list is in fact ordered alphabetically, it would convey the
same information if ordered by, say, the length of the tag.
The tag
rel
-keyword is
not used on these a
elements because they do not represent tags that apply
to the page itself; they are just part of an index listing the tags themselves.
4.13.4 Conversations
This specification does not define a specific element for marking up conversations, meeting minutes, chat transcripts, dialogues in screenplays, instant message logs, and other situations where different players take turns in discourse.
Instead, authors are encouraged to mark up conversations using p
elements and
punctuation. Authors who need to mark the speaker for styling purposes are encouraged to use
span
or b
. Paragraphs with their text wrapped in the i
element can be used for marking up stage directions.
This example demonstrates this using an extract from Abbot and Costello's famous sketch, Who's on first:
<p> Costello: Look, you gotta first baseman? <p> Abbott: Certainly. <p> Costello: Who's playing first? <p> Abbott: That's right. <p> Costello becomes exasperated. <p> Costello: When you pay off the first baseman every month, who gets the money? <p> Abbott: Every dollar of it.
The following extract shows how an IM conversation log could be marked up, using the
data
element to provide Unix timestamps for each line. Note that the timestamps are
provided in a format that the time
element does not support, so the
data
element is used instead (namely, Unix time_t
timestamps).
Had the author wished to mark up the data using one of the date and time formats supported by the
time
element, that element could have been used instead of data
. This
could be advantageous as it would allow data analysis tools to detect the timestamps
unambiguously, without coordination with the page author.
<p> <data value="1319898155">14:22</data> <b>egof</b> I'm not that nerdy, I've only seen 30% of the star trek episodes <p> <data value="1319898192">14:23</data> <b>kaj</b> if you know what percentage of the star trek episodes you have seen, you are inarguably nerdy <p> <data value="1319898200">14:23</data> <b>egof</b> it's unarguably <p> <data value="1319898228">14:23</data> <i>* kaj blinks</i> <p> <data value="1319898260">14:24</data> <b>kaj</b> you are not helping your case
HTML does not have a good way to mark up graphs, so descriptions of interactive conversations
from games are more difficult to mark up. This example shows one possible convention using
dl
elements to list the possible responses at each point in the conversation.
Another option to consider is describing the conversation in the form of a DOT file, and
outputting the result as an SVG image to place in the document. [DOT]
<p> Next, you meet a fisherman. You can say one of several greetings: <dl> <dt> "Hello there!" <dd> <p> He responds with "Hello, how may I help you?"; you can respond with: <dl> <dt> "I would like to buy a fish." <dd> <p> He sells you a fish and the conversation finishes. <dt> "Can I borrow your boat?" <dd> <p> He is surprised and asks "What are you offering in return?". <dl> <dt> "Five gold." (if you have enough) <dt> "Ten gold." (if you have enough) <dt> "Fifteen gold." (if you have enough) <dd> <p> He lends you his boat. The conversation ends. <dt> "A fish." (if you have one) <dt> "A newspaper." (if you have one) <dt> "A pebble." (if you have one) <dd> <p> "No thanks", he replies. Your conversation options at this point are the same as they were after asking to borrow his boat, minus any options you've suggested before. </dl> </dd> </dl> </dd> <dt> "Vote for me in the next election!" <dd> <p> He turns away. The conversation finishes. <dt> "Sir, are you aware that your fish are running away?" <dd> <p> He looks at you skeptically and says "Fish cannot run, sir". <dl> <dt> "You got me!" <dd> <p> The fisherman sighs and the conversation ends. <dt> "Only kidding." <dd> <p> "Good one!" he retorts. Your conversation options at this point are the same as those following "Hello there!" above. <dt> "Oh, then what are they doing?" <dd> <p> He looks at his fish, giving you an opportunity to steal his boat, which you do. The conversation ends. </dl> </dd> </dl>
In some games, conversations are simpler: each character merely has a fixed set of lines that they say. In this example, a game FAQ/walkthrough lists some of the known possible responses for each character:
<section> <h1>Dialogue</h1> <p><small>Some characters repeat their lines in order each time you interact with them, others randomly pick from amongst their lines. Those who respond in order have numbered entries in the lists below.</small> <h2>The Shopkeeper</h2> <ul> <li>How may I help you? <li>Fresh apples! <li>A loaf of bread for madam? </ul> <h2>The pilot</h2> <p>Before the accident: <ul> </li>I'm about to fly out, sorry! </li>Sorry, I'm just waiting for flight clearance and then I'll be off! </ul> <p>After the accident: <ol> <li>I'm about to fly out, sorry! <li>Ok, I'm not leaving right now, my plane is being cleaned. <li>Ok, it's not being cleaned, it needs a minor repair first. <li>Ok, ok, stop bothering me! Truth is, I had a crash. </ol> <h2>Clan Leader</h2> <p>During the first clan meeting: <ul> <li>Hey, have you seen my daughter? I bet she's up to something nefarious again... <li>Nice weather we're having today, eh? <li>The name is Bailey, Jeff Bailey. How can I help you today? <li>A glass of water? Fresh from the well! </ul> <p>After the earthquake: <ol> <li>Everyone is safe in the shelter, we just have to put out the fire! <li>I'll go and tell the fire brigade, you keep hosing it down! </ol> </section>
4.13.5 Footnotes
HTML does not have a dedicated mechanism for marking up footnotes. Here are the suggested alternatives.
For short inline annotations, the title
attribute could be used.
In this example, two parts of a dialogue are annotated with footnote-like content using the
title
attribute.
<p> <b>Customer</b>: Hello! I wish to register a complaint. Hello. Miss? <p> <b>Shopkeeper</b>: <span title="Colloquial pronunciation of 'What do you'" >Watcha</span> mean, miss? <p> <b>Customer</b>: Uh, I'm sorry, I have a cold. I wish to make a complaint. <p> <b>Shopkeeper</b>: Sorry, <span title="This is, of course, a lie.">we're closing for lunch</span>.
Unfortunately, relying on the title
attribute is
currently discouraged as many user agents do not expose the attribute in an accessible manner as
required by this specification (e.g. requiring a pointing device such as a mouse to cause a
tooltip to appear, which excludes keyboard-only users and touch-only users, such as anyone with a
modern phone or tablet).
If the title
attribute is used, CSS can used to
draw the reader's attention to the elements with the attribute.
For example, the following CSS places a dashed line below elements that have a title
attribute.
[title] { border-bottom: thin dashed; }
For longer annotations, the a
element should be used, pointing to an element later
in the document. The convention is that the contents of the link be a number in square
brackets.
In this example, a footnote in the dialogue links to a paragraph below the dialogue. The paragraph then reciprocally links back to the dialogue, allowing the user to return to the location of the footnote.
<p> Announcer: Number 16: The <i>hand</i>. <p> Interviewer: Good evening. I have with me in the studio tonight Mr Norman St John Polevaulter, who for the past few years has been contradicting people. Mr Polevaulter, why <em>do</em> you contradict people? <p> Norman: I don't. <sup><a href="#fn1" id="r1">[1]</a></sup> <p> Interviewer: You told me you did! ... <section> <p id="fn1"><a href="#r1">[1]</a> This is, naturally, a lie, but paradoxically if it were true he could not say so without contradicting the interviewer and thus making it false.</p> </section>
For side notes, longer annotations that apply to entire sections of the text rather than just
specific words or sentences, the aside
element should be used.
In this example, a sidebar is given after a dialogue, giving it some context.
<p> <span class="speaker">Customer</span>: I will not buy this record, it is scratched. <p> <span class="speaker">Shopkeeper</span>: I'm sorry? <p> <span class="speaker">Customer</span>: I will not buy this record, it is scratched. <p> <span class="speaker">Shopkeeper</span>: No no no, this's'a tobacconist's. <aside> <p>In 1970, the British Empire lay in ruins, and foreign nationalists frequented the streets — many of them Hungarians (not the streets — the foreign nationals). Sadly, Alexander Yalt has been publishing incompetently-written phrase books. </aside>
For figures or tables, footnotes can be included in the relevant figcaption
or
caption
element, or in surrounding prose.
In this example, a table has cells with footnotes that are given in prose. A
figure
element is used to give a single legend to the combination of the table and
its footnotes.
<figure> <figcaption>Table 1. Alternative activities for knights.</figcaption> <table> <tr> <th> Activity <th> Location <th> Cost <tr> <td> Dance <td> Wherever possible <td> £0<sup><a href="#fn1">1</a></sup> <tr> <td> Routines, chorus scenes<sup><a href="#fn2">2</a></sup> <td> Undisclosed <td> Undisclosed <tr> <td> Dining<sup><a href="#fn3">3</a></sup> <td> Camelot <td> Cost of ham, jam, and spam<sup><a href="#fn4">4</a></sup> </table> <p id="fn1">1. Assumed.</p> <p id="fn2">2. Footwork impeccable.</p> <p id="fn3">3. Quality described as "well".</p> <p id="fn4">4. A lot.</p> </figure>
4.14 Disabled elements
An element is said to be actually disabled if it falls into one of the following categories:
-
button
elements that are disabled -
input
elements that are disabled -
select
elements that are disabled -
textarea
elements that are disabled -
optgroup
elements that have adisabled
attribute -
option
elements that are disabled -
menuitem
elements that have adisabled
attribute -
fieldset
elements that have adisabled
attribute
This definition is used to determine what elements can be focused and which elements match the :disabled
pseudo-class.