js 代码
- var GDnew=function(){}//1
- GDnews.Effect=function(){};//2
- //上面两个方法是为了扩大命名空间
- GDnews.Effect.MoveSpeed=Class.create();
- GDnews.Effect.MoveSpeed.prototype={
- initialize:function(element) {
- this.element = $(element);
- this.options = Object.extend({
- x: 0,
- y: 0,
- mode: 'relative',
- delay:85,
- amountX:0,
- amountY:0
- }, arguments[1] || {});
- this.event("beforeSetup");
- this.options.amountX=Math.abs(this.options.amountX);
- this.options.amountY=Math.abs(this.options.amountY);
- this.scroX=0;//目前已经移动的X数目
- this.scroY=0;//目前已经移动的Y数目
- // Bug in Opera: Opera returns the "real" position of a static element or
- // relative element that does not have top/left explicitly set.
- // ==> Always set top and left for position relative elements in your stylesheets
- // (to 0 if you do not need them)
- this.element.makePositioned();
- this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
- this.originalTop = parseFloat(this.element.getStyle('top') || '0');
- if(this.options.mode == 'absolute') {
- // absolute movement, so we need to calc deltaX and deltaY
- this.options.x = this.options.x - this.originalLeft;
- this.options.y = this.options.y - this.originalTop;
- }
- this.event("afterSetup");
- this.scroll();
- },
- update: function() {
- this.event("beforeUpdate");
- var _x=Math.abs(this.options.x);
- var _y=Math.abs(this.options.y)
- var amountX=(this.scroX+this.options.amountX)>=_x ?
- (_x-this.scroX/*归零*/) : this.options.amountX;
- var amountY=(this.scroY+this.options.amountX)>=_y ?
- (_y-this.scroY/*归零*/) : this.options.amountY;
- this.scroX+=amountX;//执行X总数累加
- this.scroY+=amountY;//执行Y总数累加
- this.element.setStyle({
- left:Math.round(this.originalLeft+(this.options.x<0 ? -this.scroX : this.scroX)) + 'px',
- top:Math.round(this.originalTop+(this.options.y<0 ? -this.scroY : this.scroY)) + 'px'
- });
- this.event("beforeFinish");
- if (amountX==0 && amountY==0){//结束
- this.scroY=0;
- this.scroX=0;
- this.cancel();
- this.event("afterFinish");
- }
- },
- scroll:function(){
- this.cancel();
- this.setTimeInt=window.setInterval(this.update.bind(this),this.options.delay);
- },
- cancel:function(){
- if(this.setTimeInt) window.clearInterval(this.setTimeInt);
- this.setTimeInt=null;
- },
- event: function(eventName) {
- if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
- if(this.options[eventName]) this.options[eventName](this);
- }
- }
- 在这个类的基础上,再写一个实现marquee的类:
- GDnews.w3cMarquee=Class.create();
- /**
- *@param element 目标的marquee标签
- *@ nomouseEvent 默认为false,类似传统marquee上的onMouseover=this.stop()系列行为
- *此方法在IE中不执行。思路是把marquee删除,用一个div代替它,然后设置此div的left和top来实现滚动。
- */
- GDnews.w3cMarquee.prototype={//目前仅实现behavior=scroll
- initialize:function(element,nomouseEvent){
- if(/MSIE/.test(navigator.userAgent)){//如果是IE,留着真marquee
- if(nomouseEvent==true) return;
- element=$(element);
- Event.observe(element,'mouseover',function(){element.stop()});
- Event.observe(element,'mouseout',function(){element.start()});
- return;
- }
- this.marquee=$(element);
- if("marquee"!=this.marquee.tagName.toLowerCase()) return;
- this._createDiv();//创建DIV
- this.makePosition();//设置位置
- var _x=this.scrollWidth;
- var _y=this.scrollHeight;
- var newElementId=this.newElementId;
- var options={x:_x,y:_y,delay:this.scrollDelay,
- amountX:this.scrollAmount,amountY:this.scrollAmount,
- beforeSetup:function(effect){
- if(nomouseEvent==true) return;
- var cancel=effect.cancel.bind(effect);
- var scroll=effect.scroll.bind(effect);
- Event.stopObserving(newElementId,'mouseover',cancel);
- Event.stopObserving(newElementId,'mouseout',scroll);
- Event.observe(newElementId,'mouseover',cancel);
- Event.observe(newElementId,'mouseout',scroll);
- },
- beforeUpdate:function(effect){
- // if(behavior=='alternate'){//本想实现'alternate'行为,但由于时间关系,我就把它先留着。
- // var left=parseInt(effect.element.getStyle('left'));
- // var top=parseInt(effect.element.getStyle('top'));
- // see(left+","+top);
- // if(effect.scroX>=_parentWidth || effect.scroY>_parentHeight){
- // effect.options.x=-1*effect.options.x;
- // effect.options.y=-1*effect.options.y;
- // effect.cancel();
- // window.setTimeout(effect.scroll.bind(effect),100);
- // }
- // }
- },
- afterFinish:function(effect){
- /*if(behavior=='scroll'){*/
- effect.element.setStyle({left:effect.originalLeft,top:effect.originalTop});
- window.setTimeout(effect.scroll.bind(effect),100);
- /*}*/
- }
- };
- new GDnews.Effect.MoveSpeed(this.scrollId,options);
- },
- _createDiv:function(){
- this.newElementId=(this.marquee.id || "_marquee")+"_"+(new Date().getTime());
- var _attribute=$A(this.marquee.attributes);
- this.divEl=document.createElement('div');
- this.divEl.id=this.newElementId;
- this.scrollId=(this.marquee.id || "_marquee")+"_child_"+(new Date().getTime());
- this.scrollEl=document.createElement('div');
- this.scrollEl.id=this.scrollId;
- try{
- this.marquee.parentNode.insertBefore(this.divEl,this.marquee);//新建一个node
- this.divEl.appendChild(this.scrollEl);//一个用于滚动的node
- _attribute.each(function(d,i){//把其它属性放回去
- var key=d.nodeName.toLowerCase();
- var nodeValue=d.nodeValue;
- if(typeof nodeValue=='object' || typeof nodeValue=='function'
- || nodeValue=='' || nodeValue==null || key=='truespeed' || key=='id') return;
- switch (key){
- case 'direction':
- this.direction=nodeValue;
- return;
- break;
- case 'scrolldelay':
- this.scrollDelay=parseInt(nodeValue);
- return;
- break;
- case 'scrollamount':
- this.scrollAmount=parseInt(nodeValue);
- return;
- break;
- case 'behavior':
- this.behavior=nodeValue;
- return;
- break;
- case 'loop':
- this.loop=parseInt(nodeValue);
- return;
- break;
- }
- this.divEl.setAttribute(key,nodeValue);//IE中只有className而没有class
- }.bind(this));
- $A(this.marquee.childNodes).each(function(d){//把子元素放回去
- if(d.length!=1/*这是个长为1的textNode*/) this.scrollEl.appendChild(d);
- }.bind(this));
- this.selfWidth=parseInt($(this.scrollEl).offsetWidth);
- this.selfHeight=parseInt($(this.scrollEl).offsetHeight);
- }catch(e){
- throw e;
- }
- Element.remove(this.marquee);//结束真marquee的使命
- },
- makePosition:function(){
- $(this.newElementId).makeClipping();
- var scrollEl=$(this.scrollEl);
- scrollEl.makePositioned();
- this.originalLeft = parseFloat(this.scrollEl.getStyle('left') || '0');
- this.originalTop = parseFloat(this.scrollEl.getStyle('top') || '0');
- this.loop = this.loop || -1;
- this.scrollDelay = this.scrollDelay || 85;
- this.scrollAmount = this.scrollAmount || 6;
- this.direction = this.direction || 'left';
- this.behavior = this.behavior || 'scroll';
- if(window.opera) {//fix opera。Opera对marquee标签有不同的解释
- switch (this.direction){
- case '128':
- this.direction='left';
- break;
- case '129':
- this.direction='right';
- break;
- case '164':
- this.direction='up';
- break;
- case '165':
- this.direction='down';
- break;
- }
- if(this.behavior='137') this.behavior='scroll';
- if(this.behavior='138') this.behavior='alternate';
- else this.behavior='slide';
- }
- this.behavior = this.behavior || 'scroll';
- this.parentWidth = parseInt(this.divEl.offsetWidth);
- this.parentHeight = parseInt(this.divEl.offsetHeight)
- this.scrollWidth = this.parentWidth+this.selfWidth;
- this.scrollHeight = this.parentHeight+this.selfHeight;
- var topLeft={};
- switch (this.direction){
- case 'up':
- this.scrollWidth=0;
- this.scrollHeight=-this.scrollHeight;
- topLeft={top:this.parentHeight+"px",left:this.originalLeft+"px"};
- break;
- case 'down':
- this.scrollWidth=0;
- topLeft={top:(-this.selfHeight-this.originalTop)+"px",left:this.originalLeft+"px"};
- break;
- case 'right':
- this.scrollHeight=0;
- topLeft={top:this.originalTop+"px" ,left:-this.selfWidth+"px"};
- break;
- default:
- this.scrollHeight=0;
- this.scrollWidth=-this.scrollWidth;
- topLeft={top:this.originalTop+"px",left:this.parentWidth+"px"};
- }
- scrollEl.setStyle(topLeft);
- scrollEl.show();
- }
- }
- GDnews.w3cMarquee.initAll=function(){
- var marquees=$A(document.getElementsByTagName('marquee'));
- marquees.each(function(d){new GDnews.w3cMarquee(d);});
- }