用js实现层随着内容大小动态渐变改变 推荐


Posted in Javascript onDecember 19, 2009

下面我们就自己来实现一个这样的组件,没有参考其他资料,纯属自己瞎写。

我觉得我这个方法很简单了,只需要在外边多套一个层就可以,而且可以容纳大量的文字(为什么这样说?因为如果只是单纯的图片,那调整起来简单多了,而如果有一大串文字的话,要变换两次才可以,因为如果你改变了宽度的话,字会被挤得高度增加,这里有两个方法来调整,一个是每次动画循环都更新最新的高和宽,另一种方法就是先变换,变换完后再检查一次,这次变化的只是高度,也就是调节两次,第一种方法效果好,但是每次都更新,自然加重了负担,第二种效果差点,但是性能好,而且也不是那么差)

实现原理很简单,就是在外边放一个主体层,我们调整的就是这个层,我们首先把这个层设置一个很小的宽和高,然后设置其overflow为hidden,然后运行时判断里面内容的大小,再回来调整外部层的大小即可。
本程序用到了YUI的一个动画函数和一个淘宝sns的jsonhtml对象,这个对象的作用是将一个用json形式表示的html转换成真正的html结构,可以使构造html的程序简洁清晰。

主体从Tip开始,我将这个组件写成了单例的模式,也就是不用new就可以在任何地方使用,而且都指向一个对象,而且这个组件封装目前没优化,为了试验,里面很多东西都是直接改的,外部暴露的接口太少:

var Tip=function(){ 
//直接返回一个json对象,这是一种js单例模式的实现 
return { 
//初始化函数 
init:function(options){ 
this.config={ 
container:null,//包装容器 
style:{},//样式配置 
data:{} 
} 
//样式配置 
this.style={tip:null,tip_title:null,tip_pic:null,tip_bd:null} 
//混合配置选项 
mixin(this.config,options) 
//初始数据 
this.data={ 
//标题的数据 
hd_data:this.config.data.hd_data==null?"没有描述":this.config.data.hd_data, 
//图片数据,正常情况下应该是一个网址 
pic_data:this.config.data.pic_data==null?"#":this.config.data.pic_data, 
//主题内容数据 
bd_data:this.config.data.bd_data==null?"没有描述":this.config.data.bd_data 
} 
//这是定义了一个加载的时候显示的滚动的gif的图像 
this.loading_pic=new Image(); 
this.loading_pic.src="http://www.sj33.cn/sc/UploadFiles_6888/200803/20080320132838323.gif"; this.creatHtml();//调用html构造器 
},

关于为什么js写成这样,还有一些从某些库里学来的写法就不多解释了,注释也很清楚,这里就是初始化一些数据,用来给后面的程序处理.
/** 
*构造html结构 
*/ 
creatHtml:function(){ 
//从外边数第二层的样式,它包住了里面的所有元素,大小是随着里面元素大小而变化的 
this.style.tip={ 
backgroundColor:"#fff", 
color:"#fff", 
border:"1px #333 solid", 
padding:"10px", 
overflow:"visible" 
} 
//标题的样式 
this.style.tip_title={ 
color:"#037DF9", 
fontSize:"14px", 
fontWeight: "bold" 
} 
this.style.tip_pic={ } 
//文字内容的样式 
this.style.tip_bd={ 
color:"#333", 
lineHeight:"20px" 
} 
this.style.hr={ 
color:"#037DF9", 
height:"1px", 
border:"0", 
borderTop:"1px #037DF9 solid", 
margin:"10px 0" 
} 
//最外边包装层的样式 
this.style.outer={ 
border:"5px solid #037DF9", 
overflow:"hidden", 
width:"10px", 
height:"10px" 
} 
//混合选项,也就是说这些都可以在外部自己定义样式,然后覆盖默认的样式 
mixin(this.style.tip,this.config.style.tip) 
mixin(this.style.tip_title,this.config.style.tip_title) 
mixin(this.style.tip_pic,this.config.style.tip_pic) 
mixin(this.style.tip_bd,this.config.style.tip_bd) 
//这个json就是html结构,其实不难理解,看看jsonhtml.js的源码就理解了 
var html_config={ 
div:{id:"tip_outer",style:this.style.outer}, 
">>":[ 
{div:{id:"tip_inner",style:this.style.tip}, 
">>":[ 
{div:{className:"tip-title",style:this.style.tip_title,id:"tip-title"},">>":this.data.hd_data}, 
{hr:{style:this.style.hr}}, 
{div:{className:"tip-pic",style:this.style.tip_pic,id:"tip-pic"},">>":[{img:{src:this.data.pic_data}}]}, 
{hr:{style:this.style.hr}}, 
{div:{className:"tip-bd",style:this.style.tip_bd,id:"tip-bd"},">>":this.data.bd_data} 
]} 
] 
} 
//转换成真正的html元素 
var html=JsonHtml.compose(html_config) 
//添加到容器中 
var tip_container=this.config.container||document.body; 
tip_container.appendChild(html) 
//下面获取一些元素,用来后面的操作,例如填充数据,动画等 
this.tip_outer=document.getElementById("tip_outer") 
this.tip_inner=document.getElementById("tip_inner") 
this.tip_title=document.getElementById('tip-title') 
this.tip_pic=document.getElementById('tip-pic') 
this.tip_bd=document.getElementById('tip-bd') 
//此时已经初始化了,首次调用了此函数,这就是大小自适应的函数 
this.updateSize(); 
},

上面首次出现了updateSize()函数,此函数就是今天的主体函数,不过遗憾的是这个函数非常短,
/** 
* 自动调整大小 
*/ 
updateSize:function(size){ 
//这里用了一个很不厚道的hack,那就是在大多数时候,我在外部就计算好要调整的高度,然后传进来,而不是在这里调整的 
//当然也可以不传参数,那样这里的计算就要麻烦点 
var size=size||{width:null,height:null} 
//获取里面的tip的大小,后面就把外边的层的大小变成这个大小 
var _height=size.height||this.tip_inner.offsetHeight; 
var _width=size.width||this.tip_inner.offsetWidth; 
var now_this=this; 
//开始定义动画 
var ani=new YAHOO.util.Anim(this.tip_outer, {height:{to:_height},width:{to:_width}},0.7) 
//第一次动画结束后,文字那里通常是不对的,因为字会因为宽度变了,而改变高度,这个是动态不可预知的,所以这里 
//再检查一遍 
ani.onComplete.subscribe(function(){ 
var _height=now_this.tip_inner.offsetHeight; 
var _width=now_this.tip_inner.offsetWidth; 
var ani2=new YAHOO.util.Anim(now_this.tip_outer, {height:{to:_height},width:{to:_width}},0.7); ani2.animate(); 
}); 
ani.animate(); 
},

注释很详细,无需多说了,这个对象只剩下一个函数了,那就是填充数据,这个函数可以多次执行,每次都会导致数据变化和大小的变化
/** 
* 改变填充数据 
* @param data 一个json对象,包括三部分的数据{hd_data:"",pic_data:"",bd_data:""} 
*/ 
updateData:function(data){ 
this.data={ 
hd_data:null?"没有描述":data.hd_data,//标题的数据 
pic_data:null?"#":data.pic_data,//图片数据,正常情况下应该是一个网址 
bd_data:null?"没有描述":data.bd_data//主题内容数据 
} 
//填充数据 
this.tip_title.innerHTML=this.data.hd_data; 
this.tip_bd.innerHTML=this.data.bd_data; 
this.tip_pic.innerHTML="" 
this.tip_pic.appendChild(this.loading_pic) 
var now_this=this; 
//填充图片 
this.pic=new Image(); 
this.pic.src=this.data.pic_data; 
this.pic.errorpic=new Image(); 
this.pic.errorpic.src="https://3water.com/logo.gif";//图片加载错误时显示的图片 
this.pic.onload=function(){ 
now_this.tip_pic.innerHTML=""; now_this.tip_pic.appendChild(this) 
now_this.updateSize({width:this.width+20}); 
} 
this.pic.onerror=function(){ 
now_this.tip_pic.innerHTML=""; 
now_this.tip_pic.appendChild(this.errorpic) 
now_this.updateSize({width:this.errorpic.width+20}); 
} 
this.updateSize(); 
},

到这里这个对象就结束了,是不是很简单,他已经很完整了,下面我们就来启动它,我们设置一些数据,然后随机地填充,每次点击页面都会填充不同的数据.
window.onload = function(){ 
AddLink.init({ 
class_name: "content" 
}); 
Tip.init(); 
document.body.onclick=function(){ 
Array.prototype.rand=function(){ 
return this[Math.round(Math.random()*(this.length-1))]; 
} 
var hd_arr=[ 
"我是随机的你信不信", 
"不信算了,点击页面我就会变了", 
"每点一次都会变", 
"也有可能重复的", 
"重复的我可不管饿,因为我是随机的" 
]; 
var pic_arr=[ 
"http://www.beiju123.cn/blog/wp-content/uploads/2009/12/2009-12-14-20-53-231.png", 
"http://www.beiju123.cn/blog/wp-content/uploads/2009/12/2009-12-15-23-51-45.png", 
"http://www.beiju123.cn/blog/wp-content/uploads/2009/12/2009-12-16-00-25-38.png", 
"http://www.beiju123.cn/blog/wp-content/uploads/2009/12/2009-12-14-23-25-171.png", 
"http://www.beiju123.cn/blog/wp-content/uploads/2009/12/2009-12-14-20-49-362.png", 
"http://dgdgdg.d" 
] 
var bd_arr=[ 
"最近听人说aptana这个ide不错,也支持我喜欢的ruby,而且对js和html,css支持也很好,我比较来比较去,还是喜欢netbeans,首先因为netbeans里有个插件,可以把着色的代码复制粘贴成html+css,而是代码着色aptana不好看,自己配又配不出感觉来,net串get什么什么的就行了.js已经是够简洁的语言了,提醒太多反而没什么意义,不过在netbeans里的YUI提示和我看的YUI不是一个版本的,全是错的,但是我还是喜欢netbeans多一点,其实编程这东西效率很难说高和低,思路理清楚了,自然效率高.程序写的很快的话,代码提示很智能的话,反而太依赖,对思路理解不深刻,写着后面忘了前面,效率反而慢了", 
"后可以做一些基本的处理,例如加个边框美化下,可以用画笔涂一下,这个比较有用,高清图上有字的背景图,可以涂掉就可以直接用了.下面说一下其他功能吧, 首先,最重磅的就是”标尺”,可以", 
"代码复制粘贴成html+css,而是代码着色aptana不好看,自己配又配不出感觉来,netbeans的界面也比较清爽,至于js提示,其实我从来就没用到过高级的提示,在netbeans里我只需要他在我输入document.的时候出来后面那一串get什么什么的就行了.js已经是够简洁的语言了,提醒太多反而没什么意义,不过在netbeans里的YUI提示和我看的YUI不是一个版本的,全是错的,但是我还是喜欢netbeans多一点,其实编程这东西效率很难说高", 
"这里我只拿我的几个比较宽泛的想法来谈自己对top平台的理解,为自己保留一条秘密,同时也跟大家分享自己的想法.现今社会,很多产业都已经趋向于饱和,例如:超市行业.在南京,苏果超市占据了绝对地位.随处可见其身影,当然也有类似华联和家乐福之类的超市经提供了上述服务了,但是我们可以通过来提供更多个性服务来增加自己的竞争力.我其实也正在策划做一个公益性的垂直搜索网站,可能会争取到政府的资金支持,但是目前我除了我女朋友还没有跟任何人透露过,如果有人对此感兴趣可以找我讨论." 
] 
var config={ 
hd_data:hd_arr.rand(), 
pic_data:pic_arr.rand(), 
bd_data:bd_arr.rand() 
} 
Tip.updateData(config); } 
}

演示地址:http://beiju123.cn/blog/addLink_1.html
作者:http://www.cnblogs.com/mars-bird
Javascript 相关文章推荐
基于jQuery的仿flash的广告轮播
Nov 05 Javascript
jqeury eval将字符串转换json的方法
Jan 20 Javascript
js代码实现的加入收藏效果并兼容主流浏览器
Jun 23 Javascript
jQuery操作cookie方法实例教程
Nov 25 Javascript
JS弹出新窗口被拦截的解决方法
Aug 09 Javascript
浅谈JS使用[ ]来访问对象属性
Sep 21 Javascript
jquery延迟对象解析
Oct 26 Javascript
JavaScript自定义文本框光标
Mar 05 Javascript
JS传参及动态修改页面布局
Apr 13 Javascript
Vue CLI3.0中使用jQuery和Bootstrap的方法
Feb 28 jQuery
vue组件中实现嵌套子组件案例
Aug 31 Javascript
react项目从新建到部署的实现示例
Feb 19 Javascript
javascript demo 基本技巧
Dec 18 #Javascript
IE和Firefox下event事件杂谈
Dec 18 #Javascript
替代window.event.srcElement效果的可兼容性的函数
Dec 18 #Javascript
JavaScript 序列化对象实现代码
Dec 18 #Javascript
让div层随鼠标移动的实现代码 ie ff
Dec 18 #Javascript
Javascript在IE或Firefox下获取鼠标位置的代码
Dec 18 #Javascript
javascript 导出数据到Excel(处理table中的元素)
Dec 18 #Javascript
You might like
显示程序执行时间php函数代码
2013/08/29 PHP
初识PHP
2014/09/28 PHP
set_exception_handler函数在ThinkPHP中的用法
2014/10/31 PHP
PHP使用in_array函数检查数组中是否存在某个值
2015/03/25 PHP
php简单实现多语言切换的方法
2016/05/09 PHP
php 使用ActiveMQ发送消息,与处理消息操作示例
2020/02/23 PHP
浏览器打开层自动缓慢展开收缩实例代码
2013/07/04 Javascript
javascript:void(0)的问题使用探讨
2014/04/10 Javascript
js Dialog 去掉右上角的X关闭功能
2014/04/23 Javascript
js实现当前输入框高亮显示的方法
2015/08/19 Javascript
JavaScript控制浏览器全屏及各种浏览器全屏模式的方法、属性和事件
2015/12/20 Javascript
jQuery实现页面点击后退弹出提示框的方法
2016/08/24 Javascript
Node.js对MongoDB数据库实现模糊查询的方法
2017/05/03 Javascript
学习JS中的DOM节点以及操作
2018/04/30 Javascript
Vue利用canvas实现移动端手写板的方法
2018/05/03 Javascript
JavaScript设计模式之模板方法模式原理与用法示例
2018/08/07 Javascript
Vue实现简易翻页效果源码分享
2018/11/08 Javascript
javascript设计模式 ? 备忘录模式原理与用法实例分析
2020/04/21 Javascript
JS实现网站楼层导航效果代码实例
2020/06/16 Javascript
vue使用require.context实现动态注册路由
2020/12/25 Vue.js
[06:20]2015国际邀请赛第三日top10
2015/08/08 DOTA
PyQt5打开文件对话框QFileDialog实例代码
2018/02/07 Python
Python Requests模拟登录实现图书馆座位自动预约
2018/04/27 Python
python统计中文字符数量的两种方法
2019/01/31 Python
python的内存管理和垃圾回收机制详解
2019/05/18 Python
python通过http下载文件的方法详解
2019/07/26 Python
Python笔记之观察者模式
2019/11/20 Python
python爬虫实现获取下一页代码
2020/03/13 Python
Django实现内容缓存实例方法
2020/06/30 Python
利用scikitlearn画ROC曲线实例
2020/07/02 Python
Nuts.com:优质散装,批发坚果、干果和巧克力等
2017/03/21 全球购物
教师爱岗敬业演讲稿
2014/05/05 职场文书
干部考察材料范文
2014/12/24 职场文书
团代会闭幕词
2015/01/28 职场文书
使用ORM新增数据在Mysql中的操作步骤
2021/07/26 MySQL
24年收藏2000多部退役军用电台
2022/02/18 无线电