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

我们在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控件正确地组合在一起。

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

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

在解析文档并将DOM节点添加到“DOM树”时,将为需要显示的DOM节点创建Renderers 。 这就是“渲染树”的构建方式。

以下是Dave Hyatt在官方WebKit博客上发表的题为“WebCore渲染I – The Basics”的文章的摘录:

“渲染器是通过DOM上的一个进程创建的,称为附件。在解析文档并添加DOM节点时,会在DOM节点上调用一个名为attach的方法来创建渲染器。

void attach()

attach方法计算DOM节点的样式信息。 如果元素的显示CSS属性设置为none,或者节点是具有display:none set的元素的后代,则不会创建任何渲染器。“

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

“在附件期间,DOM查询CSS以获取元素的样式信息。结果信息存储在一个名为RenderStyle的对象中……可以使用style()方法从RenderObject访问RenderStyle …其中一个主体RenderObject的主要子类是RenderBox。这个子类表示服从CSS框模型的对象。这些对象包括具有边框,填充,边距,宽度和高度的任何对象。

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

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

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

它可以是一样简单:

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

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

小提琴就在这里,但它并不多: http : //jsfiddle.net/gwwar/ZqQtz/1/

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

既然你要求相关答案……

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

虽然它可以使你的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

 
contents...

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

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

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

看看我的小提琴的更新

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

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

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

 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类实际将它带回前台。