用于“压扁”保留视觉外观的网页DOM的JavaScript?

时间:2011-01-02 09:36:02

标签: javascript dom browser

我想编写一些JavaScript代码,“平铺”任意网页的DOM,同时保留视觉外观(但不一定是调整大小或其他动态行为)

理论上我认为这应该只是记录每个元素相对于窗口的位置(ex PPK's findPos(element))以及它的计算CSS样式(ex window.getComputedStyle(element).cssText),移动从它的父元素到“body”的直接子元素,使其绝对位于先前记录的位置,并将记录的CSS属性直接设置在元素上。

我采用这种方法取得了一些成功,但它并不接近完美:

function walkDOM(element, parent, nodes) {
    parent = parent || { top : 0, left : 0, depth : 0 };
    nodes = nodes || [];

    if (element.nodeType === 1) {
        var node = findPos(element);
        node.element = element;
        node.width = element.scrollWidth;
        node.height = element.scrollHeight;
        node.depth = parent.depth + 1;
        node.cssText = window.getComputedStyle(element).cssText;
        nodes.push(node);

        for (var i = 0; i < element.childNodes.length; i++) {
            walkDOM(element.childNodes[i], node, nodes);
        }
    }
    return nodes;
}

// based on http://www.quirksmode.org/js/findpos.html
function findPos(element) {
    var position = { left : 0, top : 0 };
    if (element.offsetParent) {
        do {
            position.left += element.offsetLeft;
            position.top += element.offsetTop;
        } while (element = element.offsetParent);
    }
    return position;
}

var nodes = walkDOM(document.body);

nodes.forEach(function(node) {
    var e = node.element;

    if (e !== document.body)
        e.parentNode.removeChild(e);

    // e.setAttribute("style", node.cssText);
    e.style.position = "absolute";
    e.style.top = node.top + "px";
    e.style.left = node.left + "px";
    e.style.width = node.width + "px";
    e.style.height = node.height + "px";
    e.style.zIndex = node.depth + 1;

    if (e !== document.body)
        document.body.appendChild(e);
});

2 个答案:

答案 0 :(得分:1)

我正在尝试类似的东西,但我只是展平只有块级节点,因为所有这些都会破坏布局(想想里面的 em a p 等)。所以我这样走在树上:

var treeWalker = document.createTreeWalker(
    document.body,
    NodeFilter.SHOW_ELEMENT,
    function (node) { 
        if (window.getComputedStyle(node, null).getPropertyValue("display") == "block") {
            return NodeFilter.FILTER_ACCEPT;
        }
        return NodeFilter.FILTER_REJECT; 
    },
    false
);

var nodeList = new Array();
while(treeWalker.nextNode()) {
    nodeList.push(treeWalker.currentNode);
}

然后只需迭代它们(因为你将以正确的相反顺序使它们)并在应用定位时将它们移动到 body

我的目的只是重新创建简单的 div 框来让他们研究布局,我发现我遇到了原本位于其他剪辑它们的块元素的问题(溢出隐藏) ,我目前正在寻找使用svg掩码来重现剪辑。

答案 1 :(得分:0)

看起来你有一个良好的开端。你有没有考虑过使用jQuery?它们具有非常有用的功能,可能使您更容易理解,特别是offset()函数,它从文档中获取元素的绝对位置。

http://api.jquery.com/category/manipulation/style-properties/
http://api.jquery.com/offset/
http://api.jquery.com/position/
http://jqueryui.com/demos/position/

您也可以尝试修复元素而不是绝对元素。