来自腾讯的一个不固定高度得消息的滚动特效

   [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

  看关键的js code:

  

复制代码 代码如下:

  var $ = function (d){

  typeof d == "string" &&(d = document.getElementById(d));

  return $.fn.call(d);

  };

  $.fn = function (){

  this.addEvent = function (sEventType,fnHandler){

  if (this.addEventListener) {this.addEventListener(sEventType, fnHandler, false);}

  else if (this.attachEvent) {this.attachEvent("on" + sEventType, fnHandler);}

  else {this["on" + sEventType] = fnHandler;}

  }

  this.removeEvent = function (sEventType,fnHandler){

  if (this.removeEventListener) {this.removeEventListener(sEventType, fnHandler, false);}

  else if (this.detachEvent) {this.detachEvent("on" + sEventType, fnHandler);}

  else { this["on" + sEventType] = null;}

  }

  return this;

  };

  var Class = {create: function() {return function() { this.initialize.apply(this, arguments); }}};

  var Bind = function (obj,fun,arr){return function() {return fun.apply(obj,arr);}}

  var Marquee = Class.create();

  Marquee.prototype = {

  initialize: function(id,name,out,speed) {

  this.name = name;

  this.box = $(id);

  this.out = 3;//滚动间隔时间,单位秒

  this.speed = speed;

  this.d = 1;

  this.box.style.position = "relative";

  this.box.scrollTop = 0;

  var _li = this.box.firstChild;

  while(typeof(_li.tagName)=="undefined")_li = _li.nextSibling;

  this.lis = this.box.getElementsByTagName(_li.tagName);

  this.len = this.lis.length;

  for(var i=0;i<this.lis.length;i++){

  var __li = document.createElement(_li.tagName);

  __li.innerHTML = this.lis[i].innerHTML;

  this.box.appendChild(__li);//cloneNode

  if(this.lis[i].offsetTop>=this.box.offsetHeight)break;

  }

  this.Start();

  this.box.addEvent("mouseover",Bind(this,function(){clearTimeout(this.timeout);},[]));

  this.box.addEvent("mouseout",Bind(this,this.Start,[]));

  },

  Start:function (){

  clearTimeout(this.timeout);

  this.timeout = setTimeout(this.name+".Up()",this.out*1000)

  },

  Up:function(){

  clearInterval(this.interval);

  this.interval = setInterval(this.name+".Fun()",10);

  },

  Fun:function (){

  this.box.scrollTop+=this.speed;

  if(this.lis[this.d].offsetTop <= this.box.scrollTop){

  clearInterval(this.interval);

  this.box.scrollTop = this.lis[this.d].offsetTop;

  this.Start();

  this.d++;

  }

  if(this.d >= this.len + 1){

  this.d = 1;

  this.box.scrollTop = 0;

  }

  }

  };

  $(window).addEvent("load",function (){

  marquee = new Marquee("msg_weibo","marquee",1,2);

  });

  实现思路与以前的文字滚动是一样的,都是先充满当前容器,再通过scrollTop++往上滚的,只不过他是每次滚动的距离不是固定的,是取当前滚动消息的高度。由于scrollTop(滚出当前可视区域的高度)和offsetTop(距离父节点顶部的距离,常用于取某元素在页面的坐标位置)的区别,所以通过 if(this.lis[this.d].offsetTop <= this.box.scrollTop)来判断是否滚动完上条消息,需要停顿下了。

  我觉得亮点之处在于$的写法。通常Prototype里也就取下obj||document.getElementById('objId'),他这里除此外还帮obj绑定了一些方法。他的作用是不是类似于原型扩展String、Array等对象的方法呢。这个可以借鉴。

  另外,他初始化时填充容器时用document.createElement->赋innerHTML->appendChild来做,我觉的不如直接cloneNode(true)->appendChild好,如不对,欢迎指正。

  主要还是填下这个月的坑,哈哈。