[译] HTML Canvas 2D Context

HTML Canvas 2D Context

W3C Recommendation 19 November 2015

概述

该规范定义了HTML canvas 的2D绘图上下文,这个2D绘图上下文提供了一些对象,方法和属性来在canvas画布上绘制丰富的图像。

目录

1、Conformance requirements

2、The canvas state

3、Line styles

4、Text styles

5、Building paths

6、Transformations

7、Image sources for 2D rendering contexts

8、Fill and stroke styles

9、Drawing rectangles to the canvas

10、Drawing text to the canvas

11、Drawing paths to the canvas

12、Drawing images to the canvas

13、Hit regions

14、Pixel manipulation

15、Compositing

16、Shadows

17、Drawing model

18、Best practices

19、Examples

References


1、Conformance requirements 遵守规范一致性

这个规范是一个HTML规范。所有标准的要求,标准的类、定义、依赖、术语,和排版惯例描述都可参照HTML5规范。HTML

接口定义HTML

这个规范定义2d上下文是如何实现的CanvasRenderingContext2D这个接口。

当用户使用canvas元素的getContext()方法时,这个方法会返回一个包含绘图上下文的新的对象。用户代理(即浏览器)必须返回一个新的CanvasRenderingContext2D对象,任何额附加的参数都会被忽略。

这个2D绘图上下文代表一个笛卡尔坐标系的平面,即(0,0)原点在画布的左上角,并且x坐标会向右越来越大,y坐标向下原来越大。


IDL

typedef (HTMLImageElement or
         HTMLVideoElement or
         HTMLCanvasElement) CanvasImageSource;

interface CanvasRenderingContext2D {

  // back-reference to the canvas
  readonly attribute HTMLCanvasElement canvas;

  // state
  void save(); // push state on state stack
  void restore(); // pop state stack and restore state

  // transformations (default: transform is the identity matrix)
  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);

  // compositing
           attribute unrestricted double globalAlpha; // (default: 1.0)
           attribute DOMString globalCompositeOperation; // (default: "source-over")

  // 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();
  void stroke();
  void drawFocusIfNeeded(Element element);
  void clip();
  boolean isPointInPath(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(HitRegionOptions options);
  void removeHitRegion(DOMString id);
  void clearHitRegions();

  // pixel manipulation
  ImageData createImageData(unrestricted double sw, unrestricted 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]
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")
};

[NoInterfaceObject]
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 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 counterclockwise = false);

  };

interface CanvasGradient {
  // opaque object
  void addColorStop(double offset, DOMString color);
};

interface CanvasPattern {
  // opaque object
};

interface TextMetrics {
  readonly attribute double width;
};

dictionary HitRegionOptions {
  // dictionary to allow expansion on Hit Regions in Canvas Context 2D Level 2
  DOMString id = "";
  // for control-backed regions:
  Element? control = null;
};

interface ImageData {
  readonly attribute unsigned long width;
  readonly attribute unsigned long height;
  readonly attribute Uint8ClampedArray data;
};

Note:

context.canvas
//该属性将返回canvas元素。

canvas属性必须返回此绘图上下文所绘制的canvas元素。

除非另有规定,对于2D绘图上下文,任何方法传入了无穷非数数值的参数,必须忽略。

每当CSS值currentColor在这个API中被用作颜色,计算后的‘color’属性即是指定的颜色值,如果计算后的‘color’属性为‘undefined’,则当前颜色为完全不透明的黑色。

如下情况,CanvasGradient对象的addColorStop(),计算后的颜色值总是完全的不透明黑色。

这是因为CanvasGradient对象是和canvas无关联的,一个CanvasGradient对象被canvas创建后也可以被另一个canvas使用,所以因此没有办法知道使用哪一个canvas元素作为被指定颜色的哪一个。


2、The canvas state 画布的状态

每一个上下文包含了一个栈的绘制状态。绘制状态由一下内容组成:

  • 当前变换矩阵
  • 当前裁剪区域
  • 当前如下属性值(strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline.

当前路径和当前bitmap并不是绘制状态的一部分,当前路径是固定的,并且只能使用**beginPath()**方法重置。当前bitmap是canvas的一个属性,并不是上下文。

context.save()
//将当前绘制状态推入栈。
context.restore()
//将当前绘制状态出栈,恢复上下文到最近一个状态。

save() 方法必须推入一个当前绘制状态的拷贝到栈中。

restore() 方法必须移出栈顶的一个绘制状态,并且重置绘制状态,如果当前栈中没有保存的状态,该方法将不作为。

3、Line styles 线的样式

context.lineWidth [ = value ]
// 返回当前线的宽度。
// 可以被设置,改变显得宽度,不是有限值和零值则忽略。

context.lineCap [ = value ]
// 返回线的端点样式。
// 可以被设置,改变线的端点样式。
// 可能的线端点样式有 "butt","round","square",其他值则忽略。

context.lineJoin [ = value ]
// 返回当前线的拐点样式。
// 可以被设置,改变线的拐点样式。
// 可能的线的拐点样式有 "bevel", "round", "miter"。 其他的值则忽略。

context.miterLimit [ = value ]
// 返回当前斜接限制比率。
// 可以被设置,改变斜接限制比率,非有限值和零值则直接忽略。

context.setLineDash(segments)
// 设置当前线的破折模式(仅被用于描边),参数是一个一维数组,分别为有线可无线的长度。

segments = context.getLineDash()
// 返回一个当前线的破折模式的拷贝。

context.lineDashOffset[ = value ]
// 返回破折的偏移量
// 可以被设置,改变偏移量,非有限值和零值则直接忽略。

实现了CanvasDrawingStyle接口的对象拥有属性和方法,用来控制对象是如何操纵线的。

lineWidth 属性给了线一个宽度,在单位空间的坐标系中,如果需要取得,就必须返回当前的值,如果需要设置,零值、无穷值、负值和非数值的值可直接忽略,其他可用的值必须改变当前值到一个新的值。

当实现了CanvasDrawingStyle接口的对象被创建,lineWidth属性必须设置初始值为1.0

lineCap属性定义了线的端点样式类型,这三个可用的值分别是"bott", “round”, “square”,需要取得该值,它必须返回当前的值。需要设置该值,如果新值是"butt",“round”,"square"其中之一,则必须将旧值改变为新的值,其他值直接忽略,原值不做变动。

CanvasDrawingStyle接口被对象实现后,lineCap的初始值为"butt"。

lineJoin属性定义了两条线在拐角相遇时的样式,这三种可用的值分别为"bevel",“round”,“miter”。

需要获取值,必须返回当前值。需要设置值时,如果新的值时"bevel",“round”,"miter"其中之一,那么当前的值必须改变为新的值;其他值直接忽略,原值不变动。

CanvasDrawingStyle接口被对象实现后,lineJoin必须初始化为"miter"。

lineJoin属性拥有值"miter",描边使用斜接限制比率来决定如何渲染两条线的连接效果。斜接限制比率可以被明确的使用miterLimit属性来指定。需要获取该值,必须返回当前的值,需要设置该值,零值,负值,无限值和非数值得值则必须忽略,并保持原值不变动。其他值可用的值则必须改变当前值为新的值。

当对象实现了CanvasDrawingStyle 接口时,miterLimit属性必须初始化为10.0。

每一个CanvasDrawingStyle对象都有一组dash列,初始化时dash list必须为空。

4、Text styles文本的样式

context.font[ = value ]
// 返回当前字体设置。
// 可以被设置,改变当前字体,语法和CSS中设置字体属性的语法相同,属性值如若不能被解析成CSS字体值则直接忽略。

context.textAlign[ = value ]
// 返回当前文本的水平对齐样式。
// 可以被设置,改变水平对齐方式。可以的值有"start", "end", "left", "right"和"center",其他的值则直接忽略。

context.textBaseline[ = value ]
// 返回当前垂直对齐样式。
// 可能的属性值有"top","hanging","middle","alphabetic","ideographic"或者"bottom"
// 可以被设置,改变垂直对齐样式,可被设置的值在下方,其他值则直接忽略,默认的值为“alphabetic”。

使用**@font-face**声明的字体,需要等待字体被加载后才能使用。

只有矢量字体可以被用户代理识别;如果用户代理使用位图字体则渲染后的效果会非常的丑陋。

context.font = 'italic 400 12px/2 Unkonw Font, sans-serif';

5、Building paths 创建路径

每一个实现了CanvasPathMethod接口的对象都拥有path,一个路径拥有一系列的零个或更多个子路径。每一个子路径都包含一系列的点,由直线或者曲线连接,由一个标志标明是否闭合。一个闭合的子路径是指最后一个点和该路径的第一个点由一条直线相连接。子路径少于两个点则直接忽略。

当一个对象实现了CanvasPathMethod接口,路径必须初始化为拥有零个子路径。

context.movetTo(x, y);
// 使用给的点创建一条新的子路径。

context.closePath();
// 标记当前子路径为闭合的,并且使用一个和刚刚闭合的路径一模一样的一条新的组路径。

context.lineTo(x, y);
// 添加给的点到当前的子路径,通过一条直线相连接。

context.quadraticCurveTo(cpx, cpy, x, y);
// 添加给的点到当前的子路径,使用给的点创建一个二次贝塞尔曲线并连接到上一个点。

context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
// 添加给的点到当前路径,使用给的点创建一个三次贝塞尔曲线并连接到上一个点。

context.arcTo(x1, y1, x2, y2, radius);
// 使用给定的控制点和半径添加一个圆弧,使用一条直线连接上一个点。
// 如果给的半径为负数则抛出一个**IndexSizeError**错误。
context.arc(x, y, radius, startAngle, endAngle[, counterclockwise]);
// 使用给定的参数创建一个圆。

context.rect(x, y, width, height);
// 使用给定的参数创建一个矩形。

如下的方法允许开发者操作路径对象,即实现了CanvasPathMethods接口的对象。

对于CanvasRenderingContext2D对象,点和线添加到当前默认的路径中时,必须被通过**current transformation matrix**变换后添加到路径中。

**method()**方法必须使用指定的点作为第一个(唯一一个)点创建开始一个新的子路径。

使用**moveTo()**方法将重新开始绘制一段路径。

如果对象的路径没有子路径,则**closePath()**方法必须不作为。否则,它必须标记为最后一条子路径为闭合的。


6、Transformations 变换

每一个CanvasRenderingContext2D对象拥有一个当前的变换矩阵,并拥有一系列的方法操作这些矩阵,当一个CanvasRenderingContext2D对象被创建后,变换矩阵必须被初始化为有限的变换。

当在CanvasRenderingContext2D上创建当前路径,绘制文本,形状,路径时,变换矩阵被应用到坐标系中。

context.scale(x, y);
// 叠加改变变换矩阵通过给定的参数应用缩放变换。

context.rotate(angle);
// 叠加改变变换矩阵通过给定的参数应用旋转变换,参数为弧度制。

context.translate(x, y);
// 叠加改变变换矩阵通过给定的参数应用平移变换。

context.transform(a, b, c, d, e, f);
// 叠加改变变换矩阵通过应用给定的参数。

context.setTransform(a, b, c, d, e, f);
// 非叠加重置变换矩阵通过给定的参数。

7、Image sources for 2D rendering contexts 源图像 2D渲染上下文

通用的类型允许对象实现任何如下的接口,来作为图像源。

HTMLImageElement(img元素)

HTMLVideoElement(video元素)

HTMLCanvasElement(canvas元素)

这些可使用的图像源均需要正确解码并加载完成后方可被渲染。

请求的图像源必须要与当前源同源


8、Fill and stroke styles 填充和描边样式

context.fillStyle[ = value ]
// 返回当前填充形状使用的样式
// 可以被设置,改变填充样式
// 这个样式可以是字符串,CSS颜色,或者**CanvasGradient**或者**CanvasPattern**对象。
// 不可用的值将直接被忽略

context.strokeStyle[ = value ]
// 返回当前描边形状使用的样式
// 可以被设置,改变描边样式。
// 样式可以是字符串,包含CSS颜色,或者**CanvasGradient**或者**CanvasPattern**对象
// 不可用的值将被直接忽略。

创建线性渐变和径向渐变

gradient.addColorStop(offset, color);
// 通过给定的颜色值和偏移位置,添加一个颜色控制点,0表示渐变开始的位置,1表示渐变结束的位置。
// 当给定的偏移位置溢出了0-1的范围,则抛出**IndexSizeError**错误。如果颜色值不能被解析则抛出**SyntaxError**错误。

gradient = context.createLinearGradient(x0, y0, x1, y1);
// 返回**CanvasGradient**对象,代表一个线性渐变,绘制沿着给定的坐标。

gradient = context.createRadinalGradient(x0, y0, r0, x1, y1, r1);
// 返回**CanvasGradient**对象,代表径向渐变,绘制沿着给定的两个圆形表示参数。
// 如果给定的圆形半径为负值,则抛出**IndexSizeError**错误。

创建填充模式

patter = context.createPattern(image, repetition);
// 返回**CanvasPattern**对象,使用给定的图像源和重复规则。
// 允许的重复规则有"repeat","repeat-x","repeat-y"和"no-repeat",如果重复参数为空,则默认重复规则为"repeat"。
// 如果图像源没有图像数据,抛出**InvalidStateError**异常,如果第二个参数不是被允许的值,抛出**Syntax**异常。如果图像源没有被完全解码,则该方法返回**null**。

9、Drawing rectangles to the canvas 绘制矩形

context.clearRect(x, y, w, h);
// 在给定的参数的范围内,清空所有画布上的像素

context.fillRect(x, y, w, h);
// 使用给定的参数绘制矩形并使用当前上下文的颜色填充。

context.strokeRect(x, y, w, h);
// 使用给定的参数绘制矩形并使用当前上下文描边。

10、Drawing text to the canvas 绘制文本

context.fillText(text, x, y[, maxWidth]);

context.strokeText(text, x, y[, maxWidth]);
// 使用给定的文本在给定的位置填充或描边,如果最大宽度在参数中被提供了,文本将被缩放以适应宽度(如果需要的话)。

metrics = context.measureText(text);
// 通过传入一段文本,返回应用当前字体上下文计算后**TextMetrics**对象,对象包括文本的宽度。

metrics.width
// 返回文本的宽度。

11、Drawing paths to the canvas 绘制路径

context.beginPath();
// 重置当前路径。

context.fill();
// 使用当前上下文的填充样式,填充当前路径的子路径。

context.stroke();
// 使用当前上下文的描边样式,描边当前路径的子路径。

context.drawFocusIfNeeded(element);
// 将当前画布的定位信息返回给用户,基于当前路径,如果给定的元素已经获取焦点,绘制一个获取焦点的样式,默认样式根据用户代理而定。

context.clip();
// 下方的绘制内容将限制在上方的路径内。

context.isPointInPath(x, y);
// 返回给定的点坐标是否在当前路径内。如果在则返回**True**,否则返回**false**。

12、Drawing images to the canvas 绘制图像源

drawImage方法被用来在画布上绘制图像。

这个方法可以被以下三种不同的传参方式调用:

  • drawImage(image, x, y);
  • drawImage(image, dx, dy, dw, dh);
  • drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);

每一种方法的图像源都可以是HTMLImageElement,HTMLCanvasElement,HTMLVideoElement

context.drawImage(image, dx, dy);
context.drawImage(image, dx, dx, dw, dh);
context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);

通过给定的参数绘制图像源到画布上。

如果给定的参数不是img,canvas或者video元素,抛出TypeMismatchError异常,如果图像没有图像数据,抛出InvalidStateError异常,如果图像源的二维大小为0,抛出一个IndexSizeError异常,如果图像源没有被完全解码,则不做绘制。


13、Hit regions 响应区域

每一个canvas元素的私有上下文均为CanvasRenderingContext2D对象,便必须有响应区域列表。

context.addHitRegion(option);
// 添加一个响应区域到画布基于当前默认的路径,参数是一个包含如下属性的对象:
**id***(默认为空的字符串)
ID用于本次区域,用于在画布上的鼠标事件。

**control**(默认为空)
// 一个元素(**canvas**的后代),事件的在这里被转发。

context.removeHitRegion(id);
// 移除一个响应区域。

context.clearHitRegions();
// 从位图画布上移除所有的响应区域。

14、Pixel manipulation 像素操作

imagedata = context.createImageData(sw, sh);
// 返回一个**imageData**对象借助给定的维度范围。

imagedata = context.createImageData(imagedata);
// 返回**imageData**对象使用相同的提供的维度范围。

imagedata = context.getImageData(sx, sy. sw, sh);
// 返回**imageData**对象,包含图像数据为给定的矩形范围。

imagedata.width
imagedata.height
// 返回实际的维度数据。

imagedata.data
// 返回以为数组包含RGBA数据。

context.putImageData(imagedata, dx, dy[, dirtyX, dirtyY, dirtyWidth, dirtyHeight]);
// 从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>
 <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>

15、Compositing 合成

context.globalAlpha[ = value ]
// 返回或设置当前不透明度,提供的值的范围为0-1;

context.globalCompositeOperation[ = value ]
// 返回或设置合成模式。

source-atop
A atop B. Display the source image wherever both images are opaque. Display the destination image wherever the destination image is opaque but the source image is transparent. Display transparency elsewhere.

source-in
A in B. Display the source image wherever both the source image and destination image are opaque. Display transparency elsewhere.

source-out
A out B. Display the source image wherever the source image is opaque and the destination image is transparent. Display transparency elsewhere.

source-over (default)
A over B. Display the source image wherever the source image is opaque. Display the destination image elsewhere.

destination-atop
B atop A. Same as source-atop but using the destination image instead of the source image and vice versa.

destination-in
B in A. Same as source-in but using the destination image instead of the source image and vice versa.

destination-out
B out A. Same as source-out but using the destination image instead of the source image and vice versa.

destination-over
B over A. Same as source-over but using the destination image instead of the source image and vice versa.

lighter
A plus B. Display the sum of the source image and destination image, with color values approaching 255 (100%) as a limit.

copy
A (B is ignored). Display the source image instead of the destination image.

xor
A xor B. Exclusive OR of the source image and destination image.

vendorName-operationName
Vendor-specific extensions to the list of composition operators should use this syntax.


16、Shadows 阴影

context.shadowColor[ = value ]
// 返回当前阴影颜色
// 设置阴影颜色

context.shadowOffsetX[ = value ]
context.shadowOffsetY[ = value ]
// 返回或设置阴影的偏移量

context.shadowBlur[ = value ]
// 返回或设置阴影的模糊值。

17、Drawing model 绘制模型


18、Best practices 最佳实践


19、Examples 示例

<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>

参考文献

所有的参考文献均为标准化的,除了标注为‘非标准化’的那些

[BEZIER]

Courbes à poles, P. de Casteljau. INPI, 1959.

[CSS]

Cascading Style Sheets Level 2 Revision 1 (URL: http://www.w3.org/TR/CSS/), B. Bos, T. Çelik, I. Hickson, H. Lie. W3C.

[CSSCOLOR]

CSS Color Module Level 3 (URL: http://www.w3.org/TR/css3-color/), T. Çelik, C. Lilley, L. Baron. 7 June 2011. W3C Recommendation.

[CSSFONTS]

CSS Fonts Module Level 3 (URL: http://www.w3.org/TR/css3-fonts/), J. Daggett. W3C.

[CSSIMAGES]

CSS Image Values and Replaced Content Module Level 3 (URL: http://www.w3.org/TR/css3-images/), E. Etemad, T. Atkins. W3C.

[CSSOM]

Cascading Style Sheets Object Model (CSSOM) (URL: http://www.w3.org/TR/cssom/), S. Pieters, G. Adams. W3C.

[HTML]

Ian Hickson; Robin Berjon; Steve Faulkner; Travis Leithead; Erika Doyle Navara; Edward O’Connor; Silvia Pfeiffer. HTML5. 28 October 2014. W3C Recommendation. URL: http://www.w3.org/TR/html5/

[PORTERDUFF]

Compositing Digital Images (URL: http://keithp.com/~keithp/porterduff/p253-porter.pdf), T. Porter, T. Duff. In Computer graphics, volume 18, number 3, pp. 253-259. ACM Press, July 1984.

[TYPEDARRAY]

Typed Array Specification (URL: https://www.khronos.org/registry/typedarray/specs/latest/), D. Herman, K. Russell. Khronos.

[WEBIDL]

Web IDL (URL: http://www.w3.org/TR/WebIDL-1/), Cameron McCormack, Boris Zbarsky, Yves Lafon, Travis Leithead. W3C.

HTML Canvas 2D Context 原文地址

原创声明 » 本文由陈帅华翻译,非原创文章。
联系方式 » 
微信:huazi19930927
邮箱:lanserdi@163.com
发布日期 » 2017年8月29日 周二
Github账号登录以留言