Generates an image from a DOM node using HTML5 canvas

Overview

DOM to Image

Build Status

What is it

dom-to-image is a library which can turn arbitrary DOM node into a vector (SVG) or raster (PNG or JPEG) image, written in JavaScript. It's based on domvas by Paul Bakaus and has been completely rewritten, with some bugs fixed and some new features (like web font and image support) added.

Installation

NPM

npm install dom-to-image

Then load

/* in ES 6 */
import domtoimage from 'dom-to-image';
/* in ES 5 */
var domtoimage = require('dom-to-image');

Bower

bower install dom-to-image

Include either src/dom-to-image.js or dist/dom-to-image.min.js in your page and it will make the domtoimage variable available in the global scope.

<script src="path/to/dom-to-image.min.js" />
<script>
  domtoimage.toPng(node)
  //...
</script>

Usage

All the top level functions accept DOM node and rendering options, and return promises, which are fulfilled with corresponding data URLs.
Get a PNG image base64-encoded data URL and display right away:

var node = document.getElementById('my-node');

domtoimage.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 blob and download it (using FileSaver, for example):

domtoimage.toBlob(document.getElementById('my-node'))
    .then(function (blob) {
        window.saveAs(blob, 'my-node.png');
    });

Save and download a compressed JPEG image:

domtoimage.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();
    });

Get an SVG data URL, but filter out all the <i> elements:

function filter (node) {
    return (node.tagName !== 'i');
}

domtoimage.toSvg(document.getElementById('my-node'), {filter: filter})
    .then(function (dataUrl) {
        /* do something */
    });

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');

domtoimage.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);
          }
        }
    });

All the functions under impl are not public API and are exposed only for unit testing.


Rendering options

filter

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). Not called on the root node.

bgcolor

A string value for the background color, any valid CSS color value.

height, width

Height and width in pixels to be applied to node before rendering.

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 undefined and will throw an error on failed images

Browsers

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

Dependencies

Source

Only standard lib is currently used, but make sure your browser supports:

Tests

Most importantly, tests depend on:

  • js-imagediff, to compare rendered and control images

  • ocrad.js, for the parts when you can't compare images (due to the browser rendering differences) and just have to test whether the text is rendered

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:

  1. Clone the original DOM node recursively

  2. 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
  3. 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 data: URLs

    • concatenate all the processed CSS rules and put them into one <style> element, then attach it to the clone

  4. Embed images

    • embed image URLs in <img> elements

    • inline images used in background CSS property, in a fashion similar to fonts

  5. Serialize the cloned node to XML

  6. Wrap XML into the <foreignObject> tag, then into the SVG, then make it a data URL

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

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

  • at the time of writing, Firefox has a problem with some external stylesheets (see issue #13). In such case, the error will be caught and logged.

Authors

Anatolii Saienko, Paul Bakaus (original idea)

License

MIT

Comments
  • Doesn't working with Google Fonts

    Doesn't working with Google Fonts

    https://jsfiddle.net/3Lu1xpxh/

    It generates the DOM element without applying the element font as it's show. I'm not sure if there is limitation with some types of fonts or there are another way to apply the element font

    https://jsfiddle.net/3Lu1xpxh/

    opened by ralharabi 24
  • Specify output image dimensions

    Specify output image dimensions

    It would be extremely useful to be able to optionally specify the dimensions for the output image and have the image rendered at a higher resolution than the DOM element itself.

    This would have numerous uses but would be particularly useful for printing the image afterwards. Printing at 72dpi (screen resolution) is not advisable!

    One simple idea for making this happen is to scale the DOM element before rendering using the CSS *_zoom *_property or the CSS *_transform *_property. I attempted this but the bounding box for the element seems to remain the same, so while the elements do render larger, as expected, the image itself is cropped to the original size of the element, cutting out the bottom and right part of the element.

    enhancement 
    opened by cronoklee 22
  • Safari Support

    Safari Support

    I got Event error when I run it on Safari 8.0.7

    OOOOOOOPS, something went wrong! 
    Event
    bubbles: false
    cancelBubble: false
    cancelable: false
    clipboardData: undefined
    currentTarget: null
    defaultPrevented: false
    eventPhase: 0
    returnValue: true
    srcElement: null
    target: null
    timeStamp: 1459283334222
    type: "error"
    __proto__: EventPrototype
    

    the function I ran is like the following

    function () {
          domtoimage.toPng(document.querySelector('body'))
            .then(function (dataUrl) {
              var img = new Image();
              img.src = dataUrl;
              document.body.appendChild(img);
            })
            .catch(function (error) {
              console.error('OOOOOOOOPS, something went wrong!', error);
            });
        }
    
    opened by allenhwkim 17
  • Remote Images

    Remote Images

    Hi

    I've just started to use this library - very helpful.

    Rendering dom with some remote image sources in it. Getting:

    `XMLHttpRequest cannot load https://{bucket}.s3.amazonaws.com/uploads/North_face.jpg. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '{me}' is therefore not allowed access.

    I've checked the CORS settings on my bucket. All OK.

    Curl from the same terminal, 200 OK.

    Not quite sure where to go now. Where in the code do you set the request headers? Maybe that's where I'll start.

    Thanks

    Tom

    opened by tomgallagher 16
  • Mobile [object Event] Error

    Mobile [object Event] Error

    Use case: description, code

    Im using the plugin on Ionic framework. My app has a button to apply an image from the gallery into an

    But the plugin doesn't render it. With alert() I got this error:

    [object Event] Error

    Any image included on the app www/img folder can be rendered. I don't know how to workaround...

    https://jsfiddle.net/ojb1b31r/3/

    Expected behavior

    Load the gallery image into tag <img src

    Actual behavior (stack traces, console logs etc)

    Fire this error through alert()

    [object Event] Error

    Library version

    /*! dom-to-image 02-03-2016 */

    Browsers

    • [x ] Chrome 49+
    • [ ] Firefox 45+
    wontfix cannot reproduce 
    opened by rafaeldcastro 15
  • Current project status

    Current project status

    Hi, what is the current status of this project? Is it still maintained?

    So far I see no progress since https://github.com/tsayen/dom-to-image/issues/187

    opened by DanielRuf 13
  • Library not loaded in mobile Safari

    Library not loaded in mobile Safari

    Hello. I'm trying to use domtoimage in Mobile Safari.

    The library is not loaded and no error is apparent. I added an alert at the beginning of the script and it does not show. If I remove all the content of the script the alert shows.

    I will investigate the issue but I was wondering if the library had been tested on safari.

    opened by vcrepin 12
  • 3 pixel padding rendered below SVG (Chrome).

    3 pixel padding rendered below SVG (Chrome).

    Update: Appears to be a Chrome Bug, see comment.

    In testing the library, I found the resultant image was larger than the dom element I was trying to capture.

    There appears to be 3 extra pixels of height rendered below SVG elements. I've found the simplest case that illustrates: [https://jsfiddle.net/8kx0una9/]

    A 100x100 pixel div, containing a 100x100 pixel SVG containing a 100x100 pixel path element. Chrome inspector verifies all three elements rendered as 100x100 px (Version 52.0.2743.82 m) Firefox (Version 47.0.1) produces a 100x100px image, as expected.

    toPng() creates a png of the div at 100x103, with the extra 100x3 pixels as transparent. toJpeg() creates a jpeg of the div at 100x103, with the extra 100x3 pixels as black.

    Various Observations:

    • 3 pixels seems to be a fixed amount. 100x100 renders as 100x103, 400x400 renders as 400x403.
    • 3 px is from the bottom of the SVG. If the SVG ends 2 pixels above the bottom of the div, 1 extra pixel of height is added.
    • toPng() renders a 3px transparent bar (even if a Bgcolor is set)
    • toJpeg() renders a 3px black bar (even if a Bgcolor is set)
    • Add padding left and right, and use {Bgcolor:"#FF0000"}: Red padding added left and right, the 3px extra height renders as transparent or black for the full width, not just below the SVG.
    • Found a separate issue while testing this one, Image size should crop for content clipped by overflow:hidden;, The overflow issue also appears in Firefox, but these 3 pixels do not.
    • Setting overflow:hidden; does not relieve the problem, but appears to increase the extra padding to 4px.

    In the above fiddle, I could not get toPng() or toJpeg() to successfully render the SVG element directly (I don't know if that would be a separate bug, or a feature request).

    Thanks for the work, btw... this looks almost perfect for my needs.

    opened by john-m-adams 11
  • 'Promise' is undefined

    'Promise' is undefined

    I get a 'Promise' is undefined error on : dom-to-image.min.js, Line: 5, Column: 9 the line : return b = b || {}, Promise.resolve(a).then(function(a) {

    When running on IE 11.0.9600.18204 on Windows 7 x64

    opened by cristian-dan 11
  • Uncaught (in promise)

    Uncaught (in promise)

    function feedback() { $("#suggestion").val(""); var feedBackNode = document.body; domtoimage.toPng(feedBackNode).then(function (dataUrl) { imgDataUrl = dataUrl; var widthO = feedBackNode.offsetWidth; var heightO = feedBackNode.offsetHeight; var v = 1; var max = 550; if (widthO > heightO) { if (widthO > max) { v = max / widthO; } } else { if (heightO > max) { v = max / heightO; } } var img = new Image(); img.src = dataUrl; $("#feedback").empty(); $("#feedback").append($(img).css("width", widthO * v).css("height", heightO * v)); }) $("#feedbackModal").modal("show"); }

    image

    • [ ] Chrome 49+
    • [ ] Firefox 45+
    opened by lixiaoran0716 9
  • Cross Origin Image Requests

    Cross Origin Image Requests

    Use case:

    The current image loading implementation fails when it tries to fetch image resources where the server does not have CORS enabled. However it is possible to load a CORS image, in an image tag, copy the content to a canvas and get the data URL for use using the code in the link below.

    CORS Enabled Image

    For example I am trying to take a screen capture of a Leaflet map using Stamen Tiles, the problem is that the Stamen Tiles server does not always have the "Access-Control-Allow-Origin: *" header depending on how the image is requested causing errors.

    I was able to get this to partially work by changing the getAndEncode method to use makeImage with crossOrigin="anonymous" then drawing to a canvas and reading the data out. It was just some prototype hacks to see if this was possible and it appears it is.

    opened by cnatis 9
  • SVG shapes are not rendered

    SVG shapes are not rendered

    Use case: description, code

    I'm trying to use this package in combination with https://github.com/anseki/leader-line , however, the latter package's created svg's are not rendering in the image. As you can see in the fiddle, I do add them to the container.

    jsfiddle

    Expected behavior

    SVG shape to be rendered in image

    Actual behavior (stack traces, console logs etc)

    SVG shape is not rendered in image

    Library version

    Master

    Browsers

    Have only tested on Chrome

    • [x] Chrome 49+
    • [ ] Firefox 45+
    opened by Marchiuzzz 0
  • Unhandled Promise rejection in firefox

    Unhandled Promise rejection in firefox

    Use case: description, code

    I am using Angular framework. dom-to-image library is loaded as script tag from assets. Sample

    const content = document.getElementsByClassName("app-wrapper")[0];
    domtoimage.toBlob(content).then((imgData) => {
        formData.append("file", imgData, "screenshot.png");
        // formData used in a API .......
    });
    

    On chrome its working fine, however on firefox its generating following error -

    image

    Stack trace -

    image

    image

    Browsers

    • [ ] Chrome 49+
    • [* ] Firefox 45+
    opened by theSumit67 0
  • Resolves an issue where the background image does not appear in some cases

    Resolves an issue where the background image does not appear in some cases

    line 573 old var URL_REGEX = /url(['"]?([^'"]+?)['"]?)/g; new var URL_REGEX = /url(['"]?([^'"]+?)['"])/g;

    If the background-image name contains (), regular matching results in incomplete URLs

    opened by 15759928829 0
  • domtoimage issue with MUI Datagrid

    domtoimage issue with MUI Datagrid

    Use case: I am trying to download a snapshot (.png) file of my screen which has a MUI data grid in it. The number of columns is high so a horizontal scroll appears in the data grid, when I scroll to the extreme right(horizontally) in the data grid and download the snapshot the grid data disappears in the snapshot.

    Replication: https://codesandbox.io/s/blissful-smoke-yxti2z?file=/demo.js (use the in app refresh if it shows syntax error)

    Expected behavior

    The data should show as is in the downloaded snapshot.

    Actual behavior (stack traces, console logs etc)

    The data grid shows up empty in the snapshot image

    Library version

    "@mui/material": "latest",
    "@mui/x-data-grid": "^5.0.0",
    "dom-to-image": "2.6.0",
    

    Browsers

    • [ ] Chrome 49+
    • [ ] Firefox 45+
    opened by Sornav 0
  • it can only capture checkbox's checked state in default, once it changed, it can't be captured

    it can only capture checkbox's checked state in default, once it changed, it can't be captured

    Use case: description, code

    it can only capture checkbox's checked state in default, once it changed, it can't be captured

    Expected behavior

    firstly, the checkbox is selected, which means it is checked in default, When the user unchecks the box, it should capture the unchecked status

    Actual behavior (stack traces, console logs etc)

    it can not captured when the checked state is changed.

    Library version

    Browsers

    • [ ] Chrome 49+
    • [ ] Firefox 45+
    opened by Freya8080 0
Owner
Anatolii Saienko
Anatolii Saienko
optimize image & upload file to cloud as image bed with tiny image automic.

Rush! 图片压缩 & 直传图床工具 这是一个兴趣使然的项目, 希望 Rush! 能让这个世界的网络资源浪费减少一点点 下载 Downloads 获取最新发行版 功能 Features 拖拽批量压缩图片, 支持格式 jpg/png/gif Drop to optimize, jpg/png/gif

{ Chao } 3 Nov 12, 2022
Domvas implements the missing piece that connects the DOM and Canvas.

Domvas Overview Domvas implements the missing piece that connects the DOM and Canvas. It gives to the ability to take arbitrary DOM content and paint

Paul Bakaus 389 Dec 29, 2022
MidJourney is an AI text-to-image service that generates images based on textual prompts. It is often used to create artistic or imaginative images, and is available on Discord and through a web interface here.

Midjourney MidJourney is an AI text-to-image service that generates images based on textual prompts. It is often used to create artistic or imaginativ

Andrew Tsegaye 8 May 1, 2023
Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.

Phaser - HTML5 Game Framework Phaser is a fast, free, and fun open source HTML5 game framework that offers WebGL and Canvas rendering across desktop a

Richard Davey 33.4k Jan 7, 2023
Framework for HTML5 Canvas oriented 2D video games

Canvas Engine http://canvasengine.net Description Framework to create video games in HTML5 Canvas Get Started Follow the steps below to start: Downloa

Samuel Ronce 378 Dec 2, 2022
The Easel Javascript library provides a full, hierarchical display list, a core interaction model, and helper classes to make working with the HTML5 Canvas element much easier.

EaselJS EaselJS is a library for building high-performance interactive 2D content in HTML5. It provides a feature-rich display list to allow you to ma

CreateJS 8k Dec 29, 2022
Pure JavaScript HTML5 Canvas Range Slider. No stylesheet needed. Simple, elegant and powerful. A quirky alternative to other sliders.

CanvasSlider CanvasSlider is a lightweight JavaScript range slider. Most of the range slider controls use Javascript and a stylesheet. This slider use

null 7 Aug 15, 2022
Custom Vitest matchers to test the state of the DOM, forked from jest-dom.

vitest-dom Custom Vitest matchers to test the state of the DOM This library is a fork of @testing-library/jest-dom. It shares that library's implement

Chance Strickland 14 Dec 16, 2022
An extension of DOM-testing-library to provide hooks into the shadow dom

Why? Currently, DOM-testing-library does not support checking shadow roots for elements. This can be troublesome when you're looking for something wit

Konnor Rogers 28 Dec 13, 2022
A Javascript library to export svg charts from the DOM and download them as an SVG file, PDF, or raster image (JPEG, PNG) format. Can be done all in client-side.

svg-exportJS An easy-to-use client-side Javascript library to export SVG graphics from web pages and download them as an SVG file, PDF, or raster imag

null 23 Oct 5, 2022
Hashmat Noorani 4 Mar 21, 2023
A NPM package powered by Yeoman that generates a scaffolding boilerplate for back-end workflow with Node.js.

generator-noderplate Generate Node.js starter files with just one command! We have deployed a npm package that will generate a boilerplate for nodejs

Samarjeet 3 Jan 24, 2022
A JavaScript library built on top of the Faker.JS library. It generates massive amounts of fake data in the browser and node.js.

Blaver - generate massive amounts of fake data in the browser and node.js Blaver is a JavaScript library built on top of the Faker.JS library. It gene

Priyansh 113 Dec 30, 2022
A very simple tool that generates multiple spellings of a phone number (to effectively search for it using the OR operator and quotes)

phonenumberqueryconstructor A very simple tool that generates multiple writings of a phone number (to effectively search for it using the OR operator

Cyb_detective 10 Dec 7, 2022
🖼️ Image proxy for Next.js. Makes it possible to use dynamic domains in next/image component.

Next.js Image Proxy Image proxy for Next.js. Makes it possible to use dynamic domains in next/image component. ❔ Motivation This library makes it poss

Blazity 30 Dec 1, 2022
A Javascript library that discourages and prevents image theft/download by preventing client ability to retrieve the image.

ProtectImage.js ProtectImage.js is a Javascript library that helps prevent image theft by disabling traditional user interactions to download/copy ima

null 4 Aug 18, 2022
Simple JavaScript Library to add parallax image to background-image

Backpax Simple JavaScript Library to add parallax image to background-image Install $ npm install backpax --save Demo Demo page is here Usage If you

appleple 13 Oct 12, 2022
Piccloud is a full-stack (Angular & Spring Boot) online image clipboard that lets you share images over the internet by generating a unique URL. Others can access the image via this URL.

Piccloud Piccloud is a full-stack application built with Angular & Spring Boot. It is an online image clipboard that lets you share images over the in

Olayinka Atobiloye 3 Dec 15, 2022