3-4 尺寸获取
本节编程练习不计算学习进度,请电脑登录imooc.com操作

尺寸获取

有三种方法能够确定浏览器窗口的尺寸(浏览器的视口,不包括工具栏和滚动条)。
对于Internet Explorer、Chrome、Firefox、Opera 以及 Safari:
窗口显示区(可视区域)的宽度和高度,包括滚动条。
window.innerHeight - IE不支持该属性,IE中body元素的clientHeight属性与该属性相同。window.innerWidth – IE不支持该属性,IE中body元素的clientWidth属性与该属性相同。

对于 Internet Explorer 8、7、6、5:

窗口显示区(可视区域)的宽度和高度,不包括滚动条区域。

document.documentElement.clientHeight
document.documentElement.clientWidth
或者
document.body.clientHeight
document.body.clientWidth

对于元素宽度尺寸的获取,jquery提供了width方法。
对于文档级非普通元素window,document的宽度获取

$(window).width()   代表了当前浏览器可见区域的宽度
$(document).width()  则代表了整个文档的宽度,可以有滚动内容

window 反映的是视图窗口,没有用window.innerWidth(包括滚动条区域),而是采用window.document.documentElement.clientWidth(不包括滚动条区域),document是反映了实际内容区间,那么可以存在溢出滚动,所以就是:

document.documentElement.scrollWidth
document.body.scrollWidth

由于兼容问题就取2者之中的最大值。

.width()是我们经常应用获取对象宽度的方法,但是就Query为了做这个兼容可不是表面上那么简单的,首先整理下涉及到元素宽度处理,我们需要考虑的因素。

1 元素的宽素可以是内联或者通过link定义,所以通过style是不可取的
2 元素在隐藏状态下是不能获取任何尺寸的 display:none
3 CSS3引入了box-sizing的设置

我们看看jquery如何处理的:
width,height在内部最终调用的是jQuery.css(elem, type, extra)方法,jQuery.css是最终的一个针对所有CSS处理的接口,我们放在下一章,这里我们只涉及width与height的获取。

display:none的状态下是无法获取元素的尺寸的,所以jQuery在最开始之前必须要检测下这个状态,这个处理是通过钩子jQuery.cssHooks['widht'].get方法调用的:

/^(none|table(?!-c[ea]).+)/test(jQuery.css(elem, "display")) //代码很简单通过判断得到的值

当检测到是none的情况下,就要把display置为block?不行这样就改变了布局的原意了,本来就是隐藏的。jQuery就会对元素增加position: absolute; visibility: hidden;这样的属性达到display:none的效果,因为在visibility: hidden的情况下,是可以获取到值的,只是对于用户不可见而已。


获取元素的尺寸值我们有offsetWidth,与offsetHeight,大多情况下是够用了,但是有一种情况如果元素采用boxSizing处理,所以jQuery还要对BorderBox情况的检测,如果如果是采用了border-box样式的话,针对值的获取还要减去padding,border,这又是一个相当繁琐的过程,我们在之前就提到过这个过程的处理了。

任务

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
  5. <script src="http://code.jquery.com/jquery-latest.js"></script>
  6. <title>jQuery.width</title>
  7. <style type="text/css">
  8. div{
  9. width: 3000px;
  10. height: 100px;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15.  
  16. <div style="background:red;border:20px solid #ccc;">获取元素大小</div>
  17.  
  18. <button id="test1">display:none状态下,无法获取</button>
  19. <button id="test2">模拟jQuery的.width()方法,在隐藏的时候也能获取</button>
  20.  
  21. <ul></ul>
  22.  
  23. <script type="text/javascript">
  24.  
  25. var div = document.querySelectorAll('div')[0]
  26.  
  27. $('#test1').click(function(){
  28. div.style.display = "none";
  29. show('隐藏状态下div.style.width: '+ div.style.width)
  30. show('隐藏状态下div.offsetWidth: '+ div.offsetWidth)
  31. })
  32.  
  33.  
  34. //获取样式合集
  35. function getStyles(elem) {
  36. return elem.ownerDocument.defaultView.getComputedStyle(elem, null);
  37. };
  38.  
  39. //交换样式
  40. function swap(elem, options, callback, args) {
  41. var ret, name,
  42. old = {};
  43. for (name in options) {
  44. old[name] = elem.style[name];
  45. elem.style[name] = options[name];
  46. }
  47. ret = callback.apply(elem, args || []);
  48. for (name in options) {
  49. elem.style[name] = old[name];
  50. }
  51. return ret;
  52. };
  53.  
  54. //获取当前样式
  55. function curCSS(elem,name) {
  56. var computed = getStyles(elem);
  57. var ret = computed.getPropertyValue(name) || computed[name];
  58. return ret;
  59. }
  60.  
  61. //获取宽高
  62. function getWidthOrHeight(elem, name, extra){
  63. var val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
  64. //需要extra判断是否是content/border的处理
  65. //代码太长,这里省略了,具体可以可以参考jQuery的源码
  66. return val;
  67. }
  68.  
  69. var cssShow = {
  70. display: "block",
  71. position: "absolute",
  72. visibility: "hidden"
  73. }
  74.  
  75.  
  76. $('#test2').click(function(){
  77. var elem = div;
  78. function width() {
  79. if( /^(none|table(?!-c[ea]).+)/.test(curCSS(div, 'display')) ){
  80. return swap(elem, cssShow, function() {
  81. return getWidthOrHeight(elem, 'width', 'content');
  82. })
  83. }
  84. }
  85. show('模拟jQuery.width的处理: '+ width())
  86. })
  87.  
  88. function show(data){
  89. $('ul').append('<li>'+ data +'</li>')
  90. }
  91.  
  92. </script>
  93. </body>
  94. </html>
下一节