鸟食轩

 Microsoft .NET[C#] MVP 2003
随笔 - 424, 文章 - 231, 评论 - 5402, 引用 - 344
数据加载中……

MyMsn动态Resize页框架的布局详解

    微软的MyMsn提供了一个自由resize和drag&drop的个人Portal,虽然这样的东西不难见到,像SharePoint、DotNetNuke等都有很好的这种操作实现。而且我们也知道在Web页中托拽一个html元素是很容易的,不过要是整个页面都是绝对定位,其实还是非常难于管理的,所以我们看看MyMsn是怎么来做的呢?

    大家应该都玩过MyMsn了吧?http://my.msn.com/,需要注册一个passpost账号。

    MyMsn的整体结构是按照channel来分的一个个Tab,这个是在服务器端处理并生成,不是我们要研究的重点。它的外观如下:
   

    它的每个独立的Tab的布局结构,是我们要研究的重点。一个TabPage在MyMsn中就是一个<table>,然后被分为了n个column,显示效果如截图下:
   
    并且MyMsn支持用户任意的Resize Column的宽度,效果如下图:
   

    嗯,我们可以看出,MyMsn的页面布局就是最外的<table>里放了两个<tr>,第一行的<tr>作为Column Header,第二行的<tr>放置具体的内容。第二行<tr>中的每个<td>就是一个放置内容的container,图中类似Windows窗口的每个block也是<table>块,他们顺序的放置于其container(<td>)中,一切的布局皆由默认布局完成。什么意思呢? 就是说此时的布局效果没有使用任何的position、top和left等style来强制约束。

    这个好像没有什么特别,只要会做网页就能做出这样的布局嘛。对,不过这样的布局支持MyMsn的特性还是有问题的,MyMsn提供的一个很sexy的功能就用户可以自由的在界面上做定制!包括reszie和drag&drop。问题是什么呢?我们知道在IE解析HTML并绘制图形的时候,它是从HTML树的每个leaf节点开始绘制的。这样的绘图顺序才能保证把所有的元素外观都表现出来而不被隐藏,只要做过Web页肯定都遇到过表格被撑开这种情况是吧?这就是因为IE按先根遍历DHTML树来输出所产生的结果,当然这不是IE特有的规则,所有的browser都是这样的策略来输出图形的。

    这样一来,就是说我们可以任意的变宽container的width,但是要想减小container的width,就要看其内部元素的布局策略了。如果container内部元素可以任意折行并且其width为百分比单位,减小container的width可以强制内部元素同时变窄(同时高度会增加哈)。相反的情况下,要想随意的改变container的宽度来约束其内容,就是做不到的了。

    MyMsn既然是使用的表格来布局,那么它是怎么处理resize的时候,每个room内的内容的宽度的呢?看一下上图(第三张),当我们在第一个column和第二个column之间resize第一个column的宽度时,居然可以出现room跑到container外去了的情况,看room "Add Content"!原来MyMsn是这样做的,当用户在resizer上MouseDown的时候,使用JavaScript把宽度受影响的container内的room的定位方式改为"absolute",然后计算每个room在页面中的位置,绝对定位每个room。拖动resizer时,在onmousemove更新受影响的container内的每个room的宽度。Room "Welcome" & "Add Content"表现出来的不同外观,就是我前面讲的IE输出图形策略造成的,就是说即使我们把"Add Content"这个Room的宽度设置为1,它还会是那么宽的。

    同时为了保证表格嵌套的这种布局策略,当用户停止resize动作,在resizer上触发onmosueup事件后,使用脚本把container内的room的position属性又全部设置回"static",让它们服从IE的默认布局流。这样的好处就是,始终能保存页面清晰的布局关系,而且依赖于IE默认布局,不会有产生任何潜在的混乱,也便与支持动态添加Column或Room。同时由于MyMsn还需要把用户自定义的设置信息传回到服务器保存,这也需要它能有一个清晰的布局结构,对于drag&drop,更需要这样的结构,如果是全部绝对定位,position属性为"absolute"的元素满页面飞,要记录其状态是非常麻烦的。MyMsn全部脚本代码2700于行,在这种布局结构下,完备的支持resize和drag&drop,只需要600行左右的代码(那剩的2000多行代码在嘛,我也不知道微软在搞什么飞机)。

    最后再附一个MyMsn页面元素布局图示(比实际稍微有些简化,但完全支持其现有功能):
  
    // 整个黑色框框、每一个蓝色绿色框框都是一个<table>元素。

posted on 2005-04-04 13:52 birdshome 阅读(3234) 评论(7)  编辑 收藏 所属分类: Jscript&Dhtml开发

评论

#1楼    回复  引用    

期待这个文章的后续
2005-04-04 22:46 | wearebug [未注册用户]

#2楼    回复  引用    

hoho,正好这个方面有些东西不明白,现在懂了
2005-04-05 08:40 | ocean2000 [未注册用户]

#3楼    回复  引用    

昨晚正做了一个类似的东西,不过考虑到显示效率就没有在拖动时实时更新显示.
因为table太特殊,就算在css里指定td宽度,它也不一定就这么宽,所以干脆放弃指定td宽度,而在td里放一个div,也用不着absolute了.感觉还不错
2005-04-10 09:13 | forfor [未注册用户]

#4楼    回复  引用  查看    

好文章!
最近对asp.net start kit portal进行了改造,实现了相同的功能效果。
2005-04-21 15:22 | 阿卡      

#5楼    回复  引用    

他这个页面好像不能保存,你是怎样拿到它的javascript文件的,能给我一份吗。guyun4@163.com
2005-05-22 23:00 | 谷生 [未注册用户]

#6楼 [楼主]   回复  引用  查看    

@谷生
调试MyMsn的页面就可以看到它的代码。本文中说到的脚本可以在这里拿到。
2005-05-22 23:44 | birdshome      

#7楼    回复  引用    

最好能写个简单例子看看
2006-01-26 14:46 | ddt1 [未注册用户]

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2005-04-22 08:31 编辑过


相关链接: