面向网页开发人员版本 — 最后更新于 2024 年 9 月 12 日
canvas
元素Path2D
对象ImageBitmap
渲染上下文OffscreenCanvas
接口canvas
元素所有当前引擎都支持。
a
元素、具有 usemap
属性的 img
元素、button
元素、input
元素(其 type
属性处于 复选框 或 单选按钮 状态)、input
元素(它们是 按钮)以及具有 multiple
属性或大于 1 的 显示大小 的 select
元素。width
— 水平尺寸height
— 垂直尺寸HTMLCanvasElement
。
元素为脚本提供了一个分辨率相关的位图画布,可用于动态渲染图形、游戏图形、艺术作品或其他视觉图像。canvas
当有更合适的元素可用时,作者不应在文档中使用
元素。例如,使用 canvas
元素渲染页面标题是不合适的:如果标题所需的呈现方式在图形上非常复杂,则应使用适当的元素(通常为 canvas
)进行标记,然后使用 CSS 和支持技术(如 影子树)进行样式设置。h1
当作者使用
元素时,还必须提供内容,以便在呈现给用户时,传达与 canvas
的位图本质上相同的功能或目的。此内容可以放置为 canvas
元素的内容。canvas
元素(如果有)的内容是元素的 回退内容。canvas
在交互式视觉媒体中,如果为
元素启用了 脚本,并且启用了对 canvas
元素的支持,则 canvas
元素 表示 由动态创建的图像(即元素的位图)组成的 嵌入内容。canvas
在非交互式静态视觉媒体中,如果
元素之前已与渲染上下文相关联(例如,如果页面在交互式视觉媒体中查看,现在正在打印,或者在页面布局过程中运行的一些脚本在元素上进行了绘制),则 canvas
元素 表示 具有元素当前位图和大小的 嵌入内容。否则,元素将改为表示其 回退内容。canvas
在非视觉媒体中,以及在视觉媒体中,如果为
元素禁用了 脚本 或禁用了对 canvas
元素的支持,则 canvas
元素 表示 其 回退内容。canvas
当
元素 表示 嵌入内容 时,用户仍然可以聚焦 canvas
元素的后代(在 回退内容 中)。当元素 获得焦点 时,它成为键盘交互事件的目标(即使元素本身不可见)。这允许作者使交互式画布可通过键盘访问:作者应该在 回退内容 中将交互区域与 可聚焦区域 建立一一映射。(焦点对鼠标交互事件没有影响)。[UIEVENTS]canvas
其最近的
元素祖先是 正在渲染 并 表示 嵌入内容 的元素是 用作相关画布回退内容的元素。canvas
元素有两个属性用于控制元素位图的大小:canvas
width
和 height
。当指定这些属性时,其值必须是 有效的非负整数。
属性默认为 300,width
属性默认为 150。height
设置
或 width
属性的值时,如果 height
元素的 上下文模式 设置为 占位符,则用户代理必须抛出 "canvas
InvalidStateError
" DOMException
并保持属性值不变。
当
元素 表示 嵌入内容 时,其 自然尺寸 等于元素位图的尺寸。canvas
用户代理必须对
及其渲染上下文的位图使用由每个坐标空间单位一个像素的图像数据组成的正方形像素密度。canvas
元素可以通过样式表任意调整大小,然后其位图将受 'object-fit' CSS 属性的影响。canvas
context = canvas.getContext(contextId [, options ])
返回一个对象,该对象公开了用于在画布上绘制的 API。 contextId 指定所需的 API:“2d
”、“bitmaprenderer
”、“webgl
”、“webgl2
”或“webgpu
”。 options 由该 API 处理。
本规范定义了以下“2d
”和“bitmaprenderer
”上下文。WebGL 规范定义了“webgl
”和“webgl2
”上下文。WebGPU 定义了“webgpu
”上下文。 [WEBGL] [WEBGPU]
如果 contextId 不受支持,或者画布已使用其他上下文类型初始化(例如,在获取“webgl
”上下文后尝试获取“2d
”上下文),则返回 null。
url = canvas.toDataURL([ type [, quality ] ])
返回画布中图像的 data:
URL。
如果提供,第一个参数控制要返回的图像类型(例如 PNG 或 JPEG)。默认值为“image/png
”;如果给定的类型不受支持,则也使用该类型。如果类型为支持可变质量的图像格式(例如“image/jpeg
”),则第二个参数适用,它是一个介于 0.0 到 1.0(含)之间的数字,表示所需的结果图像的质量级别。
当尝试使用除“image/png
”以外的类型时,作者可以通过检查返回的字符串是否以“data:image/png,
”或“data:image/png;
”这两个精确字符串中的一个开头来检查图像是否确实以请求的格式返回。如果是,则图像为 PNG,因此不支持请求的类型。(唯一的例外是,如果画布的高度或宽度均为零,则结果可能只是“data:,
”。)
canvas.toBlob(callback [, type [, quality ] ])
创建一个表示包含画布中图像的文件的 Blob
对象,并使用该对象的句柄调用回调函数。
如果提供,第二个参数控制要返回的图像类型(例如 PNG 或 JPEG)。默认值为“image/png
”;如果给定的类型不受支持,则也使用该类型。如果类型为支持可变质量的图像格式(例如“image/jpeg
”),则第三个参数适用,它是一个介于 0.0 到 1.0(含)之间的数字,表示所需的结果图像的质量级别。
canvas.transferControlToOffscreen()
返回一个新创建的 OffscreenCanvas
对象,该对象使用 canvas
元素作为占位符。一旦 canvas
元素成为 OffscreenCanvas
对象的占位符,其自然大小将无法再更改,并且不能具有渲染上下文。占位符画布的内容在 OffscreenCanvas
的 相关代理 的 事件循环 的 更新渲染 步骤中更新。
所有当前引擎都支持。
context = canvas.getContext('2d' [, { [ alpha: true ] [, desynchronized: false ] [, colorSpace: 'srgb'] [, willReadFrequently: false ]} ])
返回一个 CanvasRenderingContext2D
对象,该对象永久绑定到特定的 canvas
元素。
如果 alpha
成员为 false,则上下文将强制始终不透明。
如果 desynchronized
成员为 true,则上下文可能 异步。
colorSpace
成员指定渲染上下文的 颜色空间。
如果 willReadFrequently
成员为 true,则上下文将被标记为 回读优化。
context.canvas
返回 canvas
元素。
attributes = context.getContextAttributes()
返回一个对象,其
alpha
成员如果上下文具有 alpha 通道则为 true,如果上下文强制为不透明则为 false。desynchronized
成员如果上下文可以 异步 则为 true。colorSpace
成员是表示上下文 颜色空间 的字符串。willReadFrequently
成员如果上下文被标记为 回读优化 则为 true。PredefinedColorSpace
枚举用于指定画布后备存储的 颜色空间。
“srgb
”值表示 'srgb' 颜色空间。
“display-p3
”值表示 'display-p3' 颜色空间。
颜色空间之间转换的算法可以在 CSS 颜色 的 预定义颜色空间 部分找到。 [CSSCOLOR]
CanvasFillRule
枚举用于选择用于确定点在路径内还是路径外的 填充规则 算法。
“nonzero
”值表示非零绕线规则,其中如果从该点绘制的半无限直线穿过形状路径的方向次数等于其穿过路径的反方向次数,则该点被视为在形状外部。
“evenodd
”值表示奇偶规则,其中如果从该点绘制的半无限直线穿过形状路径的次数为偶数,则该点被视为在形状外部。
如果一个点不在形状外部,则它在形状内部。
ImageSmoothingQuality
枚举用于表达对平滑图像时使用的插值质量的偏好。
“low
”值表示对低级别的图像插值质量的偏好。低质量图像插值可能比更高的设置更节省计算资源。
“medium
”值表示对中等级别的图像插值质量的偏好。
“high
”值表示对高级别的图像插值质量的偏好。高质量图像插值可能比较低的设置更消耗计算资源。
双线性缩放是相对快速、低质量图像平滑算法的一个示例。双三次或 Lanczos 缩放是生成更高质量输出的图像平滑算法的示例。本规范不要求必须使用特定的插值算法。
当 输出位图 未由用户代理直接显示时,实现可以仅记住已应用于它的绘图操作序列,而不是更新此位图,直到需要位图的实际数据(例如,由于调用了 drawImage()
或 createImageBitmap()
工厂方法)。在许多情况下,这将更节省内存。
canvas
元素的位图是在实践中几乎总是需要的唯一位图。渲染上下文的 输出位图(如果存在)始终只是 canvas
元素位图的别名。
有时需要其他位图,例如,当画布以不同于其 自然大小 的大小绘制时启用快速绘制,或者启用双缓冲以使图形更新(例如页面滚动)可以在执行画布绘制命令的同时并行处理。
实现 CanvasState
接口的对象维护一个绘图状态堆栈。绘图状态 包括
当前的 变换矩阵。
当前的 剪辑区域。
当前的 字母间距、单词间距、填充样式、描边样式、滤镜、全局 alpha、合成和混合运算符以及 阴影颜色。
以下属性的当前值:lineWidth
、lineCap
、lineJoin
、miterLimit
、lineDashOffset
、shadowOffsetX
、shadowOffsetY
、shadowBlur
、font
、textAlign
、textBaseline
、direction
、fontKerning
、fontStretch
、fontVariantCaps
、textRendering
、imageSmoothingEnabled
、imageSmoothingQuality
。
当前的 虚线列表。
渲染上下文的位图不是绘图状态的一部分,因为它们取决于渲染上下文是否以及如何绑定到 canvas
元素。
实现 CanvasState
混合的对象具有一个 上下文丢失 布尔值,在创建对象时将其初始化为 false。上下文丢失 值在 上下文丢失步骤 中更新。
context.save()
将当前状态推入堆栈。
context.restore()
弹出堆栈顶部的状态,将上下文恢复到该状态。
context.reset()
CanvasRenderingContext2D/reset
OffscreenCanvasRenderingContext2D#canvasrenderingcontext2d.reset
重置渲染上下文,包括后备缓冲区、绘图状态栈、路径和样式。
context.isContextLost()
CanvasRenderingContext2D/isContextLost
仅在一个引擎中支持。
如果渲染上下文已丢失,则返回 true。上下文丢失可能由于驱动程序崩溃、内存不足等原因导致。在这些情况下,画布会丢失其后备存储,并采取措施将其渲染上下文重置为默认状态。
context.lineWidth [ = value ]
styles.lineWidth [ = value ]
返回当前线宽。
可以设置,以更改线宽。非零有限值以外的值将被忽略。
context.lineCap [ = value ]
styles.lineCap [ = value ]
返回当前线帽样式。
可以设置,以更改线帽样式。
可能的线帽样式为“butt
”、“round
”和“square
”。其他值将被忽略。
context.lineJoin [ = value ]
styles.lineJoin [ = value ]
返回当前线连接样式。
可以设置,以更改线连接样式。
可能的线连接样式为“bevel
”、“round
”和“miter
”。其他值将被忽略。
context.miterLimit [ = value ]
styles.miterLimit [ = value ]
返回当前斜接限制比率。
可以设置,以更改斜接限制比率。非零有限值以外的值将被忽略。
context.setLineDash(segments)
styles.setLineDash(segments)
设置当前线虚线图案(在描边时使用)。参数是一个距离列表,用于交替显示线段的开和关。
segments = context.getLineDash()
segments = styles.getLineDash()
返回当前线虚线图案的副本。返回的数组将始终具有偶数个条目(即图案已规范化)。
context.lineDashOffset
styles.lineDashOffset
返回相位偏移量(以与线虚线图案相同的单位)。
可以设置,以更改相位偏移量。非有限值将被忽略。
context.font [ = value ]
styles.font [ = value ]
返回当前字体设置。
可以设置,以更改字体。语法与 CSS 'font' 属性相同;无法解析为 CSS 字体值的值将被忽略。
相对关键字和长度相对于canvas
元素的字体进行计算。
context.textAlign [ = value ]
styles.textAlign [ = value ]
返回当前文本对齐设置。
可以设置,以更改对齐方式。可能的值及其含义如下所示。其他值将被忽略。默认值为“start
”。
context.textBaseline [ = value ]
styles.textBaseline [ = value ]
返回当前基线对齐设置。
可以设置,以更改基线对齐方式。可能的值及其含义如下所示。其他值将被忽略。默认值为“alphabetic
”。
context.direction [ = value ]
styles.direction [ = value ]
返回当前方向性。
可以设置,以更改方向性。可能的值及其含义如下所示。其他值将被忽略。默认值为“inherit
”。
context.letterSpacing [ = value ]
CanvasRenderingContext2D/letterSpacing
仅在一个引擎中支持。
styles.letterSpacing [ = value ]
返回文本中字符之间的当前间距。
可以设置,以更改字符之间的间距。无法解析为 CSS <length> 的值将被忽略。默认值为“0px
”。
context.fontKerning [ = value ]
CanvasRenderingContext2D/fontKerning
styles.fontKerning [ = value ]
返回当前字体间距设置。
可以设置,以更改字体间距。可能的值及其含义如下所示。其他值将被忽略。默认值为“auto
”。
context.fontStretch [ = value ]
CanvasRenderingContext2D/fontStretch
仅在一个引擎中支持。
styles.fontStretch [ = value ]
返回当前字体伸缩设置。
可以设置,以更改字体伸缩。可能的值及其含义如下所示。其他值将被忽略。默认值为“normal
”。
context.fontVariantCaps [ = value ]
CanvasRenderingContext2D/fontVariantCaps
仅在一个引擎中支持。
styles.fontVariantCaps [ = value ]
返回当前字体变体大写设置。
可以设置,以更改字体变体大写。可能的值及其含义如下所示。其他值将被忽略。默认值为“normal
”。
context.textRendering [ = value ]
CanvasRenderingContext2D/textRendering
仅在一个引擎中支持。
styles.textRendering [ = value ]
返回当前文本渲染设置。
可以设置,以更改文本渲染。可能的值及其含义如下所示。其他值将被忽略。默认值为“auto
”。
context.wordSpacing [ = value ]
CanvasRenderingContext2D/wordSpacing
仅在一个引擎中支持。
styles.wordSpacing [ = value ]
返回文本中单词之间的当前间距。
可以设置,以更改单词之间的间距。无法解析为 CSS <length> 的值将被忽略。默认值为“0px
”。
textAlign
属性允许的关键字如下
start
与文本的起始边缘对齐(在从左到右的文本中为左侧,在从右到左的文本中为右侧)。
end
与文本的结束边缘对齐(在从左到右的文本中为右侧,在从右到左的文本中为左侧)。
left
左对齐。
right
右对齐。
center
居中对齐。
textBaseline
属性允许的关键字对应于字体中的对齐点
关键字映射到这些对齐点的方式如下
top
hanging
middle
alphabetic
ideographic
bottom
direction
属性允许的关键字如下
fontKerning
属性允许的关键字如下
auto
用户代理自行决定是否应用字距调整。
normal
应用字距调整。
none
不应用字距调整。
fontStretch
属性允许的关键字如下
ultra-condensed
与 CSS 'font-stretch' 'ultra-condensed' 设置相同。
extra-condensed
与 CSS 'font-stretch' 'extra-condensed' 设置相同。
condensed
与 CSS 'font-stretch' 'condensed' 设置相同。
semi-condensed
与 CSS 'font-stretch' 'semi-condensed' 设置相同。
normal
默认设置,其中字形的宽度为 100%。
semi-expanded
与 CSS 'font-stretch' 'semi-expanded' 设置相同。
expanded
与 CSS 'font-stretch' 'expanded' 设置相同。
extra-expanded
与 CSS 'font-stretch' 'extra-expanded' 设置相同。
ultra-expanded
与 CSS 'font-stretch' 'ultra-expanded' 设置相同。
fontVariantCaps
属性允许的关键字如下
normal
下面列出的功能均未启用。
small-caps
与 CSS 'font-variant-caps' 'small-caps' 设置相同。
all-small-caps
与 CSS 'font-variant-caps' 'all-small-caps' 设置相同。
petite-caps
与 CSS 'font-variant-caps' 'petite-caps' 设置相同。
all-petite-caps
与 CSS 'font-variant-caps' 'all-petite-caps' 设置相同。
unicase
与 CSS 'font-variant-caps' 'unicase' 设置相同。
titling-caps
与 CSS 'font-variant-caps' 'titling-caps' 设置相同。
The textRendering
属性允许的关键字如下
auto
与 SVG text-rendering 属性中的“auto”相同。
optimizeSpeed
与 SVG text-rendering 属性中的“optimizeSpeed”相同。
optimizeLegibility
与 SVG text-rendering 属性中的“optimizeLegibility”相同。
geometricPrecision
与 SVG text-rendering 属性中的“geometricPrecision”相同。
The 文本准备算法 如下所示。它以字符串 text、CanvasTextDrawingStyles
对象 target 和可选长度 maxWidth 作为输入。它返回一个字形形状数组,每个形状都位于一个公共坐标空间上,一个 物理对齐,其值为 left、right 和 center 之一,以及一个 内联框。(此算法的大多数调用者都会忽略 物理对齐 和 内联框。)
如果提供了 maxWidth 但其值小于或等于零或等于 NaN,则返回一个空数组。
将 text 中的所有 ASCII 空格 替换为 U+0020 空格字符。
令 font 为 target 的当前字体,由该对象的 font
属性给出。
应用以下列表中的相应步骤来确定 direction 的值
形成一个包含单个包含文本 text 的 内联框 的假设无限宽 CSS 行框,其 CSS 属性设置如下
属性 | 来源 |
---|---|
'direction' | direction |
'font' | font |
'font-kerning' | target 的 fontKerning |
'font-stretch' | target 的 fontStretch |
'font-variant-caps' | target 的 fontVariantCaps |
'letter-spacing' | target 的 字母间距 |
SVG text-rendering | target 的 textRendering |
'white-space' | 'pre' |
'word-spacing' | target 的 单词间距 |
以及所有其他属性都设置为其初始值。
如果提供了 maxWidth 并且假设 内联框 在假设 行框 中的宽度大于 maxWidth CSS 像素,则更改 font 以具有更紧凑的字体(如果可用或如果可以通过将水平缩放因子应用于字体来合成一个合理可读的字体)或更小的字体,并返回到上一步。
The 锚点 是 内联框 上的一个点,而 物理对齐 是 left、right 和 center 值之一。这些变量由 textAlign
和 textBaseline
值决定,如下所示
水平位置
textAlign
为 left
textAlign
为 start
且 direction 为 'ltr'textAlign
为 end
且 direction 为 'rtl'textAlign
为 right
textAlign
为 end
且 direction 为 'ltr'textAlign
为 start
且 direction 为 'rtl'textAlign
为 center
垂直位置
textBaseline
为 top
textBaseline
为 hanging
textBaseline
为 middle
textBaseline
为 alphabetic
textBaseline
为 ideographic
textBaseline
为 bottom
令result 为一个数组,该数组通过从左到右迭代内联框中的每个字形(如果有)来构造,对于每个字形,将字形的形状(在内联框中)添加到数组中,并在使用CSS 像素且原点位于锚点的坐标空间中进行定位。
返回result、物理对齐方式和内联框。
实现CanvasPath
接口的对象具有一个路径。一个路径包含零个或多个子路径的列表。每个子路径都由一个或多个点的列表组成,这些点通过直线或曲线线段连接,并带有一个标志,指示子路径是否闭合。闭合子路径是指子路径的最后一个点通过直线与子路径的第一个点连接的子路径。在绘制路径时,仅包含一个点的子路径将被忽略。
路径具有一个需要新子路径标志。当设置此标志时,某些 API 会创建新的子路径而不是扩展上一个子路径。当创建路径时,必须设置其需要新子路径标志。
当创建实现CanvasPath
接口的对象时,其路径必须初始化为零个子路径。
context.moveTo(x, y)
path.moveTo(x, y)
使用给定点创建一个新的子路径。
context.closePath()
path.closePath()
将当前子路径标记为闭合,并使用与新闭合子路径的起始点和结束点相同的点开始一个新的子路径。
context.lineTo(x, y)
path.lineTo(x, y)
将给定点添加到当前子路径,并通过直线将其连接到前一个点。
context.quadraticCurveTo(cpx, cpy, x, y)
path.quadraticCurveTo(cpx, cpy, x, y)
将给定点添加到当前子路径,并通过具有给定控制点的二次贝塞尔曲线将其连接到前一个点。
context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
path.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
将给定点添加到当前子路径,并通过具有给定控制点的三次贝塞尔曲线将其连接到前一个点。
context.arcTo(x1, y1, x2, y2, radius)
path.arcTo(x1, y1, x2, y2, radius)
将具有给定控制点和半径的弧添加到当前子路径,并通过直线将其连接到前一个点。
如果给定的半径为负数,则抛出"IndexSizeError
"DOMException
。
context.arc(x, y, radius, startAngle, endAngle [, counterclockwise ])
path.arc(x, y, radius, startAngle, endAngle [, counterclockwise ])
向子路径添加点,以便将由参数描述的圆的圆周描述的弧添加到路径中,从给定的起始角度开始,到给定的结束角度结束,以给定的方向(默认为顺时针方向)进行,并通过直线将其连接到前一个点。
如果给定的半径为负数,则抛出"IndexSizeError
"DOMException
。
context.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle [, counterclockwise])
path.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle [, counterclockwise])
向子路径添加点,以便将由参数描述的椭圆的圆周描述的弧添加到路径中,从给定的起始角度开始,到给定的结束角度结束,以给定的方向(默认为顺时针方向)进行,并通过直线将其连接到前一个点。
如果给定的半径为负数,则抛出"IndexSizeError
"DOMException
。
context.rect(x, y, w, h)
path.rect(x, y, w, h)
向路径添加一个新的闭合子路径,表示给定的矩形。
context.roundRect(x, y, w, h, radii)
CanvasRenderingContext2D/roundRect
所有当前引擎都支持。
path.roundRect(x, y, w, h, radii)
向路径添加一个新的闭合子路径,表示给定的圆角矩形。radii 是一个半径列表或一个表示矩形角的单个半径(以像素为单位)。如果提供了一个列表,则这些半径的数量和顺序与 CSS 'border-radius' 属性相同。单个半径的行为与具有单个元素的列表相同。
如果w 和h 都大于或等于 0,或者都小于 0,则路径将顺时针绘制。否则,将逆时针绘制。
当w 为负数时,圆角矩形将水平翻转,这意味着通常应用于左角的半径值将用于右侧,反之亦然。类似地,当h 为负数时,圆角矩形将垂直翻转。
当radii 中的值r 为数字时,相应的角将绘制为半径为r 的圆弧。
当radii 中的值r 为具有{ x, y }
属性的对象时,相应的角将绘制为椭圆弧,其x 和y 半径分别等于r.x 和r.y。
当同一边的两个角的radii 之和大于边的长度时,圆角矩形的所有radii 将按长度 / (r1 + r2) 的比例缩放。如果多个边具有此属性,则使用比例因子最小的边的比例因子。这与 CSS 行为一致。
如果radii 是大小不是 1、2、3 或 4 的列表,则抛出RangeError
。
如果radii 中的值为负数,或者为{ x, y }
对象且其x
或y
属性为负数,则抛出RangeError
。
Path2D
对象所有当前引擎都支持。
Path2D
对象可用于声明路径,然后在实现CanvasDrawPath
接口的对象上使用这些路径。除了前面各节中描述的许多 API 之外,Path2D
对象还具有组合路径和向路径添加文本的方法。
path = new Path2D()
创建一个新的空Path2D
对象。
path = new Path2D(path)
当path 为Path2D
对象时,返回一个副本。
当path 为字符串时,创建由参数描述的路径,将其解释为 SVG 路径数据。[SVG]
path.addPath(path [, transform ])
将参数给出的路径添加到路径中。
实现CanvasTransform
接口的对象具有一个当前变换矩阵,以及用于操作它的方法(在本节中描述)。当创建实现CanvasTransform
接口的对象时,其变换矩阵必须初始化为单位矩阵。
在创建当前默认路径时,以及在实现CanvasTransform
接口的对象上绘制文本、形状和Path2D
对象时,会将当前变换矩阵应用于坐标。
context.scale(x, y)
将当前变换矩阵更改为应用具有给定特征的缩放变换。
context.rotate(angle)
将当前变换矩阵更改为应用具有给定特征的旋转变换。角度以弧度为单位。
context.translate(x, y)
将当前变换矩阵更改为应用具有给定特征的平移变换。
context.transform(a, b, c, d, e, f)
将当前变换矩阵更改为应用由参数给出的矩阵,如下所述。
matrix = context.getTransform()
返回当前变换矩阵的副本,作为一个新创建的DOMMatrix
对象。
context.setTransform(a, b, c, d, e, f)
将当前变换矩阵更改为由参数给定的矩阵,如下所述。
context.setTransform(transform)
将当前变换矩阵更改为传递的DOMMatrix2DInit
字典所表示的矩阵。
context.resetTransform()
将当前变换矩阵更改为单位矩阵。
参数a、b、c、d、e和f有时被称为m11、m12、m21、m22、dx和dy,或者m11、m21、m12、m22、dx和dy。尤其需要注意第二个和第三个参数(b和c)的顺序,因为它们的顺序在不同的API之间有所不同,并且API有时使用m12/m21表示法,有时使用m21/m12表示法来表示这些位置。
给定一个由transform()
和setTransform()
方法创建的矩阵形式,即:
a | c | e |
b | d | f |
0 | 0 | 1 |
变换矩阵乘法后的最终变换坐标将为
xnew = a x + c y + e
ynew = b x + d y + f
CanvasDrawImage
和CanvasFillStrokeStyles
接口上的一些方法将联合类型CanvasImageSource
作为参数。
此联合类型允许将实现以下任何接口的对象用作图像源
HTMLOrSVGImageElement
(img
或SVG image
元素)HTMLVideoElement
(video
元素)HTMLCanvasElement
(canvas
元素)OffscreenCanvas
ImageBitmap
VideoFrame
尽管没有正式指定为这样,但SVG image
元素预计将与img
元素几乎相同地实现。也就是说,SVG image
元素共享img
元素的基本概念和功能。
ImageBitmap
接口可以从许多其他表示图像的类型创建,包括ImageData
。
要检查image参数的可使用性,其中image是CanvasImageSource
对象,请运行以下步骤
切换image
HTMLOrSVGImageElement
如果image的当前请求的状态为broken,则抛出"InvalidStateError
" DOMException
。
如果image未完全可解码,则返回bad。
HTMLVideoElement
如果image的readyState
属性为HAVE_NOTHING
或HAVE_METADATA
,则返回bad。
HTMLCanvasElement
OffscreenCanvas
如果image的水平尺寸或垂直尺寸等于零,则抛出"InvalidStateError
" DOMException
。
ImageBitmap
VideoFrame
如果image的[[Detached]]内部槽值设置为true,则抛出"InvalidStateError
" DOMException
。
返回good。
当CanvasImageSource
对象表示HTMLOrSVGImageElement
时,必须使用元素的图像作为源图像。
具体来说,当CanvasImageSource
对象表示HTMLOrSVGImageElement
中的动画图像时,用户代理必须使用动画的默认图像(格式定义在不支持或禁用动画时要使用的图像),或者,如果没有这样的图像,则在为CanvasRenderingContext2D
API渲染图像时使用动画的第一帧。
当CanvasImageSource
对象表示HTMLVideoElement
时,调用带参数的方法时,当前播放位置处的帧必须用作渲染CanvasRenderingContext2D
API的图像的源图像,并且源图像的尺寸必须是媒体资源的自然宽度和自然高度(即,在应用任何纵横比校正后)。
当CanvasImageSource
对象表示HTMLCanvasElement
时,必须使用元素的位图作为源图像。
当CanvasImageSource
对象表示正在渲染的元素并且该元素已调整大小时,必须使用源图像的原始图像数据,而不是渲染后的图像(例如,源元素上的width
和height
属性对渲染CanvasRenderingContext2D
API时对象如何解释没有影响)。
当CanvasImageSource
对象表示ImageBitmap
时,必须使用对象的位图图像数据作为源图像。
当CanvasImageSource
对象表示OffscreenCanvas
时,必须使用对象的位图作为源图像。
当CanvasImageSource
对象表示VideoFrame
时,必须使用对象的像素数据作为源图像,并且源图像的尺寸必须是对象的[[display width]]和[[display height]]。
如果对象image不是源干净的,则根据image的类型进行切换
HTMLOrSVGImageElement
image的当前请求的图像数据为CORS跨源。
HTMLVideoElement
image的媒体数据为CORS跨源。
HTMLCanvasElement
ImageBitmap
OffscreenCanvas
image的位图的源干净标志为false。
context.fillStyle [ = value ]
返回用于填充形状的当前样式。
可以设置,以更改填充样式。
样式可以是包含CSS颜色的字符串,也可以是CanvasGradient
或CanvasPattern
对象。无效值将被忽略。
context.strokeStyle [ = value ]
返回用于描边形状的当前样式。
可以设置,以更改描边样式。
样式可以是包含CSS颜色的字符串,也可以是CanvasGradient
或CanvasPattern
对象。无效值将被忽略。
渐变有三种类型:线性渐变、径向渐变和圆锥渐变,它们由实现不透明CanvasGradient
接口的对象表示。
创建渐变后(见下文),将沿其放置渐变停止点以定义颜色如何在渐变中分布。
gradient.addColorStop(offset, color)
在给定偏移量处向渐变添加具有给定颜色的颜色停止点。0.0 是渐变一端的偏移量,1.0 是另一端的偏移量。
如果偏移量超出范围,则抛出"IndexSizeError
" DOMException
。如果无法解析颜色,则抛出"SyntaxError
" DOMException
。
gradient = context.createLinearGradient(x0, y0, x1, y1)
返回一个CanvasGradient
对象,该对象表示一个线性渐变,该渐变沿参数表示的坐标给出的线条绘制。
gradient = context.createRadialGradient(x0, y0, r0, x1, y1, r1)
返回一个CanvasGradient
对象,该对象表示一个径向渐变,该渐变沿参数表示的圆形给出的圆锥绘制。
如果任一半径为负,则抛出"IndexSizeError
" DOMException
异常。
gradient = context.createConicGradient(startAngle, x, y)
返回一个CanvasGradient
对象,该对象表示一个圆锥渐变,该渐变沿参数表示的中心周围顺时针旋转绘制。
模式由实现不透明CanvasPattern
接口的对象表示。
pattern = context.createPattern(image, repetition)
返回一个CanvasPattern
对象,该对象使用给定的图像并在repetition参数给定的方向上重复。
repetition的允许值为repeat
(两个方向)、repeat-x
(仅水平)、repeat-y
(仅垂直)和no-repeat
(均不)。如果repetition参数为空,则使用值repeat
。
如果图像尚未完全解码,则不绘制任何内容。如果图像是一个没有数据的画布,则抛出"InvalidStateError
" DOMException
。
pattern.setTransform(transform)
设置在填充或描边绘制操作期间渲染模式时将使用的变换矩阵。
实现 CanvasRect
接口的对象提供以下方法,用于立即将矩形绘制到位图上。每个方法都接受四个参数;前两个参数给出矩形左上角的 x 和 y 坐标,后两个参数分别给出矩形的宽度 w 和高度 h。
context.clearRect(x, y, w, h)
将给定矩形内位图上的所有像素清除为透明黑色。
context.fillRect(x, y, w, h)
使用当前填充样式,将给定矩形绘制到位图上。
context.strokeRect(x, y, w, h)
使用当前描边样式,将给定矩形轮廓的边框绘制到位图上。
所有当前引擎都支持。
context.fillText(text, x, y [, maxWidth ])
context.strokeText(text, x, y [, maxWidth ])
分别填充或描边给定位置的文本。如果提供了最大宽度,则文本将根据需要缩放以适应该宽度。
metrics = context.measureText(text)
返回一个 TextMetrics
对象,其中包含当前字体中给定文本的度量。
metrics.width
metrics.actualBoundingBoxLeft
metrics.actualBoundingBoxRight
metrics.fontBoundingBoxAscent
metrics.fontBoundingBoxDescent
metrics.actualBoundingBoxAscent
metrics.actualBoundingBoxDescent
metrics.emHeightAscent
metrics.emHeightDescent
metrics.hangingBaseline
metrics.alphabeticBaseline
metrics.ideographicBaseline
返回下面描述的测量值。
width
属性actualBoundingBoxLeft
属性从 textAlign
属性给出的对齐点到给定文本边界矩形的左侧平行于基线的距离,以CSS 像素为单位;正数表示从给定对齐点向左的距离。
此值与下一个值(actualBoundingBoxRight
)的总和可能大于内联框(width
)的宽度,特别是在倾斜字体中,字符会超出其提前宽度。
actualBoundingBoxRight
属性从 textAlign
属性给出的对齐点到给定文本边界矩形的右侧平行于基线的距离,以CSS 像素为单位;正数表示从给定对齐点向右的距离。
fontBoundingBoxAscent
属性从 textBaseline
属性指示的水平线到第一个可用字体的上行度量的距离,以CSS 像素为单位;正数表示从给定基线向上移动的距离。
此值和下一个值在渲染必须具有始终一致的高度(即使渲染的文本发生变化)的背景时很有用。 actualBoundingBoxAscent
属性(及其对应于下降的属性)在围绕特定文本绘制边界框时很有用。
fontBoundingBoxDescent
属性从 textBaseline
属性指示的水平线到第一个可用字体的下降度量的距离,以CSS 像素为单位;正数表示从给定基线向下移动的距离。
actualBoundingBoxAscent
属性从 textBaseline
属性指示的水平线到给定文本边界矩形顶部的距离,以CSS 像素为单位;正数表示从给定基线向上移动的距离。
即使第一个指定的字体涵盖了输入中的所有字符,此数字也会根据输入文本而发生很大变化。例如,从字母基线的小写字母“o”的actualBoundingBoxAscent
将小于大写字母“F”的actualBoundingBoxAscent
。该值很容易为负数;例如,当给定文本只是一个逗号“,
”时,从 em 方框顶部(textBaseline
值“top
”)到边界矩形顶部的距离很可能(除非字体非常不寻常)为负数。
actualBoundingBoxDescent
属性从 textBaseline
属性指示的水平线到给定文本边界矩形底部的距离,以CSS 像素为单位;正数表示从给定基线向下移动的距离。
emHeightAscent
属性从 textBaseline
属性指示的水平线到内联框中 em 方块的最高顶部之间的距离,以CSS 像素为单位;正数表示给定基线位于该 em 方块的顶部下方(因此此值通常为正数)。如果给定基线是该 em 方块的顶部,则为零;如果给定基线是该 em 方块的中间,则为字体大小的一半。
emHeightDescent
属性从 textBaseline
属性指示的水平线到内联框中 em 方块的最低底部之间的距离,以CSS 像素为单位;正数表示给定基线位于该 em 方块的底部上方。(如果给定基线是该 em 方块的底部,则为零。)
hangingBaseline
属性从 textBaseline
属性指示的水平线到内联框的悬挂基线的距离,以CSS 像素为单位;正数表示给定基线位于悬挂基线下方。(如果给定基线是悬挂基线,则为零。)
alphabeticBaseline
属性从 textBaseline
属性指示的水平线到内联框的字母基线的距离,以CSS 像素为单位;正数表示给定基线位于字母基线下方。(如果给定基线是字母基线,则为零。)
ideographicBaseline
属性
从由textBaseline
属性指示的水平线到汉字下划线基线的内联框的距离,以CSS像素为单位;正数表示给定基线位于汉字下划线基线下方。(如果给定基线是汉字下划线基线,则为零。)
使用fillText()
和strokeText()
渲染的字形可能会超出由字体大小(em 方块大小)和measureText()
返回的宽度(文本宽度)给出的框。如果出现此问题,建议作者使用上面描述的边界框值。
2D 上下文 API 的未来版本可能会提供一种方法,用于将使用 CSS 渲染的文档片段直接渲染到画布上。这将优先于专门的多行布局方式。
实现CanvasDrawPath
接口的对象具有当前默认路径。只有一个当前默认路径,它不是绘图状态的一部分。当前默认路径是一个路径,如上所述。
context.beginPath()
重置当前默认路径。
context.fill([ fillRule ])
context.fill(path [, fillRule ])
使用当前填充样式填充当前默认路径或给定路径的子路径,并遵守给定的填充规则。
context.stroke()
context.stroke(path)
使用当前描边样式描边当前默认路径或给定路径的子路径。
context.clip([ fillRule ])
context.clip(path [, fillRule ])
将裁剪区域进一步约束到当前默认路径或给定路径,使用给定的填充规则来确定哪些点在路径中。
context.isPointInPath(x, y [, fillRule ])
context.isPointInPath(path, x, y [, fillRule ])
如果给定点在当前默认路径或给定路径中,则返回 true,使用给定的填充规则来确定哪些点在路径中。
context.isPointInStroke(x, y)
context.isPointInStroke(path, x, y)
如果给定点将在当前默认路径或给定路径的描边覆盖的区域中,则返回 true,前提是当前描边样式。
此画布
元素包含几个复选框。与路径相关的命令已突出显示。
< 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();
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 );
context. drawFocusIfNeeded( element);
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 >
context.drawFocusIfNeeded(element)
context.drawFocusIfNeeded(path, element)
如果element已获得焦点,则围绕path绘制焦点环,遵循平台焦点环约定。
实现CanvasDrawImage
接口的对象具有drawImage()
方法来绘制图像。
context.drawImage(image, dx, dy)
context.drawImage(image, dx, dy, dw, dh)
context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
将给定的图像绘制到画布上。参数解释如下
如果图像尚未完全解码,则不绘制任何内容。如果图像是没有数据的画布,则抛出"InvalidStateError
"DOMException
。
imagedata = new ImageData(sw, sh [, settings])
返回一个具有给定尺寸和settings指示的颜色空间的ImageData
对象。返回的对象中的所有像素都是透明黑色。
如果宽度或高度参数为零,则抛出"IndexSizeError
"DOMException
。
imagedata = new ImageData(data, sw [, sh [, settings ] ])
使用Uint8ClampedArray
参数中提供的数据返回一个ImageData
对象,并使用给定的尺寸和settings指示的颜色空间进行解释。
由于数据中的每个像素都由四个数字表示,因此数据的长度需要是给定宽度的四倍的倍数。如果也提供了高度,则长度需要正好是宽度乘以高度乘以 4。
如果给定的数据和尺寸无法一致地解释,或者任一尺寸为零,则抛出"IndexSizeError
"DOMException
。
imagedata = context.createImageData(imagedata)
返回一个与参数具有相同尺寸和颜色空间的ImageData
对象。返回的对象中的所有像素都是透明黑色。
imagedata = context.createImageData(sw, sh [, settings])
返回一个具有给定尺寸的ImageData
对象。返回的对象的颜色空间是context的颜色空间,除非由settings覆盖。返回的对象中的所有像素都是透明黑色。
如果宽度或高度参数为零,则抛出"IndexSizeError
"DOMException
。
imagedata = context.getImageData(sx, sy, sw, sh [, settings])
返回一个ImageData
对象,其中包含位图给定矩形的图像数据。返回的对象的颜色空间是context的颜色空间,除非由settings覆盖。
如果宽度或高度参数为零,则抛出"IndexSizeError
"DOMException
。
imagedata.width
imagedata.height
以像素为单位返回ImageData
对象中数据的实际尺寸。
imagedata.data
返回包含以 RGBA 顺序排列的数据的一维数组,作为 0 到 255 范围内的整数。
imagedata.colorSpace
返回像素的颜色空间。
context.putImageData(imagedata, dx, dy [, dirtyX, dirtyY, dirtyWidth, dirtyHeight ])
将给定ImageData
对象中的数据绘制到位图上。如果提供了脏矩形,则仅绘制该矩形中的像素。
对于此方法调用,globalAlpha
和globalCompositeOperation
属性以及阴影属性将被忽略;画布中的像素将被整体替换,没有任何合成、alpha 混合、阴影等。
如果imagedata对象的data
属性值的 [[ViewedArrayBuffer]] 内部槽已分离,则抛出"InvalidStateError
"DOMException
。
在以下示例中,脚本生成一个ImageData
对象以便能够在其上进行绘制。
// 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) { ... }
以下是如何使用getImageData()
和putImageData()
实现边缘检测滤镜的示例。
<!DOCTYPE HTML>
< html lang = "en" >
< 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
// In this case input.width and input.height
// match canvas.width and canvas.height
// but we'll use the former to keep the code generic.
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 >
以下是一个在绘制纯色并使用 getImageData()
读取结果时应用的颜色空间转换示例。
<!DOCTYPE HTML>
< html lang = "en" >
< title > Color space image data demo</ title >
< canvas ></ canvas >
< script >
const canvas = document. querySelector( 'canvas' );
const context = canvas. getContext( '2d' , { colorSpace: 'display-p3' });
// Draw a red rectangle. Note that the hex color notation
// specifies sRGB colors.
context. fillStyle = "#FF0000" ;
context. fillRect( 0 , 0 , 64 , 64 );
// Get the image data.
const pixels = context. getImageData( 0 , 0 , 1 , 1 );
// This will print 'display-p3', reflecting the default behavior
// of returning image data in the canvas's color space.
console. log( pixels. colorSpace);
// This will print the values 234, 51, and 35, reflecting the
// red fill color, converted to 'display-p3'.
console. log( pixels. data[ 0 ]);
console. log( pixels. data[ 1 ]);
console. log( pixels. data[ 2 ]);
</ script >
context.globalAlpha [ = value ]
返回应用于渲染操作的当前全局 alpha值。
可以设置,以更改全局 alpha值。超出 0.0 .. 1.0 范围的值将被忽略。
context.globalCompositeOperation [ = value ]
返回当前合成和混合运算符,取值范围由合成和混合中定义。 [COMPOSITE]
可以设置,以更改当前合成和混合运算符。未知值将被忽略。
context.imageSmoothingEnabled [ = value ]
返回在放大图像时,图案填充和 drawImage()
方法是否会尝试平滑图像(如果图像像素与显示屏不完全对齐)。
可以设置,以更改是否平滑图像(true)或不平滑(false)。
context.imageSmoothingQuality [ = value ]
返回当前的图像平滑质量首选项。
实现 CanvasShadowStyles
接口的对象上的所有绘图操作都受四个全局阴影属性的影响。
context.shadowColor [ = value ]
返回当前的阴影颜色。
可以设置,以更改阴影颜色。无法解析为 CSS 颜色的值将被忽略。
context.shadowOffsetX [ = value ]
context.shadowOffsetY [ = value ]
返回当前的阴影偏移量。
可以设置,以更改阴影偏移量。不是有限数字的值将被忽略。
context.shadowBlur [ = value ]
返回应用于阴影的当前模糊级别。
可以设置,以更改模糊级别。不是大于或等于零的有限数字的值将被忽略。
如果当前合成和混合运算符为 "copy
",则阴影实际上不会渲染(因为形状将覆盖阴影)。
实现 CanvasFilters
接口的对象上的所有绘图操作都受全局 filter
属性的影响。
context.filter [ = value ]
返回当前过滤器。
可以设置,以更改过滤器。值可以是字符串 "none
" 或可解析为 <filter-value-list> 的字符串。其他值将被忽略。
虽然 context.
将禁用上下文的过滤器,但 filter
= "none
"context.
、filter
= ""context.
和 filter
= nullcontext.
都被视为无法解析的输入,并且当前过滤器的值保持不变。filter
= undefined
当前过滤器值中使用的坐标被解释为一个像素等效于一个 SVG 用户空间单位和一个画布坐标空间单位。过滤器坐标不受 当前变换矩阵 的影响。当前变换矩阵仅影响过滤器的输入。过滤器在输出位图的坐标空间中应用。
由于绘图使用过滤器值 "none
" 执行,直到外部定义的过滤器完成加载,因此作者可能希望在继续执行绘图操作之前确定此类过滤器是否已完成加载。实现此目的的一种方法是在同一页面中的其他位置加载外部定义的过滤器,并在某些发送 load
事件的元素中(例如,SVG use
元素),并等待分派 load
事件。
当画布具有交互性时,作者应在元素的回退内容中包含与画布每个可聚焦部分对应的可聚焦元素,如上例所示。
渲染焦点环时,为确保焦点环的外观与原生焦点环一致,作者应使用 drawFocusIfNeeded()
方法,并将其传递给正在为其绘制环的元素。此方法仅在元素获得焦点时绘制焦点环,因此可以在每次绘制元素时简单地调用它,而无需事先检查元素是否已获得焦点。
作者应避免使用 canvas
元素实现文本编辑控件。这样做有许多缺点
这是一项巨大的工作量,强烈建议作者避免执行任何此类操作,而是使用 input
元素、textarea
元素或 contenteditable
属性。
以下是一个使用画布绘制 漂亮的辉光线的脚本示例。
< 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 >
canvas
的 2D 渲染上下文通常用于基于精灵的游戏。以下示例演示了这一点
此示例的源代码如下
<!DOCTYPE HTML>
< html lang = "en" >
< meta charset = "utf-8" >
< title > Blue Robot Demo</ title >
< style >
html { overflow : hidden ; min-height : 200 px ; min-width : 380 px ; }
body { height : 200 px ; position : relative ; margin : 8 px ; }
. buttons { position : absolute ; bottom : 0 px ; left : 0 px ; margin : 4 px ; }
</ 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 100ms, 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 = "https://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 = "https://creativecommons.org/licenses/by-sa/3.0/" > Creative
Commons Attribution-ShareAlike 3.0 Unported License</ a > .</ small >
</ footer >
ImageBitmap
渲染上下文ImageBitmapRenderingContext
是一个面向性能的接口,它提供了一种低开销的方法来显示 ImageBitmap
对象的内容。它使用传输语义来减少总体内存消耗。与 CanvasRenderingContext2D
的 drawImage()
方法不同,它还通过避免中间合成来简化性能。
例如,使用 img
元素作为中间元素将图像资源放入画布中,会导致内存中同时存在图像的两个副本:img
元素的副本和画布的后备存储中的副本。当处理非常大的图像时,此内存成本可能过高。这可以通过使用 ImageBitmapRenderingContext
来避免。
使用 ImageBitmapRenderingContext
,以下是如何以内存和 CPU 高效的方式将图像转码为 JPEG 格式
createImageBitmap( inputImageBlob). then( image => {
const canvas = document. createElement( 'canvas' );
const context = canvas. getContext( 'bitmaprenderer' );
context. transferFromImageBitmap( image);
canvas. toBlob( outputJPEGBlob => {
// Do something with outputJPEGBlob.
}, 'image/jpeg' );
});
ImageBitmapRenderingContext
接口所有当前引擎都支持。
context = canvas.getContext('bitmaprenderer' [, { [ alpha: false ] } ])
返回一个 ImageBitmapRenderingContext
对象,该对象永久绑定到特定的 canvas
元素。
如果提供了 alpha
设置并将其设置为 false,则强制画布始终不透明。
context.canvas
返回 canvas
元素,该上下文绑定到此元素。
context.transferFromImageBitmap(imageBitmap)
将底层 位图数据 从 imageBitmap 传输到 context,并且位图成为 context 所绑定的 canvas
元素的内容。
context.transferFromImageBitmap(null)
将 context 所绑定的 canvas
元素的内容替换为一个 透明黑色 位图,其大小对应于 width
和 height
内容属性。
OffscreenCanvas
接口所有当前引擎都支持。
OffscreenCanvas
是一个 EventTarget
,因此 OffscreenCanvasRenderingContext2D
和 WebGL 都可以向其触发事件。OffscreenCanvasRenderingContext2D
可以触发 contextlost
和 contextrestored
,而 WebGL 可以触发 webglcontextlost
和 webglcontextrestored
。 [WEBGL]
OffscreenCanvas
对象用于创建渲染上下文,类似于 HTMLCanvasElement
,但与 DOM 无连接。这使得在 worker 中使用 canvas 渲染上下文成为可能。
OffscreenCanvas
对象可能持有对 占位符 canvas
元素 的弱引用,该元素通常位于 DOM 中,其嵌入内容由 OffscreenCanvas
对象提供。OffscreenCanvas
对象的位图作为 OffscreenCanvas
的 相关代理 的 事件循环 的 更新渲染 步骤的一部分推送到 占位符 canvas
元素。
offscreenCanvas = new OffscreenCanvas(width, height)
返回一个新的 OffscreenCanvas
对象,该对象未链接到 占位符 canvas
元素,其位图的大小由 width 和 height 参数确定。
context = offscreenCanvas.getContext(contextId [, options ])
返回一个对象,该对象公开了用于在 OffscreenCanvas
对象上绘图的 API。 contextId 指定所需的 API:“2d
”、“bitmaprenderer
”、“webgl
”、“webgl2
” 或“webgpu
”。 options 由该 API 处理。
本规范定义了下面的“2d
”上下文,它类似于但不同于从 canvas
元素创建的“2d
”上下文。WebGL 规范定义了“webgl
”和“webgl2
”上下文。 WebGPU 定义了“webgpu
”上下文。 [WEBGL] [WEBGPU]
如果 canvas 已使用其他上下文类型初始化,则返回 null(例如,在获取“webgl
”上下文后尝试获取“2d
”上下文)。
offscreenCanvas.width [ = value ]
offscreenCanvas.height [ = value ]
这些属性返回 OffscreenCanvas
对象的 位图 的尺寸。
可以设置它们,以使用具有指定尺寸的新 透明黑色 位图替换 位图(有效地调整其大小)。
如果尺寸已更改的 OffscreenCanvas
对象具有 占位符 canvas
元素,则 占位符 canvas
元素 的 自然大小 仅会在 OffscreenCanvas
的 相关代理 的 事件循环 的 更新渲染 步骤期间更新。
promise = offscreenCanvas.convertToBlob([options])
返回一个 promise,该 promise 将以一个新的 Blob
对象为结果,该对象表示包含 OffscreenCanvas
对象中图像的文件。
如果提供,则参数是一个字典,用于控制要创建的图像文件的编码选项。type
字段指定文件格式,其默认值为“image/png
”;如果请求的类型不受支持,则也会使用该类型。如果图像格式支持可变质量(例如“image/jpeg
”),则 quality
字段是一个介于 0.0 到 1.0(含)之间的数字,表示所需的结果图像的质量级别。
canvas.transferToImageBitmap()
返回一个新创建的 ImageBitmap
对象,其中包含 OffscreenCanvas
对象中的图像。OffscreenCanvas
对象中的图像将替换为新的空白图像。
以下是所有实现 OffscreenCanvas
接口的对象作为 事件处理程序(及其相应的 事件处理程序事件类型)支持的 事件处理程序 IDL 属性
事件处理程序 | 事件处理程序事件类型 |
---|---|
oncontextlost | contextlost
|
oncontextrestored | contextrestored
|
OffscreenCanvasRenderingContext2D
所有当前引擎都支持。
OffscreenCanvasRenderingContext2D
对象是用于绘制到 OffscreenCanvas
对象的 位图 的渲染上下文。它类似于 CanvasRenderingContext2D
对象,但存在以下差异
OffscreenCanvasRenderingContext2D
对象有一个 位图,该位图在对象创建时初始化。
该 位图 具有一个 origin-clean 标志,该标志可以设置为 true 或 false。最初,当创建这些位图之一时,其 origin-clean 标志必须设置为 true。
OffscreenCanvasRenderingContext2D
对象还有一个 alpha 标志,该标志可以设置为 true 或 false。最初,当创建上下文时,其 alpha 标志必须设置为 true。当 OffscreenCanvasRenderingContext2D
对象的 alpha 标志设置为 false 时,则其所有像素的 alpha 通道必须固定为 1.0(完全不透明),并且尝试更改任何像素的 alpha 分量必须被静默忽略。
OffscreenCanvasRenderingContext2D
对象还有一个类型为 PredefinedColorSpace
的 颜色空间 设置。上下文的 位图 的颜色空间设置为上下文的 颜色空间。
OffscreenCanvasRenderingContext2D
对象有一个 关联的 OffscreenCanvas
对象,它是创建 OffscreenCanvasRenderingContext2D
对象的 OffscreenCanvas
对象。
offscreenCanvas = offscreenCanvasRenderingContext2D.canvas
预乘 alpha 指的是表示图像中透明度的一种方式,另一种方式是非预乘 alpha。
在非预乘 alpha 下,像素的红色、绿色和蓝色通道表示该像素的颜色,其 alpha 通道表示该像素的不透明度。
然而,在预乘 alpha 下,像素的红色、绿色和蓝色通道表示像素添加到图像的颜色量,其 alpha 通道表示像素遮挡其后方内容的程度。
例如,假设颜色通道范围从 0(关闭)到 255(全强度),则以下示例颜色以以下方式表示
CSS 颜色表示 | 预乘表示 | 非预乘表示 | 颜色描述 | 在其他内容上方混合的颜色图像 |
---|---|---|---|---|
rgba(255, 127, 0, 1) | 255, 127, 0, 255 | 255, 127, 0, 255 | 完全不透明的橙色 | |
rgba(255, 255, 0, 0.5) | 127, 127, 0, 127 | 255, 255, 0, 127 | 半透明的黄色 | |
不可表示 | 255, 127, 0, 127 | 不可表示 | 加性半透明橙色 | |
不可表示 | 255, 127, 0, 0 | 不可表示 | 加性完全透明橙色 | |
rgba(255, 127, 0, 0) | 0, 0, 0, 0 | 255, 127, 0, 0 | 完全透明(“不可见”)橙色 | |
rgba(0, 127, 255, 0) | 0, 0, 0, 0 | 255, 127, 0, 0 | 完全透明(“不可见”)青绿色 |
将颜色值从非预乘表示转换为预乘表示 涉及将颜色的红色、绿色和蓝色通道乘以其 alpha 通道(重新映射 alpha 通道的范围,使得“完全透明”为 0,“完全不透明”为 1)。
将颜色值从预乘表示转换为非预乘表示 涉及逆运算:将颜色的红色、绿色和蓝色通道除以其 alpha 通道。
由于某些颜色只能在预乘 alpha 下表示(例如,加性颜色),而其他颜色只能在非预乘 alpha 下表示(例如,“不可见”颜色,即使没有不透明度也保留某些红色、绿色和蓝色值);并且 8 位整数上的除法和乘法(canvas 的颜色当前存储方式)会导致精度损失,因此在非完全不透明的颜色之间转换预乘和非预乘 alpha 是一个有损操作。
CanvasRenderingContext2D
的 输出位图 和 OffscreenCanvasRenderingContext2D
的 位图 必须使用预乘 alpha 来表示透明颜色。
canvas 位图使用预乘 alpha 表示颜色非常重要,因为它会影响可表示颜色的范围。虽然由于 CSS 颜色是非预乘的且无法表示加性颜色,因此目前无法直接将加性颜色绘制到画布上,但仍然可以通过例如将加性颜色绘制到 WebGL 画布上,然后通过 drawImage()
将该 WebGL 画布绘制到 2D 画布上来实现。