String.prototype.parseColor()
string=rgb(12,34,56)、#444(只有三位数),把string转化成#xxxxxx。之所以这么表达,是要表达清这个函数是实例函数还是静态函数。很多资料上讲来讲去,我们还是不清楚这个是个什么类型的函数。这样一写不就清楚了吗。
Element.collectTextNodes = function(element)
把element的所有文本内容全部收集起来。
Element.collectTextNodesIgnoreClass = function(element, className)
收集element中类名不是className的节点中的所有文本,并连成一片。与element.innerText差不多。
Element.setContentZoom = function(element, percent)
通过设置fontsize=x%em来达到缩放内容的目的。
Element.getInlineOpacity = function(element)
设置透明度,不兼容ie。可能是故意不兼容的。用的是:element.style.opacity。
Element.forceRerendering = function(element)
强制刷新element的内容。原理就是加一个空格文本节点再删除这个文本节点。
string=rgb(12,34,56)、#444(只有三位数),把string转化成#xxxxxx。之所以这么表达,是要表达清这个函数是实例函数还是静态函数。很多资料上讲来讲去,我们还是不清楚这个是个什么类型的函数。这样一写不就清楚了吗。
Element.collectTextNodes = function(element)
把element的所有文本内容全部收集起来。
Element.collectTextNodesIgnoreClass = function(element, className)
收集element中类名不是className的节点中的所有文本,并连成一片。与element.innerText差不多。
Element.setContentZoom = function(element, percent)
通过设置fontsize=x%em来达到缩放内容的目的。
Element.getInlineOpacity = function(element)
设置透明度,不兼容ie。可能是故意不兼容的。用的是:element.style.opacity。
Element.forceRerendering = function(element)
强制刷新element的内容。原理就是加一个空格文本节点再删除这个文本节点。
- //创建一个全局变量。
- var Effect = {
- //定义一个错误提示文本
- _elementDoesNotExistError: {
- name: 'ElementDoesNotExistError',
- message: 'The specified DOM element does not exist, but is required for this effect to operate'
- },
- //顾名思意:Transitions是转换的意思,它定义一些转换函数。
- Transitions: {
- linear: Prototype.K,
- sinoidal: function(pos) {
- return (-Math.cos(pos*Math.PI)/2) + 0.5;
- },
- reverse: function(pos) {
- return 1-pos;
- },
- flicker: function(pos) {
- var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
- return pos > 1 ? 1 : pos;
- },
- wobble: function(pos) {
- return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
- },
- pulse: function(pos, pulses) {
- pulses = pulses || 5;
- return (
- ((pos % (1/pulses)) * pulses).round() == 0 ?
- ((pos * pulses * 2) - (pos * pulses * 2).floor()) :
- 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor())
- );
- },
- spring: function(pos) {
- return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
- },
- none: function(pos) {
- return 0;
- },
- full: function(pos) {
- return 1;
- }
- },
- DefaultOptions: {
- duration: 1.0, //以秒为单位
- fps: 100, //每秒的桢数,最小只能是66kps。为什么是这样,这是因为队列中触发间隔时15ms。
- sync: false, //为true则为异步动画。
- from: 0.0, //这个玩意起始百分数
- to: 1.0, //终点百分数
- delay: 0.0, //动画在起动后延迟的时间。
- queue: 'parallel' //要加入的动画队列。
- },
- //为element中的每一个字符都加上标记,用span括起来。
- tagifyText: function(element) {
- var tagifyStyle = 'position:relative';
- if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
- element = $(element);
- //用element.childNodes的方法取得所有节点,正是方便啊。
- $A(element.childNodes).each( function(child) {
- //nodeType=1是元素节点,3为文本节点。2是属性节点。一般都只用到1,2。
- if (child.nodeType==3) {
- child.nodeValue.toArray().each( function(character) {
- element.insertBefore(
- new Element('span', {style: tagifyStyle}).update(
- character == ' ' ? String.fromCharCode(160) : character),
- child);
- });
- Element.remove(child);
- }
- });
- },
- //element可以是一个元素数组,也可是一个元素节点,如果是单个元素,则会自动获取此元素下面的所有子节点,针对子节点施加特效。
- multiple: function(element, effect) {
- var elements;
- if (((typeof element == 'object') ||
- Object.isFunction(element)) &&
- (element.length))
- elements = element;
- else
- elements = $(element).childNodes;
- //此函数还允计有第三个参数,用于传入options。
- var options = Object.extend({
- speed: 0.1,
- delay: 0.0
- }, arguments[2] || { });
- var masterDelay = options.delay;
- //为数组中的每个元素都创建动画,并且,依次设定delay。delay按index成线性增长。
- $A(elements).each(function(element, index) {
- new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
- });
- },
- //这个JSON为下面的toggle函数准备的。
- PAIRS: {
- 'slide': ['SlideDown','SlideUp'],
- 'blind': ['BlindDown','BlindUp'],
- 'appear': ['Appear','Fade']
- },
- //用于反转特效,能反转三类特效,这三类特效都有一个特点,要么让元素可见,要么让元素隐藏。用法如下:
- //Effect.toggle(element)当元素可见时则调用fade,如果不可见则调用appear。就这么容易。
- //可以传入第三个参数options。
- toggle: function(element, effect) {
- element = $(element);
- effect = (effect || 'appear').toLowerCase();
- var options = Object.extend({
- //关于特效所加入队列的设置:position是加上位置,scope是队列名,limit是特效在队列中的极限位置。
- queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
- }, arguments[2] || { });
- Effect[element.visible() ?
- Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
- }
- };
- //设置默认转换函数。
- Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
- //特效队列
- Effect.ScopedQueue = Class.create(Enumerable, {
- //构造函数
- initialize: function() {
- //用于放特效对象的数组
- this.effects = [];
- //定时器的句柄
- this.interval = null;
- },
- //要从Enumerable继承就非得要实现这个_each函数
- _each: function(iterator) {
- this.effects._each(iterator);
- },
- //将特效对象加入到this.effects中
- add: function(effect) {
- //返回自70/1/1 0:0:0至今的毫秒数
- var timestamp = new Date().getTime();
- var position = Object.isString(effect.options.queue) ?
- effect.options.queue : effect.options.queue.position;
- switch(position) {
- case 'front':
- // 让那些没有开始的特效在这个特效之后发生。
- this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
- e.startOn += effect.finishOn;
- e.finishOn += effect.finishOn;
- });
- break;
- case 'with-last':
- //让特效与队列中最后一个特效同时发生。
- timestamp = this.effects.pluck('startOn').max() || timestamp;
- break;
- case 'end':
- // 在队列最后一个特效之后发生,这个pluck函数好用啦。
- timestamp = this.effects.pluck('finishOn').max() || timestamp;
- break;
- }
- //设特效的起始时间
- effect.startOn += timestamp;
- effect.finishOn += timestamp;
- //如果没有极限位置设置或者数组大小没有超过极限位置,则在队列中加入此特效
- if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
- this.effects.push(effect);
- //如果没有启动定时器,则启动定时器,并把句柄返回给this.interval属性。
- if (!this.interval)
- this.interval = setInterval(this.loop.bind(this), 15);
- },
- //移除特效
- remove: function(effect) {
- //reject的作用是把条件函数返回假时的成员的数组
- this.effects = this.effects.reject(function(e) { return e==effect });
- if (this.effects.length == 0) {
- clearInterval(this.interval);
- this.interval = null;
- }
- },
- //定时器每次被触发,都执行的玩意,每触发一次就给特效数组循环一次,哪个的特效的时间到了,就让它工作去了。
- loop: function() {
- var timePos = new Date().getTime();
- for(var i=0, len=this.effects.length;i<len;i++)
- this.effects[i] && this.effects[i].loop(timePos);
- }
- });
- //特效队列的容器,因为一个页面中,可能为了管理许多的特效,而将一些特效放在一个特定的队列中。也方便管理嘛。
- Effect.Queues = {
- instances: $H(),
- get: function(queueName) {
- if (!Object.isString(queueName)) return queueName;
- return this.instances.get(queueName) ||
- this.instances.set(queueName, new Effect.ScopedQueue());
- }
- };
- //页面的全局队列,默认情况下,如果一个特效没有定义其所属队列的名称,则把它们放到Effect.Queue中。
- Effect.Queue = Effect.Queues.get('global');
- //传说中的特效类的基类,所有特效都是从它继承过去的。这个东西是关键所在了。
- Effect.Base = Class.create({
- //position的取值、意义前面有讲到了,可取值为:front、with-last、end。
- position: null,
- //这个函数是关键的关键,只要去后面的代码中看一看,一个特效的关键代码在它的initialize中,initialize的思路无非就是先设一下options,然后再setup一下,setup说到底就是设一些某些特效特有的属性,以供update函数中使用。
- start: function(options) {
- //产生字符串形式的事件触发代码
- function codeForEvent(options,eventName){
- return (
- (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
- (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
- );
- }
- //如果传入options为false,则设其pos求取函数为线性函数
- if (options && options.transition === false) options.transition = Effect.Transitions.linear;
- this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
- this.currentFrame = 0; //当前桢
- this.state = 'idle'; //当前状态,有三种状态:idle、running、finished
- this.startOn = this.options.delay*1000; //开始时间
- this.finishOn = this.startOn+(this.options.duration*1000); //结束时间
- this.fromToDelta = this.options.to-this.options.from; //变化的差值:from-to
- this.totalTime = this.finishOn-this.startOn; //总共运行的时间,以毫秒为单位,不同于duration是以秒为单位。
- this.totalFrames = this.options.fps*this.options.duration; //总共的桢数
- //创建render成员函数,一切的关键都在这儿了,用它来更新视图、界面。它做了哪些事呢?
- //如果状态是:idle,则执行beforeSetup、setUp、afterSetup,如果是running的话,就通过transition来求pos,然后是beforeUpdate、update、afterUpdate。
- //如果状态为finished,自然是啥都不执行。canel的实质就是把状态变量变成finished而己。这样做确实存在很多问题。因为中途退出跟正常结束的标志是一样的。事实上,这是两个不同的状态。框架没有对此进行细分。因此,大伙在网上查到的那个教程,里面提到canel后还执行那个afterstart的事件这个bug。这其实还只是一般分后果,所以啊,不研究代码,你就不晓得这个后果有哪些,说也说不清楚,网上也没有这个资料,这年头,还得靠自己。
- eval('this.render = function(pos){ '+
- 'if (this.state=="idle"){this.state="running";'+
- codeForEvent(this.options,'beforeSetup')+
- (this.setup ? 'this.setup();':'')+
- codeForEvent(this.options,'afterSetup')+
- '};if (this.state=="running"){'+
- 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
- 'this.position=pos;'+
- codeForEvent(this.options,'beforeUpdate')+
- (this.update ? 'this.update(pos);':'')+
- codeForEvent(this.options,'afterUpdate')+
- '}}');
- this.event('beforeStart');
- if (!this.options.sync)
- Effect.Queues.get(Object.isString(this.options.queue) ?
- 'global' : this.options.queue.scope).add(this);
- },
- loop: function(timePos) {
- //如果是最后一桢
- if (timePos >= this.startOn) {
- if (timePos >= this.finishOn) {
- this.render(1.0);
- this.cancel();
- this.event('beforeFinish');
- if (this.finish) this.finish();
- this.event('afterFinish');
- return;
- }
- var pos = (timePos - this.startOn) / this.totalTime,
- frame = (pos * this.totalFrames).round();
- if (frame > this.currentFrame) {
- //呈现当前视图
- this.render(pos);
- //这个当前桢数是摆看的,没有真正用于计算,真正用于计算的只有pos。
- this.currentFrame = frame;
- }
- }
- },
- //取消特效
- cancel: function() {
- if (!this.options.sync)
- Effect.Queues.get(Object.isString(this.options.queue) ?
- 'global' : this.options.queue.scope).remove(this);
- this.state = 'finished';
- },
- //触发事件处理函数
- event: function(eventName) {
- if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
- if (this.options[eventName]) this.options[eventName](this);
- },
- //相当于tostring。
- inspect: function() {
- var data = $H();
- for(property in this)
- if (!Object.isFunction(this[property])) data.set(property, this[property]);
- return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
- }
- });