1 (function(window,undefined){ 2 var arr = [], 3 push = arr.push, 4 slice = arr.slice; 5 //首先要做的就是封装一个parseHtml函数 6 //要注意的是,parthHtml要放在一个自调用函数内 7 var parseHtml = (function(){ 8 //做一个模板 9 var div = document.createElement('div'); 10 //这个函数是用来创建标签 11 function parseHtml(html){ 12 var res = []; 13 //这边是将具有html语义的字符串放在模板div中,div里面的就有这些标签了 14 div.innerHTML = html; 15 //这个时候div里有标签元素,循环遍历div里面的元素 16 for(var i = 0;i < div.childNodes.length;i++){ 17 //这边是将div模板里面的元素一一放到res数组里,因为这边的div.childNodes[i]是单个元素,可以直接push进数组 18 res.push(div.childNodes[i]); 19 } 20 //完成之后,将div里面的元素清除掉,方便下一次使用 21 div.innerHTML = ''; 22 //将这个数组返回 23 return res; 24 } 25 return parseHtml; 26 })(); 27 //封装insertBefore方法 28 function prependChild(parent,element){//传入的元素是父元素,要插入的元素 29 var first = parent.firstChild;//将父元素中的第一个元素取出来 30 parent.insertBefore(element,first);//使用insertBefore方法将element插入到父元素的第一个子元素的前面 31 } 32 //封装cc函数 33 function cc(html){ 34 //这边返回的是cc原型对象里面的一个方法创建出来的实例 35 return new cc.fn.init(html); 36 } 37 //这边是为了后面书写方便 38 cc.fn = cc.prototype = { 39 constructor : cc, 40 length : 0, 41 //这两个属性要加到原型上 42 selector: '',//这两个属性在init所创建的实例之中还会用到,所以要加到这个原型上面 43 type : 'cc', 44 init : function(html){//这个函数的作用就是:1.创建实例;2.在这个函数里面对所传入的参数进行一个判断 45 this.events = {}; 46 if(html == ''){//这边判断传入的参数是不是一个空字符串 47 return;//如果传入的是一个空字符串,那么就直接返回this,注意,这边虽然没写返回this,但是他是默认的 48 }else if(cc.isString(html)){//这边是当传入的html是字符串的时候 49 if(/^</.test(html)){//这边的html是标签组成的字符串 50 push.apply(this,parseHtml(html)); 51 }else{//这边的html是选择器字符串 52 //这边的this指的是通过:cc.prototype.init这个函数创建出来的实例 53 push.apply(this,select(html)); 54 //将这个实例的selector设置成html 55 this.selector = html; 56 } 57 }else if(html && html.type === 'cc'){//这边是当传入的html是一个cc对象的时候 58 push.apply(this,html); 59 this.selector = html.selector; 60 this.events = html.events; 61 }else if(html && html.nodeType){//这边是当传入的是一个dom对象的时候,因为dom对象都有nodeType属性 62 this[0] = html; 63 this.length = 1; 64 }else if(typeof html === 'function'){//这边是当传入的是一个函数的时候,进入里面 65 var oldfunc = onload;//将原来onload里面的函数取出来 66 if(typeof oldfunc === 'function'){ 67 onload = function(){ 68 oldfunc(); 69 html(); 70 } 71 }else{ 72 onload = html; 73 } 74 } 75 } 76 }; 77 //将封装好的select方法放到这里面 78 var select = (function () { 79 //这是一个异常与捕获的代码,它表示的意思是:如果push方法出现了错误那么就需要重写push方法 80 try { 81 //这边是自己模拟一个场景,来使用系统的push方法,如果可以实现的话就证明系统支持push方法 82 //这种方法是系统能力检测中的方法功能检测 83 var div = document.createElement( 'div' ); 84 div.innerHTML = '<p></p>'; 85 var arr = []; 86 push.apply( arr, div.getElementsByTagName( 'p' )); 87 } catch ( e ) { 88 //这边是当try里面的push方法不执行的时候,会进入这里面 89 //在这里面将push重新定义了一下,将其变为一个对象,这个对象里面有一个push方法 90 var push = { 91 //将apply变成了push对象里面的一个方法 92 apply: function ( array1, array2 ) { 93 for ( var i = 0; i < array2.length; i++ ) { 94 //注意这边的赋值 95 array1[ array1.length++ ] = array2[ i ]; 96 } 97 } 98 }; 99 } 100 // 正则表达式 101 //这句正则表达式是为了匹配系统中是否有自带的方法 102 var rnative = /{s*[native/; 103 var rtrim = /^s+|s+$/g; 104 //这个是为了匹配出 Id 类名 通配符 标签名 105 // 1 2 3 4 106 var rbaseselector = /^(?:#([w-]+)|.([w-]+)|(*)|(w+))$/; 107 // 基本函数, support 对象, 验证 qsa 与 byclass 108 var support = {}; 109 //基本函数里面的一个属性,实质上是为了看一下系统中是否有该方法(使用正则来判断) 110 support.qsa = rnative.test( document.querySelectorAll + '' ); 111 //同上 112 support.getElementsByClassName = rnative.test( document.getElementsByClassName + '' ); 113 support.trim = rnative.test( String.prototype.trim + '' ); 114 support.indexOf = rnative.test( Array.prototype.indexOf + '' ); 115 // 基本方法 116 //封装了getElementsByClassName函数,这是为了解决兼容问题 117 //传入两个参数,一个是className,另一个是node-->这个node指的是从页面上的node元素开始查找这个className 118 function getByClassName ( className, node ) { 119 //如果没有传入node的话就给它一个默认值:document 120 node = node || document; 121 //声明一些变量 122 var allElem, res = [], i; 123 //首先做判断,如果系统有这个方法会使用系统的 124 if ( support.getElementsByClassName ) { 125 //直接使用定义的push方法 126 return push.apply(res,node.getElementsByClassName( className )); 127 } else { 128 allElem = node.getElementsByTagName( '*' ); 129 for ( i = 0; i < allElem.length; i++ ) { 130 if ( allElem[ i ].className === className ) { 131 res.push( allElem[ i ] ); 132 } 133 } 134 return res; 135 } 136 } 137 // 自定义实现 trim 方法,该方法是将字符串中的指定的东西去掉 138 var myTrim = function ( str ) { 139 // 表示两端去空格, 然后返回去除空格的结果 140 if ( support.trim ) { 141 return str.trim(); 142 } else { 143 // 自定义实现 144 //这边是将rtrim转换成空字符串,即将空格去掉了 145 return str.replace( rtrim, '' ); 146 } 147 } 148 //这边封装的是indexOf方法,传入三个参数,数组,要搜索的东西,要搜索的东西在数组里面的开始索引(从第几个开始找) 149 var myIndexOf = function ( array, search, startIndex ) { 150 //首先将索引赋值,如果传入了索引,那么就让开始的索引等于它,如果没有传入那么就让它从零开始找 151 startIndex = startIndex || 0; 152 //这边还是先判断系统有没有这种方法 153 if ( support.indexOf ) { 154 //这里表示系统有这种方法,那么就直接使用就OK了,将结果返回 155 return array.indexOf( search, startIndex ); 156 } else { 157 //如果没有的话,我们就自己动手封装一个 158 //对这个数组进行一个遍历,遍历的初始值就是从startIndex开始 159 for ( var i = startIndex; i < array.length; i++ ) { 160 //判断一下,如果数组里面有值与要查询的值相等,那么就返回这个索引值 161 if ( array[ i ] === search ) { 162 return i; 163 } 164 } 165 //当遍历完成之后,如果还是没有找到的话,就返回-1 166 return -1; 167 } 168 } 169 //封装一个去重的函数,传入的参数是一个数组 170 var unique = function ( array ) { 171 //声明一个空数组,用于接收去重之后的元素 172 var resArray = [], i = 0; 173 //对传入的数组进行一个遍历 174 for ( ; i < array.length; i++ ) { 175 //做一个判断,如果说resArray里面没有arr里面的元素,则将arr里面的元素放到resArray里面 176 //注意,这边使用的是之前封装好的myIndexOf方法 177 if ( myIndexOf( resArray, array[ i ] ) == -1 ) { 178 //使用的是前面封装好的push方法 179 resArray.push( array[ i ] ); 180 } 181 } 182 //将这个数组返回 183 return resArray; 184 } 185 //这边封装的是四种基本选择器,ID选择器,类选择器,通配符选择器,标签选择器 186 function basicSelect ( selector, node ) { 187 //这边的node指的是要在哪一个下面去寻找selector 188 node = node || document; 189 var m, res; 190 if ( m = rbaseselector.exec( selector ) ) { 191 if ( m[ 1 ] ) { // id选择器 192 res = document.getElementById( m[ 1 ] ); 193 if ( res ) {//如果res不是一个空的话,进入 194 return [ res ]; 195 } else {//当res为空的话返回一个空数组 196 return []; 197 } 198 } else if ( m[ 2 ] ) { // class选择器 199 return getByClassName( m[ 2 ], node ); 200 } else if ( m[ 3 ] ) {//通配符选择器 201 return node.getElementsByTagName( m[ 3 ] ); 202 } else if ( m[ 4 ] ) {//标签选择器 203 return node.getElementsByTagName( m[ 4 ] ); 204 } 205 } 206 return []; 207 } 208 //封装一个组合选择器,这里面的标签使用逗号隔开的 209 function select ( selector, results ) { 210 results = results || []; 211 var m, temp, selectors, i, subselector; 212 //这边是如果传入的selector不是一个字符串的话,那么返回空数组 213 if ( typeof selector != 'string' ) return results; 214 // 表明参数都没有问题, 接下来就是如何选择 215 // 首先判断 qsa 是否可用 216 // 然后再 一步步的 自己实现 217 if ( support.qsa ) {//如果系统有querySelectorAll方法,那么就使用 218 push.apply( results, document.querySelectorAll( selector ) ); 219 } else { 220 // 不存在再来考虑自己实现 221 //首先将传入的参数以逗号隔开,放到一个数组里面 222 selectors = selector.split( ',' ); 223 // 循环遍历这个数组 224 for ( i = 0; i < selectors.length; i++ ) { 225 //在这个循环里面对数组里面的每一个元素进行一个去除空格的操作,保证数据是我们想要的形式 226 subselector = myTrim( selectors[ i ] ); 227 // 接下来就是 处理 subselector,使用正则进行判断 228 if ( rbaseselector.test( subselector ) ) { 229 // 基本选择器 230 //如果匹配到了就将匹配到的传入到基本的四种选择器函数只中,返回一个数组,将这个数组进行一个push 231 push.apply( results, basicSelect( subselector ) ); 232 } else { 233 //如果匹配不到那么就使用 select2 函数 234 select2( subselector, results ); 235 } 236 } 237 } 238 // 返回 result注意,这个数组要进行一个去重操作 239 return unique( results ); 240 } 241 //封装一个后代选择器的函数,传入两个参数 242 function select2 ( selector, results ) { 243 results = results || []; 244 //将这个参数以逗号隔开 245 var selectors = selector.split( ' ' ); 246 //声明一个数组,这个数组用于存放元素,以及一个node数组,这个数组用于存放从哪一个元素开始找 247 var arr = [], node = [ document ]; 248 for ( var j = 0; j < selectors.length; j++ ) { 249 for ( var i = 0; i < node.length; i++ ) { 250 //因为这边寻找的是后代选择器,所以只要找到最后面的并将其返回就可以了 251 push.apply( arr, basicSelect( selectors[ j ], node[ i ] )); 252 } 253 //在结束的时候将arr里面的值全部给node,要注意此时node里面的值的作用是什么 254 node = arr; 255 //将arr清空 256 arr = []; 257 } 258 //在最后将最后一次获取到的node值赋给results 259 //这里面的值是最后一次获取到的元素,也就是说是要获取的子代元素中的的最后一个元素 260 push.apply( results, node ); 261 return results; 262 } 263 return select; 264 })(); 265 //让init这个方法的原型与cc这个构造函数的原型相等,这样init的原型里面就有init的方法 266 cc.fn.init.prototype = cc.fn; 267 //给cc以及cc原型添加一个混入的方法 268 cc.extend = cc.fn.extend = function extend(obj){ 269 for(var k in obj){ 270 this[k] = obj[k]; 271 } 272 } 273 //给cc混入方法,这些方法都是静态方法 274 cc.extend({ 275 //给cc混入一个isString方法 276 isString : function(html){ 277 return typeof html === "string"; 278 }, 279 //给cc混入一个each方法 280 each : function(arr,fnc){ 281 var i; 282 if(arr instanceof Array || arr.length >= 0){ 283 for(i = 0; i < arr.length; i ++){ 284 fnc.call(arr[i],i,arr[i]); 285 } 286 }else { 287 for( i in arr){ 288 fnc.call(arr[i],i,arr[i]); 289 } 290 } 291 return arr; 292 }, 293 map : function(arr,fnc){ 294 var i,tmp,res=[]; 295 if(arr instanceof Array || arr.length >= 0){ 296 for(i =0;i<arr.length;i++){ 297 //这边的tmp的值是这边fnc的返回值,如果说fnc这个函数里面没有返回值的话(return),那么tmp就是undefined 298 tmp = fnc(arr[i],i); 299 if(tmp != null){ 300 res.push(tmp); 301 } 302 } 303 }else{ 304 for(i in arr){ 305 tmp = fnc(arr[i],i); 306 if(tmp != null){ 307 res.push(tmp); 308 } 309 } 310 } 311 return res; 312 }, 313 //获取到样式 314 getStyle : function(dom,styleName){ 315 if(dom.currentStyle){ 316 return dom.currentStyle[styleName]; 317 }else{ 318 return window.getComputedStyle(dom)[styleName]; 319 } 320 }, 321 getText : function(dom,list){ 322 var node = dom.childNodes; 323 for(var i = 0;i < node.length;i ++){ 324 if(node[i].nodeType == 3){ 325 list.push(node[i].nodeValue); 326 } 327 if(node[i].nodeType == 1){ 328 cc.getText(node[i],list); 329 } 330 } 331 } 332 }); 333 //核心方法 334 cc.fn.extend({ 335 //将调用该方法的对象变成数组模式 336 toArray : function(){ 337 //法一: 338 /*var res = []; 339 for(var i = 0;i < this.length; i ++){ 340 res.push(this[i]); 341 } 342 return res;*/ 343 //法二: 344 //这句话的意思是:this.slice(0);--->this指的是实例对象,调用slice将其从一个伪数组变成一个数组 345 return slice.call(this , 0); 346 }, 347 //get方法是通过索引值来返回调用该方法的对象/数组里面的对应的值 348 get : function(index){ 349 if(index === undefined){ 350 return this.toArray(); 351 } 352 return this[index]; 353 }, 354 //这边的eq返回的是dom对象,这是与get方法的区别,简单地说就是eq返回的是一个init对象,而get返回的是一个元素 355 eq : function(num){ 356 var dom; 357 if(num >= 0){ 358 dom = this.get(num); 359 }else{ 360 dom = this.get(this.length + num); 361 } 362 return cc(dom); 363 }, 364 each : function(fnc){ 365 return cc.each(this,fnc); 366 }, 367 map : function(fnc){ 368 return cc.map(this,fnc); 369 } 370 }); 371 //对DOM的操作方法 372 cc.fn.extend({ 373 //给cc的原型混入一个appendTo方法,注意这边的原型是与init的原型是一至的 374 //首先要明白,appendTo方法是将appendT之前的元素添加到appendTo的括号里 375 appendTo : function(selector){ 376 //首先声明一个ccObj对象,这个对象是和this一样,是init的实例对象 377 //当我们将selector传入其中时,它会解析出来传入的是一个什么样的参数 378 //这边的selector参数,其实就是appendTo括号里面的内容 379 var ccObj = this.constructor(selector); 380 //这边声明一个新的init的实例对象,这是为了仿照jQuery里面链式原理的写法 381 //这边执行完该方法之后,返回的是一个dom对象 382 var newObj = this.constructor(); 383 //这边循环遍历this,这个this指的就是appendTo前面的内容 384 for(var i = 0;i < this.length;i ++){ 385 //这边循环遍历的是解析了传入参数selector之后得到的一个对象ccObj 386 for(var j = 0;j < ccObj.length;j ++){ 387 //声明一个变量temp 388 var temp; 389 if(j == ccObj.length-1){//当j循环到最后一个的时候,进入这个循环 390 //将this[i]赋值给temp 391 temp = this[i]; 392 }else{ 393 //这种情况就是当j值还没有到最后一个的时候 394 temp = this[i].cloneNode(true); 395 } 396 //将temp里面的值,放到之前创建的newobj中,这是为了仿照jQuery里面的链式结构 397 push.call(newObj , temp); 398 //将temp添加到ccObj中,temp里面存放的是this伪数组里面的值 399 ccObj[j].appendChild(temp); 400 } 401 } 402 //这个是:即使完成了这个appendTo操作,返回值依旧是一个cc对象 403 return newObj; 404 }, 405 //首先要明确的是:append方法是将append括号里面的加到append前面的元素中 406 append: function(selector){ 407 //还是一样,先声明一个cc对象,这个对象里面是将传入的参数进行解析 408 var ccObj = this.constructor(selector); 409 //这个循环的是创建的cc对象 410 for(var i = 0;i < ccObj.length;i ++){ 411 //这个循环的是this这个伪数组 412 for(var j = 0;j < this.length;j ++){ 413 var temp; 414 if(j == this.length-1){//这边的做法可以参照appendTo的方法封装 415 temp = ccObj[i]; 416 this[j].appendChild(temp); 417 }else{ 418 temp = ccObj[i].cloneNode(true); 419 this[j].appendChild(temp); 420 } 421 } 422 } 423 return this; 424 }, 425 prependTo : function(selector){ 426 var ccObj = this.constructor(selector); 427 var newObj = this.constructor(); 428 for(var i = 0;i< this.length;i ++){ 429 for(var j = 0;j < ccObj.length;j ++){ 430 var temp; 431 if(j == ccObj.length-1){ 432 temp = this[i]; 433 }else{ 434 temp = this[i].cloneNode(true); 435 } 436 push.call(newObj,temp); 437 prependChild(ccObj[j],temp); 438 } 439 } 440 return newObj; 441 }, 442 prepend : function(selector){ 443 var ccObj = this.constructor(selector); 444 for(var i = 0;i < ccObj.length;i ++){ 445 for(var j = 0;j < this.length;j ++){ 446 var temp; 447 if(j == this.length-1){ 448 temp = ccObj[i]; 449 prependChild(this[j],temp); 450 }else{ 451 temp = ccObj[i].cloneNode(true); 452 prependChild(this[j],temp); 453 } 454 } 455 } 456 return this; 457 } 458 }); 459 //事件处理模块 460 cc.fn.extend({ 461 on : function(type,fn){ 462 if(!this.events[type]){//当this中的events属性里面没有type的时候,进入这个里面 463 this.events[type] = [];//给它提供一个空数组 464 //当cc对象中的元素被点击的时候我们应该把数组中保存的函数拿出来一一执行 465 //我们应该为cc对象中的元素添加事件处理函数 466 var iObj = this;//将this赋值给iObj,此时iObj就表示创建出来的实例对象 467 //这边的this指的是实例对象 468 this.each(function(){//调用这个实例的each方法 469 var fnc = function(e){//fnc执行的时机是type事件执行的时候,在这个时候跟着传入一个e,这个e是事件参数 470 for(var i = 0;i < iObj.events[type].length;i ++){ 471 //iObj.events[type][i]指的是:找到iObj对象->events属性->type数组->第i个函数,将之执行 472 //iObj.events[type][i]指的是:函数 473 //在执行的时候,这边的this指的是执行点击的这个dom元素 474 iObj.events[type][i].call(this,e);//这边将e传入到这个执行的函数中 475 } 476 } 477 //如果系统支持addEventListener方法就用它添加事件处理函数f,否则使用attachEvent 478 //事件参数e是从哪里来的?就是从事件绑定的函数来的 479 //我们通过addEventListener绑定事件的处理函数为f,那么f就带有了事件参数e 480 if(this.addEventListener){ 481 this.addEventListener(type,fnc); 482 }else{ 483 this.attachEvent('on' + type,fnc); 484 } 485 }); 486 } 487 this.events[type].push(fn); 488 return this; 489 }, 490 off : function(type,fn){ 491 var arr = this.events[type]; 492 if(arr){ 493 for(var i = arr.length;i >= 0;i --){ 494 if(arr[i] == fn){ 495 arr.splice(i,1); 496 } 497 } 498 } 499 return this; 500 } 501 }); 502 //其他事件 503 //其他事件的添加是将这些字符串用split方法分隔 504 var arr = 505 ("blur focus focusin focusout load resize scroll unload click dblclick " + 506 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + 507 "change select submit keydown keypress keyup error contextmenu").split(' '); 508 //调用cc的each方法,这个方法里面传入的一个参数是数组,一个参数是函数fnc 509 cc.each(arr,function(i,v){ 510 //在这个fnc中, 511 cc.fn[v] = function(fn){ 512 this.on(v,fn); 513 return this; 514 } 515 }); 516 cc.fn.extend({ 517 hover : function(fn1,fn2){ 518 this.mouseover(fn1); 519 this.mouseout(fn2); 520 return this; 521 }, 522 toggle : function(){ 523 var i = 0; 524 var args = arguments; 525 this.on('click' , function(e){ 526 args[i % args.length].call(this , e); 527 i ++; 528 }); 529 } 530 }); 531 //样式操作 532 cc.fn.extend({ 533 css : function(option){ 534 var args = arguments, 535 argsLength = arguments.length; 536 if(argsLength == 2){ 537 if(cc.isString(args[0]) && cc.isString(args[1])){ 538 return this.each(function(){ 539 this.style[args[0]] = args[1]; 540 }) 541 } 542 } 543 if(argsLength == 1){ 544 if(cc.isString(option)){ 545 return this[0].style[option] || cc.getStyle(this[0],option) 546 } 547 if(typeof option === 'object'){ 548 return this.each(function(){ 549 for(var k in option){ 550 this.style[k] = option[k]; 551 } 552 }) 553 } 554 } 555 }, 556 addClass : function(name){ 557 return this.each(function(){ 558 var classText = this.className; 559 if(classText){ 560 if((' ' + classText +' ').indexOf(' ' + name + ' ') ==-1){ 561 this.className += ' ' + name;//这边是将这个name添加到dom的className中 562 } 563 }else{ 564 this.className = name; 565 } 566 }) 567 }, 568 removeClass : function(name){ 569 return this.each(function(){ 570 var classText = this.className; 571 if(classText){ 572 var arr = classText.split(' '); 573 for(var i = arr.length;i >= 0;i --){ 574 if(arr[i] == name){ 575 arr.splice(i,1); 576 } 577 } 578 this.className = arr.join(' '); 579 } 580 }) 581 }, 582 hasClass : function(name){ 583 //法一 584 /*var boolean; 585 this.each(function(){ 586 var classText = this.className; 587 if(classText){ 588 var arr = classText.split(' '); 589 for(var i = 0;i < arr.length;i ++){ 590 if(arr[i] == name){ 591 boolean = true; 592 return; 593 } 594 } 595 boolean = false; 596 return; 597 } 598 boolean = false; 599 return; 600 }); 601 return boolean;*/ 602 //法二 603 for(var i = 0;i < this.length;i ++){ 604 if((' ' + this[i].className + ' ').indexOf(' ' + name + ' ') != -1){ 605 return true; 606 } 607 } 608 return false; 609 }, 610 toggleClass : function(name){ 611 if(this.hasClass(name)){ 612 this.removeClass(name); 613 }else{ 614 this.addClass(name); 615 } 616 } 617 }); 618 //属性操作 619 cc.fn.extend({ 620 attr: function(name,value){ 621 //第一种情况:有value值以及value值为空时 622 if(value || value == ''){ 623 //这时要传入的name以及value都要是字符串 624 if(cc.isString(name) && cc.isString(value)){ 625 this.each(function(){ 626 this.setAttribute(name,value);//设置属性 627 }) 628 } 629 }else{//这种情况是当只传了name且name为字符串 630 if(cc.isString(name)){ 631 //这个时候是获取该属性 632 return this[0].getAttribute(name); 633 } 634 } 635 //这个是当以上两种都不符合时: 636 return this; 637 }, 638 prop : function(name,value){ 639 if(value || value == ''){ 640 if(cc.isString(name) && cc.isString(value)){ 641 this.each(function(){ 642 this[name] = value; 643 }) 644 }else{ 645 if(cc.isString(name)){ 646 return this[name]; 647 } 648 } 649 } 650 return this; 651 }, 652 val : function(value){ 653 return this.attr('value',value); 654 }, 655 html : function(html){ 656 return this.prop('innerHTML',html); 657 }, 658 text : function(){ 659 var res = []; 660 cc.getText(this[0],res); 661 return res.join(' '); 662 } 663 }); 664 //给cc原型添加anmite属性 665 cc.fn.extend({ 666 animate : function(property,time,fn,easing){ 667 var iObj = this 668 flag = false; 669 this.each(function(){ 670 move(this,property,time,fn,easing); 671 }); 672 return this; 673 function move(node,property,time,fn,easing){//需要传入的参数有:元素,元素要移动的距离,动画执行的时长 674 var start = {}; 675 for(var k in property){ 676 start[k] = parseInt(cc.getStyle(node,k)); 677 } 678 var startTime = + new Date;//开始的时间 679 iObj.timer = setInterval(function(){//设置定时器 680 var currentTime = + new Date,//当前时间 681 deltaTime = currentTime - startTime;//当前时间与开始事件的差值,这个差值可以得到的是已经过去了多久 682 if(deltaTime >= time){//这边如果差值大于规定的时长之后,进入这个判断里面 683 clearInterval(iObj.timer);//这时候要清除计时器 684 deltaTime = time;//将差值赋值为要求的时长 685 flag = true; 686 } 687 easing = easing || 'change'; 688 for(var k in property){ 689 node.style[k] = start[k] 690 + g(deltaTime,time,start[k],parseInt(property[k]),easing) 691 + 'px'; 692 } 693 if(flag && fn){ 694 fn.call(iObj); 695 return; 696 } 697 },20); 698 }; 699 function g(deltaTime,time,start,end,easing){ 700 if(easing == 'line'){ 701 return ((end - start)/time)*deltaTime; 702 }else if(easing == 'change'){ 703 var distance = end - start;//需要移动的距离 704 //法一: 705 //return distance*Math.sin(daleTime*Math.PI/2/time); 706 //法二: 707 return distance*(Math.log(deltaTime + 1) / Math.log(time + 1)); 708 } 709 } 710 }, 711 timer : null, 712 stop : function(){ 713 clearInterval(this.timer); 714 this.timer = null; 715 } 716 }) 717 //在桌面上可以使用I以及cc来调用沙箱内部的cc函数 718 window.C = window.cc = cc; 719 })(window);