html-to-image
✂️ 使用 HTML5 画布和 SVG 从 DOM 节点生成图像。
从 分叉dom-to-image 具有更易于维护的代码和一些新功能。
< /a>
Install
npm install --save html-to-image
Usage
/* ES6 */
import * as htmlToImage from 'html-to-image';
import { toPng, toJpeg, toBlob, toPixelData, toSvg } from 'html-to-image';
/* ES5 */
var htmlToImage = require('html-to-image');
所有顶级函数都接受 DOM 节点和渲染选项,并返回一个使用相应数据 URL 实现的承诺:
继续以下示例。
toPng
Get a PNG image base64-encoded data URL and display it right on:
var node = document.getElementById('my-node');
htmlToImage.toPng(node)
.then(function (dataUrl) {
var img = new Image();
img.src = dataUrl;
document.body.appendChild(img);
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
Get a PNG image base64-encoded data URL and download it (using 下载):
htmlToImage.toPng(document.getElementById('my-node'))
.then(function (dataUrl) {
download(dataUrl, 'my-node.png');
});
toSvg
获取 SVG 数据 URL,但过滤掉所有
元素:
function filter (node) {
return (node.tagName !== 'i');
}
htmlToImage.toSvg(document.getElementById('my-node'), { filter: filter })
.then(function (dataUrl) {
/* do something */
});
toJpeg
保存并下载压缩的 JPEG 图像:
htmlToImage.toJpeg(document.getElementById('my-node'), { quality: 0.95 })
.then(function (dataUrl) {
var link = document.createElement('a');
link.download = 'my-image-name.jpeg';
link.href = dataUrl;
link.click();
});
toBlob
获取 PNG 图像 blob 并下载它(使用 FileSaver):
htmlToImage.toBlob(document.getElementById('my-node'))
.then(function (blob) {
if (window.saveAs) {
window.saveAs(blob, 'my-node.png');
} else {
FileSaver.saveAs(blob, 'my-node.png');
}
});
toCanvas
获取一个 HTMLCanvasElement,并立即显示它:
htmlToImage.toCanvas(document.getElementById('my-node'))
.then(function (canvas) {
document.body.appendChild(canvas);
});
toPixelData
获取原始像素数据作为 Uint8Array 每 4 个数组元素代表一个像素的 RGBA 数据:
var node = document.getElementById('my-node');
htmlToImage.toPixelData(node)
.then(function (pixels) {
for (var y = 0; y < node.scrollHeight; ++y) {
for (var x = 0; x < node.scrollWidth; ++x) {
pixelAtXYOffset = (4 * y * node.scrollHeight) + (4 * x);
/* pixelAtXY is a Uint8Array[4] containing RGBA values of the pixel at (x, y) in the range 0..255 */
pixelAtXY = pixels.slice(pixelAtXYOffset, pixelAtXYOffset + 4);
}
}
});
React
import React, { useCallback, useRef } from 'react';
import { toPng } from 'html-to-image';
const App: React.FC = () => {
const ref = useRef<HTMLDivElement>(null)
const onButtonClick = useCallback(() => {
if (ref.current === null) {
return
}
toPng(ref.current, { cacheBust: true, })
.then((dataUrl) => {
const link = document.createElement('a')
link.download = 'my-image-name.png'
link.href = dataUrl
link.click()
})
.catch((err) => {
console.log(err)
})
}, [ref])
return (
<>
<div ref={ref}>
{/* DOM nodes you want to convert to PNG */}
</div>
<button onClick={onButtonClick}>Click me</button>
</>
)
}
Options
filter
(domNode: HTMLElement) => boolean
一个以 DOM 节点为参数的函数。 如果传递的节点应包含在输出中,则应返回 true。 排除节点意味着也排除它的子节点。
您可以为每个图像功能添加过滤器。 例如,
const filter = (node)=>{
const exclusionClasses = ['remove-me', 'secret-div'];
return !exclusionClasses.some(classname=>node.classList.includes(classname));
}
htmlToImage.toJpeg(node, { quality: 0.95, filter: filter});
或未
htmlToImage.toPng(node, {filter:filter})
在根节点上调用。
backgroundColor
背景颜色的字符串值,任何有效的 CSS 颜色值。
width, height
渲染前应用于节点的宽度和高度(以像素为单位)。
canvasWidth, canvasHeight
允许缩放画布的大小,包括内部元素到给定的宽度和高度(以像素为单位)。
style
一个对象,其属性在渲染之前被复制到节点的样式。 您可能需要查看此参考以了解 CSS 属性的 JavaScript 名称。
quality
0
和 1
之间的数字,表示 JPEG 图像的图像质量(例如 0.92
=> 92%
) .
默认为 1.0
(100%
)
cacheBust
设置为 true 以将当前时间作为查询字符串附加到 URL 请求以启用缓存清除。
默认为 false
imagePlaceholder
获取图像失败时将使用的占位符图像的数据 URL。
默认为空字符串,将为失败的图像呈现空白区域。
pixelRatio
拍摄图像的像素比。 默认使用设备的实际像素比。 将 1
设置为
用作图像的初始比例 1
。
字体嵌入所需的格式。 当 webfont 提供者时,这是一个有用的优化
为 CSS 中的字体指定几种不同的格式,例如:
@font-face {
name: 'proxima-nova';
src: url("...") format("woff2"), url("...") format("woff"), url("...") format("opentype");
}
不是嵌入每种格式,而是丢弃除指定格式之外的所有格式。 如果
未指定此选项则将下载并嵌入所有格式。
fontEmbedCSS
提供后,该库将跳过在 CSS 中解析和嵌入 webfont URL 的过程,
而不是使用这个值。 这在与 getFontEmbedCSS()
结合使用以仅执行
在对库函数的多次调用中嵌入一次过程。
const fontEmbedCss = await htmlToImage.getFontEmbedCSS(element1);
html2Image.toSVG(element1, { fontEmbedCss });
html2Image.toSVG(element2, { fontEmbedCss });
skipAutoScale
提供后,库将跳过将超大 dom 缩放到画布对象的过程。
如果设置为 true
并且您正在导出非常大的图像,则可能会丢失部分图像。
默认为 false
type
表示图像格式的字符串。 默认类型是image/png; 如果不支持给定类型,也会使用该类型。
提供时,toCanvas 函数将返回匹配给定图像类型和质量的 blob。
默认为 image/png
Browsers
当前仅使用标准库,但请确保您的浏览器支持:
它在最新的 Chrome 和 Firefox(撰写本文时分别为 49 和 45)上进行了测试,Chrome 的性能明显更好在大型 DOM 树上,可能是因为它对 SVG 的支持性能更高,而且它支持 CSSStyleDeclaration.cssText
属性。
Internet Explorer 不受(也不会)支持,因为它不支持 SVG
标签。
Safari 不受支持,因为它使用
标签上更严格的安全模型。 建议的解决方法是使用 toSvg
并在服务器上呈现。
How it works
可能有一天会存在(或者可能已经存在?)一种将部分 HTML 导出到图像(和那么这个脚本只能作为我为了完成如此明显的事情而必须跳过的所有箍的证据)但到目前为止我还没有找到一个。
该库使用 SVG 的一项功能,允许在
标签内包含任意 HTML 内容。 因此,为了为您呈现该 DOM 节点,需要执行以下步骤:
- Clone the original DOM node recursively
- Compute the style for the node and each sub-node and copy it to corresponding clone
- and don't forget to recreate pseudo-elements, as they are not cloned in any way, of course
- Embed web fonts
- find all the
@font-face
declarations that might represent web fonts
- parse file URLs, download corresponding files
- base64-encode and inline content as dataURLs
- concatenate all the processed CSS rules and put them into one
<style>
element, then attach it to the clone
- Embed images
- embed image URLs in
<img>
elements
- inline images used in
background
CSS property, in a fashion similar to fonts
- Serialize the cloned node to XML
- Wrap XML into the
<foreignObject>
tag, then into the SVG, then make it a data URL
- Optionally, to get PNG content or raw pixel data as a Uint8Array, create an Image element with the SVG as a source, and render it on an off-screen canvas, that you have also created, then read the content from the canvas
- Done!
Things to watch out for
- If the DOM node you want to render includes a
<canvas>
element with something drawn on it, it should be handled fine, unless the canvas is tainted - in this case rendering will rather not succeed.
- Rendering will failed on huge DOM due to the dataURI limit varies.
Contributing
请告诉我们如何提供帮助。 请先查看问题以获得错误报告或建议。
要成为贡献者,请遵循我们的贡献指南。
html-to-image
✂️ Generates an image from a DOM node using HTML5 canvas and SVG.
Fork from dom-to-image with more maintainable code and some new features.
Install
npm install --save html-to-image
Usage
/* ES6 */
import * as htmlToImage from 'html-to-image';
import { toPng, toJpeg, toBlob, toPixelData, toSvg } from 'html-to-image';
/* ES5 */
var htmlToImage = require('html-to-image');
All the top level functions accept DOM node and rendering options, and return a promise fulfilled with corresponding dataURL:
Go with the following examples.
toPng
Get a PNG image base64-encoded data URL and display it right away:
var node = document.getElementById('my-node');
htmlToImage.toPng(node)
.then(function (dataUrl) {
var img = new Image();
img.src = dataUrl;
document.body.appendChild(img);
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
Get a PNG image base64-encoded data URL and download it (using download):
htmlToImage.toPng(document.getElementById('my-node'))
.then(function (dataUrl) {
download(dataUrl, 'my-node.png');
});
toSvg
Get an SVG data URL, but filter out all the <i>
elements:
function filter (node) {
return (node.tagName !== 'i');
}
htmlToImage.toSvg(document.getElementById('my-node'), { filter: filter })
.then(function (dataUrl) {
/* do something */
});
toJpeg
Save and download a compressed JPEG image:
htmlToImage.toJpeg(document.getElementById('my-node'), { quality: 0.95 })
.then(function (dataUrl) {
var link = document.createElement('a');
link.download = 'my-image-name.jpeg';
link.href = dataUrl;
link.click();
});
toBlob
Get a PNG image blob and download it (using FileSaver):
htmlToImage.toBlob(document.getElementById('my-node'))
.then(function (blob) {
if (window.saveAs) {
window.saveAs(blob, 'my-node.png');
} else {
FileSaver.saveAs(blob, 'my-node.png');
}
});
toCanvas
Get a HTMLCanvasElement, and display it right away:
htmlToImage.toCanvas(document.getElementById('my-node'))
.then(function (canvas) {
document.body.appendChild(canvas);
});
toPixelData
Get the raw pixel data as a Uint8Array with every 4 array elements representing the RGBA data of a pixel:
var node = document.getElementById('my-node');
htmlToImage.toPixelData(node)
.then(function (pixels) {
for (var y = 0; y < node.scrollHeight; ++y) {
for (var x = 0; x < node.scrollWidth; ++x) {
pixelAtXYOffset = (4 * y * node.scrollHeight) + (4 * x);
/* pixelAtXY is a Uint8Array[4] containing RGBA values of the pixel at (x, y) in the range 0..255 */
pixelAtXY = pixels.slice(pixelAtXYOffset, pixelAtXYOffset + 4);
}
}
});
React
import React, { useCallback, useRef } from 'react';
import { toPng } from 'html-to-image';
const App: React.FC = () => {
const ref = useRef<HTMLDivElement>(null)
const onButtonClick = useCallback(() => {
if (ref.current === null) {
return
}
toPng(ref.current, { cacheBust: true, })
.then((dataUrl) => {
const link = document.createElement('a')
link.download = 'my-image-name.png'
link.href = dataUrl
link.click()
})
.catch((err) => {
console.log(err)
})
}, [ref])
return (
<>
<div ref={ref}>
{/* DOM nodes you want to convert to PNG */}
</div>
<button onClick={onButtonClick}>Click me</button>
</>
)
}
Options
filter
(domNode: HTMLElement) => boolean
A function taking DOM node as argument. Should return true if passed node should be included in the output. Excluding node means excluding it's children as well.
You can add filter to every image function. For example,
const filter = (node)=>{
const exclusionClasses = ['remove-me', 'secret-div'];
return !exclusionClasses.some(classname=>node.classList.includes(classname));
}
htmlToImage.toJpeg(node, { quality: 0.95, filter: filter});
or
htmlToImage.toPng(node, {filter:filter})
Not called on the root node.
backgroundColor
A string value for the background color, any valid CSS color value.
width, height
Width and height in pixels to be applied to node before rendering.
canvasWidth, canvasHeight
Allows to scale the canva's size including the elements inside to a given width and height (in pixels).
style
An object whose properties to be copied to node's style before rendering. You might want to check this reference for JavaScript names of CSS properties.
quality
A number between 0
and 1
indicating image quality (e.g. 0.92
=> 92%
) of the JPEG image.
Defaults to 1.0
(100%
)
cacheBust
Set to true to append the current time as a query string to URL requests to enable cache busting.
Defaults to false
imagePlaceholder
A data URL for a placeholder image that will be used when fetching an image fails.
Defaults to an empty string and will render empty areas for failed images.
pixelRatio
The pixel ratio of the captured image. Default use the actual pixel ratio of the device. Set 1
to
use as initial-scale 1
for the image.
The format required for font embedding. This is a useful optimisation when a webfont provider
specifies several different formats for fonts in the CSS, for example:
@font-face {
name: 'proxima-nova';
src: url("...") format("woff2"), url("...") format("woff"), url("...") format("opentype");
}
Instead of embedding each format, all formats other than the one specified will be discarded. If
this option is not specified then all formats will be downloaded and embedded.
fontEmbedCSS
When supplied, the library will skip the process of parsing and embedding webfont URLs in CSS,
instead using this value. This is useful when combined with getFontEmbedCSS()
to only perform the
embedding process a single time across multiple calls to library functions.
const fontEmbedCss = await htmlToImage.getFontEmbedCSS(element1);
html2Image.toSVG(element1, { fontEmbedCss });
html2Image.toSVG(element2, { fontEmbedCss });
skipAutoScale
When supplied, the library will skip the process of scaling extra large doms into the canvas object.
You may experience loss of parts of the image if set to true
and you are exporting a very large image.
Defaults to false
type
A string indicating the image format. The default type is image/png; that type is also used if the given type isn't supported.
When supplied, the toCanvas function will return a blob matching the given image type and quality.
Defaults to image/png
Browsers
Only standard lib is currently used, but make sure your browser supports:
It's tested on latest Chrome and Firefox (49 and 45 respectively at the time of writing), with Chrome performing significantly better on big DOM trees, possibly due to it's more performant SVG support, and the fact that it supports CSSStyleDeclaration.cssText
property.
Internet Explorer is not (and will not be) supported, as it does not support SVG <foreignObject>
tag.
Safari is not supported, as it uses a stricter security model on <foreignObject>
tag. Suggested workaround is to use toSvg
and render on the server.
How it works
There might some day exist (or maybe already exists?) a simple and standard way of exporting parts of the HTML to image (and then this script can only serve as an evidence of all the hoops I had to jump through in order to get such obvious thing done) but I haven't found one so far.
This library uses a feature of SVG that allows having arbitrary HTML content inside of the <foreignObject>
tag. So, in order to render that DOM node for you, following steps are taken:
- Clone the original DOM node recursively
- Compute the style for the node and each sub-node and copy it to corresponding clone
- and don't forget to recreate pseudo-elements, as they are not cloned in any way, of course
- Embed web fonts
- find all the
@font-face
declarations that might represent web fonts
- parse file URLs, download corresponding files
- base64-encode and inline content as dataURLs
- concatenate all the processed CSS rules and put them into one
<style>
element, then attach it to the clone
- Embed images
- embed image URLs in
<img>
elements
- inline images used in
background
CSS property, in a fashion similar to fonts
- Serialize the cloned node to XML
- Wrap XML into the
<foreignObject>
tag, then into the SVG, then make it a data URL
- Optionally, to get PNG content or raw pixel data as a Uint8Array, create an Image element with the SVG as a source, and render it on an off-screen canvas, that you have also created, then read the content from the canvas
- Done!
Things to watch out for
- If the DOM node you want to render includes a
<canvas>
element with something drawn on it, it should be handled fine, unless the canvas is tainted - in this case rendering will rather not succeed.
- Rendering will failed on huge DOM due to the dataURI limit varies.
Contributing
Please let us know how can we help. Do check out issues for bug reports or suggestions first.
To become a contributor, please follow our contributing guide.