获取组件的实际宽度和高度

Get actual width and height of a component

本文关键字:高度 组件 获取      更新时间:2023-09-26

我们在 JavaScript 中面临着一个相当可怕的问题,我们似乎都没有能力解决:

我们如何获得 DOM 元素的宽度和高度,包括子元素、整个盒子模型等,而组件实际上并未显示在页面上?

记住:我正在寻找建议。即使是不能完全回答问题(或不太符合指定参数)的答案也可能是有帮助的。

主要目标:我通过Javascript将HTML元素添加到页面中 - 来自数据库的大小和样式的HTML元素。问题是它们行为不端,通常是不好的对齐方式,由于填充/边距,一个元素比另一个元素大,所以我需要检查它们的实际大小来解决这些问题。

正如BigMacAttack在评论中描述的那样,由此产生的应用程序将是一个"紧密结合的第三方HTML控件的马赛克"几乎是恰到好处的。它需要看起来很像成熟的桌面应用程序,HTML似乎非常讨厌这个想法。不是我怪它。

无论如何,这里有一些示例代码:

JavaScript:

function exampleElement(caption, content) {
    this.caption = caption;
    this.content = content;
    this.rootElement = document.createElement("div");
}
exampleElement.prototype.constructElement = function() {
    var otherElement = document.createElement("p");
    this.rootElement.className = "exampleElement";
    this.rootElement.textContent = this.caption; 
    otherElement.className = "exampleP";
    otherElement.textContent = this.content;
    this.rootElement.appendChild(otherElement);
    /*I need to know size of the otherElement here*/
    /*here goes code adding stuff into rootElement*/
};
window.onload = function() {
    var ex = new exampleElement("Hello", "Here's text");
    ex.constructElement();
    document.body.appendChild(ex.rootElement);
};

.CSS:

.exampleElement {
    padding: 5px;
    margin: 6px;
}
.exampleElement .exampleP {
    padding: 20px;
    margin: 6px;
}

小提琴

现在,我们需要我们的页面对窗口的大小和各个组件的内容做出动态反应,这就是为什么能够在显示对象之前获取对象的大小很重要的原因。同样重要的是,对象的创建应明确分为三个阶段:

  • 通过新创建

  • DOM 树的构造 (constructElement)

  • 添加到
  • 文档中(直接添加到正文或另一个 DOM 树中)

施工阶段,我们必须了解各个元素的尺寸,这一点很重要。

到目前为止,我们已经尝试通过jQuery,DOM宽度和高度属性来测量它,但是对于DOM对象没有直接显示在页面上,这些都不起作用。我尝试过的另一种方法是将对象添加到 document.body 中的几个函数,获取宽度和高度,然后立即将其删除 - 但是,由于我们的 CSS 文件非常具体,除非您插入整个 rootElement,否则这是不可靠的,这将是一个糟糕的性能和内存消耗,因为我们的组件变得相当复杂。

我想一种放弃的方法.完全CSS文件并直接通过JS定义样式至少可以解决我们的部分困境,但必须有更好的方法。

开始赏金以获得更多的想法和建议。只需射击人,即使答案不完全在问题的范围内(你会/你怎么做等) - 我试图实现的目标是让我的 JS 生成的 HTML 控件正确组合在一起。

如果最初需要隐藏手风琴、滑块等组件以及需要边界框信息才能正常工作的其他组件,则经常会遇到此问题。

一个简单的技巧是添加css,隐藏相关内容的可见性,并确保它不会闪烁或干扰您的布局。

它可以像这样简单:

{   visibility:hidden;
    position:absolute;
    left: -9999px;
}

然后将位置设置回静态或相对,并在准备好显示组件时将可见性设置回可见。

小提琴在这里,但没有太多内容:http://jsfiddle.net/gwwar/ZqQtz/1/

使用 javascript 获取盒模型 DOM 节点的渲染宽度和高度,而不实际将其添加到要显示的 DOM 中是不可能的。

为了证明这一点,让我们来看看如何在浏览器内部计算 DOM 节点的渲染高度和宽度。我将参考 WebKit 如何处理这个问题,因为它是最常用的布局引擎。

随着文档的解析和 DOM 节点添加到"DOM 树"中,会为需要显示的 DOM 节点创建Renderers。这就是"渲染树"的构建方式。

以下是Dave Hyatt在官方WebKit博客上发表的一篇题为"WebCore Rendering I – The Basics"的文章的摘录:

"渲染器是通过DOM上称为附件的过程创建的。 在解析文档并添加 DOM 节点时,一种名为 attach在 DOM 节点上被调用以创建渲染器。

void attach()

attach方法计算 DOM 节点的样式信息。如果 元素的显示 CSS 属性设置为无,或者如果节点是 具有 display:未设置,然后无渲染器的元素的后代 将被创建。

因此,为了提高效率,浏览器甚至不会为显示设置为none的元素计算样式信息。因此,无法通过javascript访问该信息。但是,如果显示属性设置为 none,则会发生以下情况:

"在附件期间,DOM 查询 CSS 以获取 一个元素。生成的信息存储在名为 渲染样式...可以从 RenderObject 访问 RenderStyle 使用 style() 方法...主要主力子类之一 的 RenderObject 是 RenderBox。此子类表示以下对象: 遵守 CSS 框模型。这些包括任何有边框的对象, 填充、边距、宽度和高度。

因此,如果您的用例允许您直接从浏览器中通过 C/C++ 检索盒模型渲染高度和宽度,并通过其他方式将其传递给您的 JavaScript 代码,那么您可以查询每个 DOM 元素的 RenderBox 子类的高度/宽度方法。这基本上就是 WebKit 开发人员工具获取此信息的方式。

你可以试试这个jQuery插件:https://github.com/dreamerslab/jquery.actual

既然你问了相关的答案...

如果您的 DOM 元素不按其内容动态调整大小,我建议使用以下工作流程。

虽然它可以让你的 DOM 结构更加臃肿,但通常最好使用"容器"对象。 这些对象将没有边框、填充或边距,以保持其 DOM 尺寸可预测。然后,您可以强制孩子在其容器的范围内紧紧扩展。

容器对象将用于查询特定的大小和位置,因为没有额外的属性来解释大小失真。

http://jsfiddle.net/aywS6/

.CSS

#container {
    position: absolute;
    margin:0px;
    padding:0px;
    width: 300px;
    height: 100px;
    background: #aaa;
    border: 0 none;
}
#subject {
    position: absolute;
    top: 0px;
    bottom: 0px;
    left: 0px;
    right: 0px;
    padding: 10px 20px;
    background: #aaf;
}

.HTML

<div id="container">
    <div id="subject">
        contents...
    </div>
</div>

这里的问题是,在页面上添加此元素之前,您无法获取元素大小。

在您的方法"constructElement"上,您将元素添加到根元素,但只是在加载时添加到页面。您的属性"rootElement"没有设置大小属性。

如果要操作这些属性,请重新考虑对象/方法的结构。

看看我对你的小提琴的更新

$(function ()
{
    var ex = new exampleElement("Hello", "Here's text");
    ex.constructElement();
    document.body.appendChild(ex.rootElement);
    $("<span/>")
        .text(" => Width is " + $("div").width() + ", and Height is " + $("div").height())
        .appendTo($("div p"));
});

不知道这是否有帮助,但既然你问了任何答案:)这是我所拥有的。

我有一个类似的问题,我想有很好的jQuery效果,根据HTML容器的内部内容将它的大小调整为"自动"高度和宽度。这个想法仍然类似于一些人已经在这里提到的:你在"屏幕外"的某个地方有一个容器,你把你的东西放在那里,测量尺寸并删除它。所以这是我在这里找到的功能

jQuery.fn.animateAuto = function(prop, speed, callback) {
    var elem, height, width;
    return this.each(function(i, el) {
        el = jQuery(el), elem = el.clone().css({
            "height" : "auto",
            "width" : "auto"
        }).appendTo("body");
        height = elem.css("height"), width = elem.css("width"), elem.remove();
        if (prop === "height")
            el.animate({
                "height" : height
            }, speed, callback);
        else if (prop === "width")
            el.animate({
                "width" : width
            }, speed, callback);
        else if (prop === "both")
            el.animate({
                "width" : width,
                "height" : height
            }, speed, callback);
    });
};

这段代码比你需要的多一点,但你可能感兴趣的部分是这样的:

elem = el.clone().css({
                "height" : "auto",
                "width" : "auto"
}).appendTo("body");
height = elem.css("height")
width = elem.css("width")

希望这有帮助

如果主要问题是您无法在将其放置到屏幕上之前获取大小,我建议您创建一个允许将div 隐藏在页面背景下的类。这应该跨浏览器工作。

.exampleHidden{
    position: absolute;
    z-index: -1;
}

如果将页面 z-index 的主背景设置为 0,则将隐藏类附加到新元素,它会将其置于背景下。假设它不大于你的背景,它现在应该被隐藏,以允许你在通过删除.exampleHidden 类将其实际带回前台之前测量和设置高度和宽度。