Node-Canvas是一个由开罗支持的帆布实现。
提示
V3.0.0-RC2现在可以在Linux(X64 GliBC),MacOS(X64)和Windows(X64)上进行测试!这是第一个使用N-API和Prebuild-install的版本。如果您遇到任何问题,请尝试一下,让我们知道。
npm install canvas@next
$ npm install canvas
默认情况下,如果您在以下平台之一上,将下载预构建的二进制文件:
如果要从源构建,请使用npm install --build-from-source
,并查看下面的编译部分。
Node.js的最低版本是18.12.0 。
如果您没有支持的操作系统或处理器体系结构,或者您使用的--build-from-source
,则将在系统上编译该模块。这需要几个依赖项,包括开罗和Pango。
有关详细的安装信息,请参见Wiki。公共OS的一行安装说明如下。请注意,libgif/giflib,librsvg和libjpeg是可选的,仅当您分别需要GIF,SVG和JPEG支持时才需要。需要开罗V1.10.0或更高版本。
操作系统 | 命令 |
---|---|
macos | 使用自制:brew install pkg-config cairo pango libpng jpeg giflib librsvg pixman python-setuptools |
Ubuntu | sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev |
软呢帽 | sudo yum install gcc-c++ cairo-devel pango-devel libjpeg-turbo-devel giflib-devel |
Solaris | pkgin install cairo pango pkg-config xproto renderproto kbproto xextproto |
OpenBSD | doas pkg_add cairo pango png jpeg giflib |
视窗 | 看到Wiki |
其他的 | 看到Wiki |
Mac OS X V10.11+:如果您最近已更新为Mac OS X V10.11+,并且在编译时遇到麻烦,请运行以下命令: xcode-select --install
。在堆栈溢出上阅读有关问题的更多信息。如果您安装了Xcode 10.0或更高,为了从源构建,则需要NPM 6.4.1或更高。
const { createCanvas , loadImage } = require ( 'canvas' )
const canvas = createCanvas ( 200 , 200 )
const ctx = canvas . getContext ( '2d' )
// Write "Awesome!"
ctx . font = '30px Impact'
ctx . rotate ( 0.1 )
ctx . fillText ( 'Awesome!' , 50 , 100 )
// Draw line under text
var text = ctx . measureText ( 'Awesome!' )
ctx . strokeStyle = 'rgba(0,0,0,0.5)'
ctx . beginPath ( )
ctx . lineTo ( 50 , 102 )
ctx . lineTo ( 50 + text . width , 102 )
ctx . stroke ( )
// Draw cat with lime helmet
loadImage ( 'examples/images/lime-cat.jpg' ) . then ( ( image ) => {
ctx . drawImage ( image , 50 , 0 , 70 , 70 )
console . log ( '<img src="' + canvas . toDataURL ( ) + '" />' )
} )
请参阅ChangElog以获取从1.x升级到2.x的指南。
有关版本1.x文档,请参见V1.x分支。
该项目是Web Canvas API的实现,并尽可能地实现API。有关API文档,请访问Mozilla Web Canvas API。 (请参阅当前API合规性的兼容性状态。)下面记录了所有实用程序方法和非标准API。
createCanvas ( width : number , height : number , type ?: 'PDF' | 'SVG' ) = > Canvas
创建一个画布实例。此方法在没有帆布构造函数的Node.js和Web浏览器中起作用。 (有关在浏览器中运行的实现,请参见browser.js
。)
const { createCanvas } = require ( 'canvas' )
const mycanvas = createCanvas ( 200 , 200 )
const myPDFcanvas = createCanvas ( 600 , 800 , 'pdf' ) // see "PDF Support" section
createImageData ( width : number , height : number ) = > ImageData createImageData ( data : Uint8ClampedArray , width : number , height ?: number ) = > ImageData // for alternative pixel formats: createImageData ( data : Uint16Array , width : number , height ?: number ) = > ImageData
创建一个Imagedata实例。此方法在Node.js和Web浏览器中都起作用。
const { createImageData } = require ( 'canvas' )
const width = 20 , height = 20
const arraySize = width * height * 4
const mydata = createImageData ( new Uint8ClampedArray ( arraySize ) , width )
loadImage ( ) = > Promise < Image >
加载图像的便利方法。此方法在Node.js和Web浏览器中都起作用。
const { loadImage } = require ( 'canvas' )
const myimg = loadImage ( 'http://server.com/image.png' )
myimg . then ( ( ) => {
// do something with image
} ) . catch ( err => {
console . log ( 'oh no!' , err )
} )
// or with async/await:
const myimg = await loadImage ( 'http://server.com/image.png' )
// do something with image
registerFont ( path : string , { family : string , weight ?: string , style ?: string } ) = > void
要使用未安装为系统字体的字体文件,请使用registerFont()
在画布上注册字体。这必须在创建画布之前完成。
const { registerFont , createCanvas } = require ( 'canvas' )
registerFont ( 'comicsans.ttf' , { family : 'Comic Sans' } )
const canvas = createCanvas ( 500 , 500 )
const ctx = canvas . getContext ( '2d' )
ctx . font = '12px "Comic Sans"'
ctx . fillText ( 'Everyone hates this font :(' , 250 , 10 )
第二个参数是一个对象,其属性类似于@font-face
规则中指定的CSS属性。您必须至少指定family
。 weight
和style
是可选的,默认为'normal'
。
deregisterAllFonts ( ) = > void
使用deregisterAllFonts
来解开以前注册的所有字体。当您要删除所有注册字体时,例如在测试中使用帆布时,此方法很有用
const { registerFont , createCanvas , deregisterAllFonts } = require ( 'canvas' )
describe ( 'text rendering' , ( ) => {
afterEach ( ( ) => {
deregisterAllFonts ( ) ;
} )
it ( 'should render text with Comic Sans' , ( ) => {
registerFont ( 'comicsans.ttf' , { family : 'Comic Sans' } )
const canvas = createCanvas ( 500 , 500 )
const ctx = canvas . getContext ( '2d' )
ctx . font = '12px "Comic Sans"'
ctx . fillText ( 'Everyone loves this font :)' , 250 , 10 )
// assertScreenshot()
} )
} )
img . src : string | Buffer
与浏览器一样,可以将img.src
设置为data:
URI或远程URL。此外,Node-Canvas允许将src
设置为本地文件路径或Buffer
实例。
const { Image } = require ( 'canvas' )
// From a buffer:
fs . readFile ( 'images/squid.png' , ( err , squid ) => {
if ( err ) throw err
const img = new Image ( )
img . onload = ( ) => ctx . drawImage ( img , 0 , 0 )
img . onerror = err => { throw err }
img . src = squid
} )
// From a local file path:
const img = new Image ( )
img . onload = ( ) => ctx . drawImage ( img , 0 , 0 )
img . onerror = err => { throw err }
img . src = 'images/squid.png'
// From a remote URL:
img . src = 'http://picsum.photos/200/300'
// ... as above
// From a `data:` URI:
img . src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='
// ... as above
注意:在某些情况下, img.src=
当前是同步的。但是,您应该始终使用img.onload
和img.onerror
,因为我们打算使img.src=
始终像浏览器中的同步。参见#1007。
img . dataMode : number
仅适用于绘制的JPEG图像,仅适用于PDF画布。
设置img.dataMode = Image.MODE_MIME
或Image.MODE_MIME|Image.MODE_IMAGE
启用图像的模仿数据跟踪。当跟踪MIME数据时,PDF画布可以将JPEG直接嵌入输出中,而不是重新编码为PNG。这可以大大减少文件化并加快渲染加速。
const { Image , createCanvas } = require ( 'canvas' )
const canvas = createCanvas ( w , h , 'pdf' )
const img = new Image ( )
img . dataMode = Image . MODE_IMAGE // Only image data tracked
img . dataMode = Image . MODE_MIME // Only mime data tracked
img . dataMode = Image . MODE_MIME | Image . MODE_IMAGE // Both are tracked
如果使用非PDF画布,则必须跟踪图像数据;否则,输出将是垃圾。
除非您生成PDF,否则启用MIME数据跟踪没有任何好处(仅放慢速度)。
canvas . toBuffer ( ( err : Error | null , result : Buffer ) => void , mimeType ?: string , config ?: any ) = > void canvas . toBuffer ( mimeType ?: string , config ?: any ) = > Buffer
创建代表画布中包含的图像Buffer
对象。
raw
或PDF或SVG画布。image/png
, image/jpeg
(如果构建了jpeg支持的节点 - 滴定),则raw
(大多数(大多数)系统中的BGRA订单中的未编码数据,大型系统上的ARGB上的ARGB; ), application/pdf
(用于PDF画布)和image/svg+xml
(用于SVG画布)。默认图像画布的image/png
,或PDF或SVG画布的相应类型。对于image/jpeg
,指定质量的对象(0至1),如果应使用渐进压缩和/或应使用色度亚采样: {quality: 0.75, progressive: false, chromaSubsampling: true}
。所有属性都是可选的。
对于image/png
,指定ZLIB压缩级别(0到9之间)的对象,压缩过滤器,调色板(仅索引PNG),背景调色板索引(仅索引PNG)和/或分辨率(或/或分辨率( PPI): {compressionLevel: 6, filters: canvas.PNG_ALL_FILTERS, palette: undefined, backgroundIndex: 0, resolution: undefined}
。所有属性都是可选的。
请注意,PNG格式编码分辨率每米的像素分辨率,因此,如果指定96
,则文件将编码3780 ppm(〜96.01 ppi)。默认情况下,该分辨率是不确定的,无法匹配常见的浏览器行为。
对于application/pdf
,指定可选文档元数据的对象: {title: string, author: string, subject: string, keywords: string, creator: string, creationDate: Date, modDate: Date}
。除creationDate
外,所有属性都是可选的,默认为undefined
,默认为当前日期。添加元数据需要开罗1.16.0或更高版本。
有关这些属性的描述,请参见PDF 32000-1:2008的第550页。
请注意,没有用于keywords
的标准分离器。建议使用空间,因为其他应用程序通常会使用它,如果使用逗号或半隆,开罗将在引号中附上关键字列表。
返回值
如果没有提供回调,则为Buffer
。如果提供回调,则无。
// Default: buf contains a PNG-encoded image
const buf = canvas . toBuffer ( )
// PNG-encoded, zlib compression level 3 for faster compression but bigger files, no filtering
const buf2 = canvas . toBuffer ( 'image/png' , { compressionLevel : 3 , filters : canvas . PNG_FILTER_NONE } )
// JPEG-encoded, 50% quality
const buf3 = canvas . toBuffer ( 'image/jpeg' , { quality : 0.5 } )
// Asynchronous PNG
canvas . toBuffer ( ( err , buf ) => {
if ( err ) throw err // encoding failed
// buf is PNG-encoded image
} )
canvas . toBuffer ( ( err , buf ) => {
if ( err ) throw err // encoding failed
// buf is JPEG-encoded image at 95% quality
} , 'image/jpeg' , { quality : 0.95 } )
// BGRA pixel values, native-endian
const buf4 = canvas . toBuffer ( 'raw' )
const { stride , width } = canvas
// In memory, this is `canvas.height * canvas.stride` bytes long.
// The top row of pixels, in BGRA order on little-endian hardware,
// left-to-right, is:
const topPixelsBGRALeftToRight = buf4 . slice ( 0 , width * 4 )
// And the third row is:
const row3 = buf4 . slice ( 2 * stride , 2 * stride + width * 4 )
// SVG and PDF canvases
const myCanvas = createCanvas ( w , h , 'pdf' )
myCanvas . toBuffer ( ) // returns a buffer containing a PDF-encoded canvas
// With optional metadata:
myCanvas . toBuffer ( 'application/pdf' , {
title : 'my picture' ,
keywords : 'node.js demo cairo' ,
creationDate : new Date ( )
} )
canvas . createPNGStream ( config ?: any ) = > ReadableStream
创建一个发出PNG编码数据的ReadableStream
。
config
一个指定ZLIB压缩级别(0到9之间),压缩过滤器,调色板{compressionLevel: 6, filters: canvas.PNG_ALL_FILTERS, palette: undefined, backgroundIndex: 0, resolution: undefined}
仅索引PNG)和/或背景调色板索引(仅索引PNG)的对象: {compressionLevel: 6, filters: canvas.PNG_ALL_FILTERS, palette: undefined, backgroundIndex: 0, resolution: undefined}
所有属性都是可选的。 const fs = require ( 'fs' )
const out = fs . createWriteStream ( __dirname + '/test.png' )
const stream = canvas . createPNGStream ( )
stream . pipe ( out )
out . on ( 'finish' , ( ) => console . log ( 'The PNG file was created.' ) )
要使用pixelFormat: 'A8'
或'A1'
编码从画布中编码索引的png,请提供一个选项对象:
const palette = new Uint8ClampedArray ( [
//r g b a
0 , 50 , 50 , 255 , // index 1
10 , 90 , 90 , 255 , // index 2
127 , 127 , 255 , 255
// ...
] )
canvas . createPNGStream ( {
palette : palette ,
backgroundIndex : 0 // optional, defaults to 0
} )
canvas . createJPEGStream ( config ?: any ) = > ReadableStream
创建一个排放JPEG编码数据的ReadableStream
。
注意:目前, createJPEGStream()
在引擎盖下是同步的。也就是说,它在主线程中运行,而不是在libuv threadpool中运行。
config
一个指定质量的对象(0至1),如果应使用渐进压缩,并且/或是否应使用Chroma子采样: {quality: 0.75, progressive: false, chromaSubsampling: true}
。所有属性都是可选的。 const fs = require ( 'fs' )
const out = fs . createWriteStream ( __dirname + '/test.jpeg' )
const stream = canvas . createJPEGStream ( )
stream . pipe ( out )
out . on ( 'finish' , ( ) => console . log ( 'The JPEG file was created.' ) )
// Disable 2x2 chromaSubsampling for deeper colors and use a higher quality
const stream = canvas . createJPEGStream ( {
quality : 0.95 ,
chromaSubsampling : false
} )
canvas . createPDFStream ( config ?: any ) = > ReadableStream
config
一个指定可选文档元数据的对象: {title: string, author: string, subject: string, keywords: string, creator: string, creationDate: Date, modDate: Date}
。有关更多信息,请参见toBuffer()
。添加元数据需要开罗1.16.0或更高版本。仅适用于PDF画布。创建一个发出编码PDF的ReadableStream
。 canvas.toBuffer()
还会产生编码的PDF,但是createPDFStream()
可用于减少内存使用情况。
这是标准API,但支持了几个非标准呼叫。支持电话的完整列表是:
dataUrl = canvas . toDataURL ( ) // defaults to PNG
dataUrl = canvas . toDataURL ( 'image/png' )
dataUrl = canvas . toDataURL ( 'image/jpeg' )
dataUrl = canvas . toDataURL ( 'image/jpeg' , quality ) // quality from 0 to 1
canvas . toDataURL ( ( err , png ) => { } ) // defaults to PNG
canvas . toDataURL ( 'image/png' , ( err , png ) => { } )
canvas . toDataURL ( 'image/jpeg' , ( err , jpeg ) => { } ) // sync JPEG is not supported
canvas . toDataURL ( 'image/jpeg' , { ... opts } , ( err , jpeg ) => { } ) // see Canvas#createJPEGStream for valid options
canvas . toDataURL ( 'image/jpeg' , quality , ( err , jpeg ) => { } ) // spec-following; quality from 0 to 1
context . patternQuality : 'fast' | 'good' | 'best' | 'nearest' | 'bilinear'
默认为'good'
。影响模式(梯度,图像等)呈现质量。
context . quality : 'fast' | 'good' | 'best' | 'nearest' | 'bilinear'
默认为'good'
。像patternQuality
一样,但适用于影响模式不仅仅是影响模式的转换。
context . textDrawingMode : 'path' | 'glyph'
默认为'path'
。效果取决于画布类型:
标准(图像) glyph
和path
均导致栅格化文本。字形模式比path
快,但可能导致较低质量的文本,尤其是在旋转或翻译时。
PDF glyph
将文本而不是路径嵌入PDF中。这是更快的编码,更快地使用PDF查看器打开,产生较小的文件大小并使文本可选。渲染字形所需的字体子集将嵌入PDF中。这通常是您要与PDF画布一起使用的模式。
SVG glyph
不会像人们期望的那样引起<text>
元素(开罗错误)。相反, glyph
将为每个字形创建一个带有<defs>
<symbol>
的部分,然后通过<use>
元素重复使用这些字形。 path
模式为每个文本字符串创建<path>
元素。 glyph
模式更快,产生较小的文件大小。
在glyph
模式下, ctx.strokeText()
和ctx.fillText()
表现相同(除了使用中风和填充样式外,除了分别使用)。
此属性在保存/还原中作为画布状态的一部分跟踪。
除了画布规范定义的所有标准全局复合操作外,还可以使用“饱和”操作。
context . antialias : 'default' | 'none' | 'gray' | 'subpixel'
设置反缩放模式。
节点 - 玻璃体可以创建PDF文档而不是图像。在创建画布时,必须设置帆布类型,如下所示:
const canvas = createCanvas ( 200 , 500 , 'pdf' )
然后,可以使用另一种方法.addPage()
来创建多页PDF:
// On first page
ctx . font = '22px Helvetica'
ctx . fillText ( 'Hello World' , 50 , 80 )
ctx . addPage ( )
// Now on second page
ctx . font = '22px Helvetica'
ctx . fillText ( 'Hello World 2' , 50 , 80 )
canvas . toBuffer ( ) // returns a PDF file
canvas . createPDFStream ( ) // returns a ReadableStream that emits a PDF
// With optional document metadata (requires Cairo 1.16.0):
canvas . toBuffer ( 'application/pdf' , {
title : 'my picture' ,
keywords : 'node.js demo cairo' ,
creationDate : new Date ( )
} )
也可以通过将width
和height
传递到.addPage()
方法来创建不同大小的页面:
ctx . font = '22px Helvetica'
ctx . fillText ( 'Hello World' , 50 , 80 )
ctx . addPage ( 400 , 800 )
ctx . fillText ( 'Hello World 2' , 50 , 80 )
参见:
节点 - 玻璃体可以创建SVG文档而不是图像。在创建画布时,必须设置帆布类型,如下所示:
const canvas = createCanvas ( 200 , 500 , 'svg' )
// Use the normal primitives.
fs . writeFileSync ( 'out.svg' , canvas . toBuffer ( ) )
如果安装了节点 - 棒棒时可用的Libersvg,则节点canvas可以将SVG图像呈现到您的画布上下文。当前,这是通过栅格化SVG图像(即将SVG图像绘制到SVG画布上不会保留SVG数据的)来起作用。
const img = new Image ( )
img . onload = ( ) => ctx . drawImage ( img , 0 , 0 )
img . onerror = err => { throw err }
img . src = './example.svg'
节点 - 胶囊对其他像素格式具有实验支持,大致遵循帆布颜色空间建议。
const canvas = createCanvas ( 200 , 200 )
const ctx = canvas . getContext ( '2d' , { pixelFormat : 'A8' } )
默认情况下,画布以RGBA32
格式创建,该格式与本机HTML画布行为相对应。每个像素为32位。涉及像素数据( getImageData
, putImageData
)的JavaScript API将颜色存储在{红色,绿色,蓝色,蓝色,alpha}的顺序中,而无需alpha pre-Myliplication。 (C ++ API将颜色以{alpha,red,green,blue}顺序存储在本机式订购中,并使用alpha pre-multiplication。)
这些其他像素格式具有实验支持:
RGB24
像RGBA32
一样,但是8个alpha位总是不透明的。如果alpha
上下文属性设置为false(即canvas.getContext('2d', {alpha: false})
),则始终使用此格式。这种格式可以比RGBA32
更快,因为无需计算透明度。A8
每个像素为8位。这种格式可以用于创建灰度图像(将每个字节视为alpha值),也可以用于创建索引的png(将每个字节视为调色板索引)(请参阅使用fillStyle
和使用imageData
示例的示例的示例)。RGB16_565
每个像素为16位,上5位红色,中间6位绿色,下部5位的蓝色在本机平台的底线中。一些硬件设备和框架缓冲区使用此格式。请注意,PNG不支持这种格式;创建PNG时,图像将转换为24位RGB。因此,这种格式是生成PNG的次优。 ImageData
实例此模式使用Uint16Array
而不是Uint8ClampedArray
。A1
每个像素为1位,然后将像素包装成32位的数量。钻头的订购与平台的端度相匹配:在小型机器上,第一个像素是最不重要的位。这种格式可用于创建单色图像。对此格式的支持不完整,请参见下面的注释。RGB30
每个像素为30位,上部10位为红色,中间10位为绿色,下部为蓝色。(需要开罗1.12或更高版本。笔记和注意事项:
使用非默认格式可能会影响涉及像素数据的API的行为:
context2d.createImageData
返回的数组的大小取决于上面描述的基础图像数据格式的每个像素的位数。context2d.getImageData
根据上述描述,返回的数组格式取决于基础图像模式。请注意平台端度,可以使用node.js的os.endianness()
函数确定。context2d.putImageData
。 A1
和RGB30
尚未支持getImageData
或putImageData
。有使用这些格式的用例和/或意见吗?打开一个问题,让我们知道! (请参阅#935。)
带有阴影模糊的A1
, A8
, RGB30
和RGB16_565
可能会崩溃或无法正确渲染。
ImageData(width, height)
和ImageData(Uint8ClampedArray, width)
构造函数假设每个像素为4个字节。要创建一个具有不同数量的字节的ImageData
实例,请使用new ImageData(new Uint8ClampedArray(size), width, height)
或new ImageData(new Uint16ClampedArray(size), width, height)
。
首先确保您已经构建了最新版本。获取所需的所有深度(请参阅上面的编译),然后运行:
npm install --build-from-source
对于视觉测试: npm run test-server
,并将浏览器指向http:// localhost:4000。
对于单元测试: npm run test
。
基准测试在benchmarks
目录中。
examples
目录中的示例行。大多数生产同名的PNG图像,而其他诸如Live-clock.js之类的其他图像启动了浏览器中要查看的HTTP服务器。
(麻省理工学院许可证)
版权所有(C)2010 Learn Boost和贡献者<[email protected]>
版权(C)2014 Automattic,Inc和贡献者<[email protected]>
特此免费授予任何获得此软件副本和相关文档文件(“软件”)的人,以无限制处理该软件,包括无限制的使用权,复制,修改,修改,合并,发布,分发,分布和/或出售该软件的副本,并允许提供该软件的人,但要遵守以下条件:
上述版权通知和此许可通知应包含在软件的所有副本或大量部分中。
该软件是“按原样”提供的,没有任何形式的明示或暗示保证,包括但不限于适销性,适合特定目的和非侵害的保证。在任何情况下,作者或版权持有人均不应对任何索赔,损害赔偿或其他责任责任,无论是在合同,侵权或其他方面的诉讼中,与软件或与软件或使用或其他交易有关的诉讼或其他责任软件。
请参阅许可证