mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
112 lines
3.3 KiB
JavaScript
112 lines
3.3 KiB
JavaScript
_html2canvas.Renderer = function(parseQueue, options){
|
||
function sortZindex(a, b) {
|
||
if (a === 'children') {
|
||
return -1;
|
||
} else if (b === 'children') {
|
||
return 1;
|
||
} else {
|
||
return a - b;
|
||
}
|
||
}
|
||
|
||
// http://www.w3.org/TR/CSS21/zindex.html
|
||
function createRenderQueue(parseQueue) {
|
||
var queue = [],
|
||
rootContext;
|
||
|
||
rootContext = (function buildStackingContext(rootNode) {
|
||
var rootContext = {};
|
||
function insert(context, node, specialParent) {
|
||
var zi = (node.zIndex.zindex === 'auto') ? 0 : Number(node.zIndex.zindex),
|
||
contextForChildren = context, // the stacking context for children
|
||
isPositioned = node.zIndex.isPositioned,
|
||
isFloated = node.zIndex.isFloated,
|
||
stub = {node: node},
|
||
childrenDest = specialParent; // where children without z-index should be pushed into
|
||
|
||
if (node.zIndex.ownStacking) {
|
||
contextForChildren = stub.context = {
|
||
children: [{node:node, children: []}]
|
||
};
|
||
childrenDest = undefined;
|
||
} else if (isPositioned || isFloated) {
|
||
childrenDest = stub.children = [];
|
||
}
|
||
|
||
if (zi === 0 && specialParent) {
|
||
specialParent.push(stub);
|
||
} else {
|
||
if (!context[zi]) { context[zi] = []; }
|
||
context[zi].push(stub);
|
||
}
|
||
|
||
node.zIndex.children.forEach(function(childNode) {
|
||
insert(contextForChildren, childNode, childrenDest);
|
||
});
|
||
}
|
||
insert(rootContext, rootNode);
|
||
return rootContext;
|
||
})(parseQueue);
|
||
|
||
function sortZ(context) {
|
||
Object.keys(context).sort(sortZindex).forEach(function(zi) {
|
||
var nonPositioned = [],
|
||
floated = [],
|
||
positioned = [],
|
||
list = [];
|
||
|
||
// positioned after static
|
||
context[zi].forEach(function(v) {
|
||
if (v.node.zIndex.isPositioned || v.node.zIndex.opacity < 1) {
|
||
// http://www.w3.org/TR/css3-color/#transparency
|
||
// non-positioned element with opactiy < 1 should be stacked as if it were a positioned element with ‘z-index: 0’ and ‘opacity: 1’.
|
||
positioned.push(v);
|
||
} else if (v.node.zIndex.isFloated) {
|
||
floated.push(v);
|
||
} else {
|
||
nonPositioned.push(v);
|
||
}
|
||
});
|
||
|
||
(function walk(arr) {
|
||
arr.forEach(function(v) {
|
||
list.push(v);
|
||
if (v.children) { walk(v.children); }
|
||
});
|
||
})(nonPositioned.concat(floated, positioned));
|
||
|
||
list.forEach(function(v) {
|
||
if (v.context) {
|
||
sortZ(v.context);
|
||
} else {
|
||
queue.push(v.node);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
sortZ(rootContext);
|
||
|
||
return queue;
|
||
}
|
||
|
||
function getRenderer(rendererName) {
|
||
var renderer;
|
||
|
||
if (typeof options.renderer === "string" && _html2canvas.Renderer[rendererName] !== undefined) {
|
||
renderer = _html2canvas.Renderer[rendererName](options);
|
||
} else if (typeof rendererName === "function") {
|
||
renderer = rendererName(options);
|
||
} else {
|
||
throw new Error("Unknown renderer");
|
||
}
|
||
|
||
if ( typeof renderer !== "function" ) {
|
||
throw new Error("Invalid renderer defined");
|
||
}
|
||
return renderer;
|
||
}
|
||
|
||
return getRenderer(options.renderer)(parseQueue, options, document, createRenderQueue(parseQueue.stack), _html2canvas);
|
||
};
|