Calculate correct bounds for text/elements under nested transforms

This commit is contained in:
Niklas von Hertzen 2017-08-01 23:27:12 +08:00
parent c5135f4839
commit aafb0cfb9c
5 changed files with 38 additions and 30 deletions

View File

@ -44,20 +44,8 @@ export class Bounds {
} }
} }
export const parseBounds = (node: HTMLElement, isTransformed: boolean): Bounds => { export const parseBounds = (node: HTMLElement): Bounds => {
return isTransformed ? offsetBounds(node) : Bounds.fromClientRect(node.getBoundingClientRect()); return Bounds.fromClientRect(node.getBoundingClientRect());
};
const offsetBounds = (node: HTMLElement): Bounds => {
// //$FlowFixMe
const parent = node.offsetParent ? offsetBounds(node.offsetParent) : {top: 0, left: 0};
return new Bounds(
node.offsetLeft + parent.left,
node.offsetTop + parent.top,
node.offsetWidth,
node.offsetHeight
);
}; };
export const calculatePaddingBox = (bounds: Bounds, borders: Array<Border>): Bounds => { export const calculatePaddingBox = (bounds: Bounds, borders: Array<Border>): Bounds => {

View File

@ -88,10 +88,15 @@ export default class NodeContainer {
zIndex: parseZIndex(style.zIndex) zIndex: parseZIndex(style.zIndex)
}; };
if (this.isTransformed()) {
// getBoundingClientRect provides values post-transform, we want them without the transformation
node.style.transform = 'matrix(1,0,0,1,0,0)';
}
this.image = this.image =
// $FlowFixMe // $FlowFixMe
node.tagName === 'IMG' ? imageLoader.loadImage(node.currentSrc || node.src) : null; node.tagName === 'IMG' ? imageLoader.loadImage(node.currentSrc || node.src) : null;
this.bounds = parseBounds(node, this.isTransformed()); this.bounds = parseBounds(node);
if (__DEV__) { if (__DEV__) {
this.name = `${node.tagName.toLowerCase()}${node.id this.name = `${node.tagName.toLowerCase()}${node.id
? `#${node.id}` ? `#${node.id}`

View File

@ -35,7 +35,8 @@ const parseNodeTree = (
stack: StackingContext, stack: StackingContext,
imageLoader: ImageLoader imageLoader: ImageLoader
): void => { ): void => {
node.childNodes.forEach((childNode: Node) => { for (let childNode = node.firstChild, nextNode; childNode; childNode = nextNode) {
nextNode = childNode.nextSibling;
if (childNode.nodeType === Node.TEXT_NODE) { if (childNode.nodeType === Node.TEXT_NODE) {
//$FlowFixMe //$FlowFixMe
if (childNode.data.trim().length > 0) { if (childNode.data.trim().length > 0) {
@ -72,7 +73,7 @@ const parseNodeTree = (
} }
} }
} }
}); }
}; };
const createsRealStackingContext = (container: NodeContainer, node: HTMLElement): boolean => { const createsRealStackingContext = (container: NodeContainer, node: HTMLElement): boolean => {

View File

@ -3,7 +3,7 @@
import {ucs2} from 'punycode'; import {ucs2} from 'punycode';
import type TextContainer from './TextContainer'; import type TextContainer from './TextContainer';
import {Bounds} from './Bounds'; import {Bounds, parseBounds} from './Bounds';
import {TEXT_DECORATION} from './parsing/textDecoration'; import {TEXT_DECORATION} from './parsing/textDecoration';
import FEATURES from './Feature'; import FEATURES from './Feature';
@ -40,19 +40,32 @@ export const parseTextBounds = (textContainer: TextContainer, node: Text): Array
) { ) {
if (FEATURES.SUPPORT_RANGE_BOUNDS) { if (FEATURES.SUPPORT_RANGE_BOUNDS) {
textBounds.push(new TextBounds(text, getRangeBounds(node, offset, text.length))); textBounds.push(new TextBounds(text, getRangeBounds(node, offset, text.length)));
} else {
const replacementNode = node.splitText(text.length);
textBounds.push(new TextBounds(text, getWrapperBounds(node)));
node = replacementNode;
} }
} else if (!FEATURES.SUPPORT_RANGE_BOUNDS) {
node = node.splitText(text.length);
} }
offset += text.length; offset += text.length;
} }
return textBounds; return textBounds;
};
/* const getWrapperBounds = (node: Text): Bounds => {
else if (container.node && typeof container.node.data === 'string') { const wrapper = node.ownerDocument.createElement('html2canvaswrapper');
var replacementNode = container.node.splitText(text.length); wrapper.appendChild(node.cloneNode(true));
var bounds = this.getWrapperBounds(container.node, container.parent.hasTransform()); const parentNode = node.parentNode;
container.node = replacementNode; if (parentNode) {
parentNode.replaceChild(wrapper, node);
const bounds = parseBounds(wrapper);
if (wrapper.firstChild) {
parentNode.replaceChild(wrapper.firstChild, wrapper);
}
return bounds; return bounds;
}*/ }
return new Bounds(0, 0, 0, 0);
}; };
const getRangeBounds = (node: Text, offset: number, length: number): Bounds => { const getRangeBounds = (node: Text, offset: number, length: number): Bounds => {

View File

@ -19,10 +19,7 @@ export type Options = {
type: ?string type: ?string
}; };
const html2canvas = ( const html2canvas = (element: HTMLElement, config: Options): Promise<HTMLCanvasElement> => {
element: HTMLElement,
config: Options
): Promise<HTMLCanvasElement> => {
const logger = new Logger(); const logger = new Logger();
const ownerDocument = element.ownerDocument; const ownerDocument = element.ownerDocument;
@ -91,7 +88,11 @@ const html2canvas = (
} }
} }
const renderer = new CanvasRenderer(canvas, {scale: options.scale, backgroundColor, imageStore}); const renderer = new CanvasRenderer(canvas, {
scale: options.scale,
backgroundColor,
imageStore
});
return renderer.render(stack); return renderer.render(stack);
}); });
}); });