mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00

If you omit compare function in javascript `sort()` method it will sort lexicographically (in dictionary order) according to the string conversion of each element. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters For example [0, 9, 8, 10].sort() will place element with z-index 10 on 2nd position of the array
102 lines
3.2 KiB
JavaScript
102 lines
3.2 KiB
JavaScript
_html2canvas.Renderer = function(parseQueue, options){
|
||
|
||
// 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) {
|
||
// '!' comes before numbers in sorted array
|
||
contextForChildren = stub.context = { '!': [{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(function(a, b) { return a - b; }).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);
|
||
};
|