仿qq新闻 按数据源均分时间点幻灯效果
var jsondata=[{...},{...},...];//数据源,一切皆因它而生,因它而灭
function itimepoint(itimeslideid, dateid, timelineid, titletop, titleid, defaultshow){
/* 传入参数说明:
* itimeslideid: 外围id名. 本样例dom中#itimeslide;
* dateid: 日期id名. 本样例dom中#date;
* timelineid: 时间点分布id名. 本样例dom中#timeline;
* titletop: 标题容器上方小三角id名. 本样例dom中#titletop;
* titleid: 标题容器id名. 本样例dom中#title;
* defaultshow: 设定初始显示的时间点, 默认为0, 可不传值
*/
//参数判断,测试用,成功运行后可删除
if (arguments.length < 5 || arguments.length>6) {
alert('参数传入错误,请传入5或6个值! :)');
return false;
}
//通用方法
var ibase = {
//document.getelementbyid
id: function(name){
return document.getelementbyid(name);
},
//时间点动画显示
pointslide: function(elem, val){
//可通过修改i+=5中的5控制滑动速度
for (var i = 0; i <= 100; i += 5) {
(function(){
//这个pos定义很重要,若直接使用闭包获取到的不是上面的i
var pos = i;
//平滑移动
settimeout(function(){
elem.style.left = pos * val / 100 + 'px';
}, (pos + 1) * 10);
})();
}
},
//为元素添加样式
addclass: function(elem, val){
//若元素无class,直接赋值
if (!elem.classname) {
elem.classname = val;
}else {
//否则通过添加空格新增一个class
var oval = elem.classname;
oval += ' ';
oval += val;
elem.classname = val;
}
},
//获取元素索引
index: function(cur, obj){
for (var i = 0; i < obj.length; i++) {
if (obj[i] == cur) {
return i;
}
}
}
}
//整个函数变量定义区
var datalen = jsondata.length;
var itimesilde = ibase.id(itimeslideid);
var date = ibase.id(dateid);
var timeline = ibase.id(timelineid);
var titletop = ibase.id(titletop);
var title = ibase.id(titleid);
var itimesildew = itimesilde.offsetwidth;//幻灯区实际宽度
var timepoint = document.createelement('ul');//用来存储时间点的ul
var timepointleft = null;//时间点相对于父元素左边距离
var timepointleftcur = null;//每两个时间点间距
var pointindex = 0;//时间点在队列中的索引值
var defaultshow = defaultshow || 0;//默认显示的时间
var clearfun=null;//当用户无意识的划过时中止执行
var that=null;
//根据数据条数生成对应的时间点html
for (var i = 0; i < datalen; i++) {
timepoint.innerhtml += '<li></li>';
}
//将时间点插入到时间线div中
timeline.appendchild(timepoint)
var timepoints = timeline.getelementsbytagname('li');
//时间点平滑显示
for (var i = 0; i < timepoints.length; i++) {
//每两个时间点间间距
timepointleftcur = parseint(itimesildew / (datalen + 1));
//计算对应时间点左边距
timepointleft = (i + 1) * timepointleftcur;
//时间点动画形式初始化
ibase.pointslide(timepoints[i], timepointleft);
//初始显示时间点
settimeout(function(){
timepoints[defaultshow].onmouseo教程ver();
}, 1200);
//获取时间点默认class值,为鼠标事件做准备
timepoints[i].oldclassname = timepoints[i].classname;
timepoints[i].onmouseover = function(){
that = this;//确保clearfun中的this是当前的this
//提升用户体验,当用户无意识地划过时不执行函数
clearfun=settimeout(function(){
//计算出当前时间点索引值,为鼠标划出做准备
pointindex = ibase.index(that, timepoints);
//去除上一个时间点高亮样式
for (var m = 0; m < timepoints.length; m++) {
if (m != pointindex) {
timepoints[m].classname = timepoints[m].oldclassname
}
}
//为当前时间点加载高亮样式
ibase.addclass(that, 'hover');
//切换日期及标题值
date.innerhtml = '<span>' + (jsondata[pointindex]['date'] || '') + '</span><em></em>';
title.innerhtml = '<a href="' + (jsondata[pointindex]['href'] || '') + '">' + (jsondata[pointindex]['title'] || '') + '</a>';
//改变日期及标题的位置,此处减去的数字,可根据实际样式调整
date.style.left = ((pointindex + 1) * timepointleftcur - 25) + 'px';
titletop.style.left = ((pointindex + 1) * timepointleftcur + 6) + 'px';
//当标题框左边距与标题框宽度之和大于外围宽度时,以右边为绝对点
if ((title.offsetwidth + (pointindex + 1) * timepointleftcur) < itimesildew) {
title.style.left = ((pointindex + 1) * timepointleftcur - timepointleftcur) + 'px';
}else {
title.style.left = (itimesildew - title.offsetwidth) + 'px';
}
//显示日期/时间点/标题
date.style.display = 'block';
titletop.style.display = 'block';
title.style.display = 'block';
},200);//200为认定无意识划过的时间,可自行调节
}
timepoints[i].onmouseout = function(){
//若停留时间低于200ms,认定为无意识划过,中止函数
cleartimeout(clearfun);
}
}
}
腾讯新闻详情页有一个事件进展效果, 觉得挺有意思. 于是, 就有了本文的效果: 按数据源均分时间点幻灯. 花了三个多小时写的, 当然, 包括样式与调试. 兼容主流, 建议在chrom,firefox,opera,safari等标准浏览器中查看. ie下没有阴影及圆角.
实现了根据源数据(样例中是一个json数据组)总条数, 均分出时间点以平滑向右动画方式显示在时间线上, 当鼠标划过时间点时, 显示对应的日期及标题. 鼠标划过事件, 充分考虑了用户体验, 当用户快速(无意识移动)从时间点上划
看整个实例源码。
<style>
#itimeslide{position:relative;margin:0 20px;padding:15px 0}
#itimeslide #date{display:none;position:absolute;left:74px;top:3px;width:70px}
#itimeslide #date span{display:block;height:14px;padding:0 3px;background:#4e7db3;color:#fff;font-size:12px;line-height:14px}
#itimeslide #date em{display:block;width:5px;height:3px;margin:0 auto;background:url(yun_qi_img/20101224sprite.gif) no-repeat -61px 0}
#itimeslide #timeline{overflow:visible;width:100%;height:2px;margin:16px 0 20px;background:#c7c7c7}
#itimeslide #timeline li{display:block;position:absolute;left:0;top:24px;width:17px;height:17px;background:url(yun_qi_img/20101224sprite.gif) no-repeat 0 0;text-indent:-999px;cursor:pointer}
#itimeslide #timeline li.hover{background-position:-20px 0}
#itimeslide span#titletop{display:none;position:absolute;top:45px;width:12px;height:8px;background:url(yun_qi_img/20101224sprite.gif) no-repeat -88px -21px;z-index:1}
#itimeslide #title{display:none;position:absolute;top:52px;padding:15px 10px;background:#f8f8ff;border:1px solid #708bab;border-radius:5px;-weblit-border-radius:5px;-moz-border-radius:5px;-webkit-box-shadow:3px 3px 3px #c7c7c7;
-moz-box-shadow:3px 3px 3px #c7c7c7}
</style>
<script>
/*******************************
* @author mr.think
* @author blog http://mrthink.net/
* @2010.12.24
* @可自由转载及使用,但请注明版权归属
*******************************/
//原数据 json :) 一般是由后台传入的
var jsondata=[
{'date':'2010-12-25','title':'原生js实现按数据源均分时间点幻灯片','href':'http://mrthink.net/'},
{'date':'2010-11-01','title':'原生js获取元素样式属性值的方法','href':'http://mrthink.net/'},
{'date':'2010-10-22','title':'纯css教程实现列表鼠标划过变色','href':'http://mrthink.net/'},
{'date':'2010-09-23','title':'实现checkbox的全选/全不选/点选/行内点选','href':'http://mrthink.net/'},
{'date':'2010-09-05','title':'js计时器settimeout()与setinterval()方法的区别','href':'http://mrthink.net/'},
{'date':'2010-06-07','title':'加载xml文档的函数(原生网页特效版及jquery版)','href':'http://mrthink.net/'},
{'date':'2010-05-09','title':'限制字符输入数功能(jq版和原生js版)','href':'http://mrthink.net/'},
{'date':'2010-04-13','title':'奇或偶数行高亮显示及鼠标划过高亮显示类','href':'http://mrthink.net/'},
{'date':'2010-03-01','title':'结构/表现/行为完全分离的选项卡(jq版和原生js版)','href':'http://mrthink.net/'},
{'date':'2010-02-22','title':'简易的点击展开/关闭效果(原生js版和jq版)','href':'http://mrthink.net/'},
{'date':'2010-02-01','title':'网站基本优化:php教程的gzip压缩方法','href':'http://mrthink.net/'},
{'date':'2010-01-20','title':'基于jquery的渐隐渐显图片轮换幻灯片','href':'http://mrthink.net/'}
];
function itimepoint(itimeslideid, dateid, timelineid, titletop, titleid, defaultshow){
/* 传入参数说明:
* itimeslideid: 外围id名. 本样例dom中#itimeslide;
* dateid: 日期id名. 本样例dom中#date;
* timelineid: 时间点分布id名. 本样例dom中#timeline;
* titletop: 标题容器上方小三角id名. 本样例dom中#titletop;
* titleid: 标题容器id名. 本样例dom中#title;
* defaultshow: 设定初始显示的时间点, 默认为0, 可不传值
*/
//参数判断,测试用,成功运行后可删除
if (arguments.length < 5 || arguments.length>6) {
alert('参数传入错误,请传入5或6个值! :)');
return false;
}
//通用方法
var ibase = {
//document.getelementbyid
id: function(name){
return document.getelementbyid(name);
},
//时间点动画显示
pointslide: function(elem, val){
//可通过修改i+=5中的5控制滑动速度
for (var i = 0; i <= 100; i += 5) {
(function(){
//这个pos定义很重要,若直接使用闭包获取到的不是上面的i
var pos = i;
//平滑移动
settimeout(function(){
elem.style.left = pos * val / 100 + 'px';
}, (pos + 1) * 10);
})();
}
},
//为元素添加样式
addclass: function(elem, val){
//若元素无class,直接赋值
if (!elem.classname) {
elem.classname = val;
}else {
//否则通过添加空格新增一个class
var oval = elem.classname;
oval += ' ';
oval += val;
elem.classname = val;
}
},
//获取元素索引
index: function(cur, obj){
for (var i = 0; i < obj.length; i++) {
if (obj[i] == cur) {
return i;
}
}
}
}
//整个函数变量定义区
var datalen = jsondata.length;
var itimesilde = ibase.id(itimeslideid);
var date = ibase.id(dateid);
var timeline = ibase.id(timelineid);
var titletop = ibase.id(titletop);
var title = ibase.id(titleid);
var itimesildew = itimesilde.offsetwidth;//幻灯区实际宽度
var timepoint = document.createelement('ul');//用来存储时间点的ul
var timepointleft = null;//时间点相对于父元素左边距离
var timepointleftcur = null;//每两个时间点间距
var pointindex = 0;//时间点在队列中的索引值
var defaultshow = defaultshow || 0;//默认显示的时间
var clearfun=null;//当用户无意识的划过时中止执行
var that=null;
//根据数据条数生成对应的时间点html
for (var i = 0; i < datalen; i++) {
timepoint.innerhtml += '<li></li>';
}
//将时间点插入到时间线div中
timeline.appendchild(timepoint)
var timepoints = timeline.getelementsbytagname('li');
//时间点平滑显示
for (var i = 0; i < timepoints.length; i++) {
//每两个时间点间间距
timepointleftcur = parseint(itimesildew / (datalen + 1));
//计算对应时间点左边距
timepointleft = (i + 1) * timepointleftcur;
//时间点动画形式初始化
ibase.pointslide(timepoints[i], timepointleft);
//初始显示时间点
settimeout(function(){
timepoints[defaultshow].onmouseover();
}, 1200);
//获取时间点默认class值,为鼠标事件做准备
timepoints[i].oldclassname = timepoints[i].classname;
timepoints[i].onmouseover = function(){
that = this;//确保clearfun中的this是当前的this
//提升用户体验,当用户无意识地划过时不执行函数
clearfun=settimeout(function(){
//计算出当前时间点索引值,为鼠标划出做准备
pointindex = ibase.index(that, timepoints);
//去除上一个时间点高亮样式
for (var m = 0; m < timepoints.length; m++) {
if (m != pointindex) {
timepoints[m].classname = timepoints[m].oldclassname
}
}
//为当前时间点加载高亮样式
ibase.addclass(that, 'hover');
//切换日期及标题值
date.innerhtml = '<span>' + (jsondata[pointindex]['date'] || '') + '</span><em></em>';
title.innerhtml = '<a href="' + (jsondata[pointindex]['href'] || '') + '">' + (jsondata[pointindex]['title'] || '') + '</a>';
//改变日期及标题的位置,此处减去的数字,可根据实际样式调整
date.style.left = ((pointindex + 1) * timepointleftcur - 25) + 'px';
titletop.style.left = ((pointindex + 1) * timepointleftcur + 6) + 'px';
//当标题框左边距与标题框宽度之和大于外围宽度时,以右边为绝对点
if ((title.offsetwidth + (pointindex + 1) * timepointleftcur) < itimesildew) {
title.style.left = ((pointindex + 1) * timepointleftcur - timepointleftcur) + 'px';
}else {
title.style.left = (itimesildew - title.offsetwidth) + 'px';
}
//显示日期/时间点/标题
date.style.display = 'block';
titletop.style.display = 'block';
title.style.display = 'block';
},200);//200为认定无意识划过的时间,可自行调节
}
timepoints[i].onmouseout = function(){
//若停留时间低于200ms,认定为无意识划过,中止函数
cleartimeout(clearfun);
}
}
}//样例加载该函数
window.onload = function(){
itimepoint('itimeslide', 'date', 'timeline', 'titletop','title');
}</script>
<div id="demo">
<div id="itimeslide">
<div id="date"></div>
<div id="timeline"></div>
<span id="titletop"></span>
<div id="title"></div>
</div>
</div>