html2canvas/src/index.js

141 lines
4.3 KiB
JavaScript
Raw Normal View History

2017-07-29 05:07:42 +03:00
/* @flow */
'use strict';
import {NodeParser} from './NodeParser';
import Renderer from './Renderer';
import CanvasRenderer from './renderer/CanvasRenderer';
2017-07-29 05:07:42 +03:00
import Logger from './Logger';
import ImageLoader from './ImageLoader';
import {Bounds, parseDocumentSize} from './Bounds';
2017-08-01 15:54:18 +03:00
import {cloneWindow} from './Clone';
2017-07-29 05:07:42 +03:00
import Color from './Color';
import {FontMetrics} from './Font';
2017-07-29 05:07:42 +03:00
export type Options = {
2017-08-01 17:36:51 +03:00
async: ?boolean,
allowTaint: ?boolean,
canvas: ?HTMLCanvasElement,
imageTimeout: ?number,
proxy: ?string,
removeContainer: ?boolean,
scale: number,
type: ?string,
windowWidth: number,
windowHeight: number
2017-07-29 05:07:42 +03:00
};
const html2canvas = (element: HTMLElement, config: Options): Promise<HTMLCanvasElement> => {
2017-08-06 13:13:40 +03:00
if (typeof console === 'object' && typeof console.log === 'function') {
console.log(`html2canvas ${__VERSION__}`);
}
2017-07-29 05:07:42 +03:00
const logger = new Logger();
2017-08-01 15:54:18 +03:00
const ownerDocument = element.ownerDocument;
const defaultView = ownerDocument.defaultView;
2017-08-01 17:36:51 +03:00
const defaultOptions = {
async: true,
allowTaint: false,
canvas: ownerDocument.createElement('canvas'),
imageTimeout: 10000,
proxy: null,
removeContainer: true,
scale: defaultView.devicePixelRatio || 1,
type: null,
windowWidth: defaultView.innerWidth,
windowHeight: defaultView.innerHeight
2017-08-01 17:36:51 +03:00
};
const options = {...defaultOptions, ...config};
const windowBounds = new Bounds(
defaultView.pageXOffset,
defaultView.pageYOffset,
options.windowWidth,
options.windowHeight
);
2017-08-01 17:36:51 +03:00
const canvas = options.canvas;
if (!(canvas instanceof HTMLCanvasElement)) {
return Promise.reject(__DEV__ ? `Invalid canvas element provided in options` : '');
}
2017-08-03 19:13:20 +03:00
const result = cloneWindow(
2017-08-01 15:54:18 +03:00
ownerDocument,
ownerDocument,
windowBounds,
element,
options
).then(([container, clonedElement]) => {
if (__DEV__) {
logger.log(`Document cloned`);
}
const imageLoader = new ImageLoader(
options,
logger,
clonedElement.ownerDocument.defaultView
);
2017-08-01 15:54:18 +03:00
const stack = NodeParser(clonedElement, imageLoader, logger);
const clonedDocument = clonedElement.ownerDocument;
const size = options.type === 'view' ? windowBounds : parseDocumentSize(clonedDocument);
const width = size.width;
const height = size.height;
2017-08-01 17:36:51 +03:00
canvas.width = Math.floor(width * options.scale);
canvas.height = Math.floor(height * options.scale);
2017-08-01 15:54:18 +03:00
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
// http://www.w3.org/TR/css3-background/#special-backgrounds
const backgroundColor =
clonedElement === clonedDocument.documentElement
2017-08-01 15:54:18 +03:00
? stack.container.style.background.backgroundColor.isTransparent()
? clonedDocument.body
? new Color(getComputedStyle(clonedDocument.body).backgroundColor)
2017-08-01 15:54:18 +03:00
: null
: stack.container.style.background.backgroundColor
: null;
return imageLoader.ready().then(imageStore => {
2017-08-01 17:36:51 +03:00
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`);
}
2017-08-01 15:54:18 +03:00
}
const fontMetrics = new FontMetrics(clonedDocument);
if (__DEV__) {
logger.log(`Starting renderer`);
}
const renderOptions = {
backgroundColor,
fontMetrics,
imageStore,
logger,
scale: options.scale,
width,
height
};
const canvasTarget = new CanvasRenderer(canvas, renderOptions);
const renderer = new Renderer(canvasTarget, renderOptions);
2017-08-01 15:54:18 +03:00
return renderer.render(stack);
});
2017-07-29 05:07:42 +03:00
});
2017-08-03 19:13:20 +03:00
if (__DEV__) {
return result.catch(e => {
logger.error(e);
throw e;
});
}
return result;
2017-07-29 05:07:42 +03:00
};
module.exports = html2canvas;