mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
104 lines
3.3 KiB
JavaScript
104 lines
3.3 KiB
JavaScript
/* @flow */
|
|
'use strict';
|
|
|
|
import {NodeParser} from './NodeParser';
|
|
import CanvasRenderer from './CanvasRenderer';
|
|
import Logger from './Logger';
|
|
import ImageLoader from './ImageLoader';
|
|
import {Bounds, parseDocumentSize} from './Bounds';
|
|
import {cloneWindow} from './Clone';
|
|
import Color from './Color';
|
|
|
|
export type Options = {
|
|
async: ?boolean,
|
|
allowTaint: ?boolean,
|
|
canvas: ?HTMLCanvasElement,
|
|
imageTimeout: ?number,
|
|
proxy: ?string,
|
|
removeContainer: ?boolean,
|
|
type: ?string
|
|
};
|
|
|
|
const html2canvas = (element: HTMLElement, config: Options): Promise<HTMLCanvasElement> => {
|
|
const logger = new Logger();
|
|
|
|
const ownerDocument = element.ownerDocument;
|
|
const defaultView = ownerDocument.defaultView;
|
|
const windowBounds = new Bounds(
|
|
defaultView.pageXOffset,
|
|
defaultView.pageYOffset,
|
|
defaultView.innerWidth,
|
|
defaultView.innerHeight
|
|
);
|
|
|
|
const defaultOptions = {
|
|
async: true,
|
|
allowTaint: false,
|
|
canvas: ownerDocument.createElement('canvas'),
|
|
imageTimeout: 10000,
|
|
proxy: null,
|
|
removeContainer: true,
|
|
scale: defaultView.devicePixelRatio,
|
|
type: null
|
|
};
|
|
|
|
const options = {...defaultOptions, ...config};
|
|
|
|
const canvas = options.canvas;
|
|
|
|
if (!(canvas instanceof HTMLCanvasElement)) {
|
|
return Promise.reject(__DEV__ ? `Invalid canvas element provided in options` : '');
|
|
}
|
|
|
|
return cloneWindow(
|
|
ownerDocument,
|
|
ownerDocument,
|
|
windowBounds,
|
|
element,
|
|
options
|
|
).then(([container, clonedElement]) => {
|
|
if (__DEV__) {
|
|
logger.log(`Document cloned`);
|
|
}
|
|
const imageLoader = new ImageLoader(options, logger);
|
|
const stack = NodeParser(clonedElement, imageLoader, logger);
|
|
const size =
|
|
options.type === 'view' ? windowBounds : parseDocumentSize(clonedElement.ownerDocument);
|
|
const width = size.width;
|
|
const height = size.height;
|
|
canvas.width = Math.floor(width * options.scale);
|
|
canvas.height = Math.floor(height * options.scale);
|
|
canvas.style.width = `${width}px`;
|
|
canvas.style.height = `${height}px`;
|
|
|
|
// http://www.w3.org/TR/css3-background/#special-backgrounds
|
|
const backgroundColor =
|
|
clonedElement === clonedElement.ownerDocument.documentElement
|
|
? stack.container.style.background.backgroundColor.isTransparent()
|
|
? clonedElement.ownerDocument.body
|
|
? new Color(getComputedStyle(clonedElement.ownerDocument.body).backgroundColor)
|
|
: null
|
|
: stack.container.style.background.backgroundColor
|
|
: null;
|
|
|
|
return imageLoader.ready().then(imageStore => {
|
|
if (options.removeContainer === true) {
|
|
if (container.parentNode) {
|
|
container.parentNode.removeChild(container);
|
|
} else if (__DEV__) {
|
|
logger.log(`Cannot detach cloned iframe as it is not in the DOM anymore`);
|
|
}
|
|
}
|
|
|
|
const renderer = new CanvasRenderer(canvas, {
|
|
scale: options.scale,
|
|
backgroundColor,
|
|
imageStore
|
|
});
|
|
return renderer.render(stack);
|
|
});
|
|
});
|
|
};
|
|
|
|
module.exports = html2canvas;
|