学习一个框架到一定阶段后,如果希望对它有更深入的理解,应该尝试写给它写独立的模块或者插件。

趁周末写了一个YUI模块:

1.支持自定义数量的预加载

2.支持history

3.支持键盘导航

 

参照了人人网的相册,还有百度的图片搜索结果页面。

人人网的相册功能,体验还是不错的。载入大图的时候速度很快,猜测肯定是预加载了的,现在的网站大规模的使用了ajax功能,url不会刷新,但是内容会变,带来的后果就是,可能失去历史信息,人人的相册对这个也是做了处理的,图片切换url地址会变,那么历史前进后退功能也就没有问题了。而且也是支持鼠标导航的。试下左右方向键。

类似的效果还有百度的图片搜索结果,有一个很贴心的功能就是点击向下翻页的时候,上一页的最后一个会列在新一页的第一个,这样感觉很好,这个一并copy了

1.图片预加载

最简单能想到的就是 

var img = new Image();

img.src = imgurl;

对IE浏览器来说,很好,但是火狐却不能达到预加载的目的。【我自己没有验证,参考了这里 ,因为火狐中的图片有独立的缓存 new Image().src  has a separate cache for images】

一个兼容的预加载的实现就是

    preloadImage:function(src){
      Y.log('preload:'+src);
      if(Y.UA.ie){
        new Image().src = src;
      }else{
        var d = document,
        b = document.body;
        o = d.createElement('object');
        o.data  = src;
        o.width = o.height = 0;
        b.appendChild(o);
      }
    }

 

2.历史记录功能

YUI3 是提供了这样的功能的:当切换一张图片,改变url的hash值,即历史记录添加一个value

 history.addValue("pic",currentIndex || null);

 

切换图片后,重新刷新页面,或者将本页面的url发送给别人,再次进入这个页面,图片的也是如期望所显示的

        var pic = Number(history.get("pic"));
        if(thumbs.item(pic)){
          gallery.gotoIndex(pic);
        }

3.键盘导航

键盘导航还是比较简单的,给document添加一个keydown 事件,判断如果按下的是左方向键,那么久显示上一张图片,如果按下的是向右方向键,那么显示下一张图片。按理说,应该也是可以将事件绑定到document.body 上的,发现在出FF以外的浏览器上是OK的,而FF不太灵敏,最终将keydow 事件绑定到了document上。

        var eventType = (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress';
        var handleKeypress = function(e){
          //console.log('keynav',e.keyCode);
          if(e.keyCode === 37 || e.keyCode === 38){
            gallery.prevImage();
          }else if(e.keyCode === 39 || e.keyCode === 40){
            gallery.nextImage();
          }
        }

  

第一个YUI模块还是不够满意,放了好多代码在实例化后,来支持历史记录和键盘导航功能,有空会将这些逻辑放到模块本身中去。上代码了:

 

YUI.add('k2-gallery', function(Y) {

  var Lang = Y.Lang,
      EVENT_FORWARD = "forward",
      EVENT_BACKWARD = "backward",
      EVENT_CHANGE = "change";


  var DefaultConfig = {
    preloadNumber:10,
    autostart:true,
    playPause:'#play-pause',
    imgContainer:'#img-con',
    imgEl:'#img-el',
    prev:'#prev',
    next:'#next',
    autoPlay:false,
    direction:'forward',
    loading:'#k2-gallery-loading',
    bigImage:{"selector":'li>a','data-src':'href','data-alt':'title'},
    smallImage:{"selector":'li>a>img','data-src':'src','data-alt':'alt'},
    //一批小图个数
    batchSize:5

  };
  function KGallery(imgList,config) {
    Y.log("imgList id:"+imgList);
    //图片源
    this.imageList = Lang.isObject(imgList) ? imgList : Y.one(imgList);
    if(!this.imageList) return;

    this.config = DefaultConfig;

    if(Lang.isObject(config))
      this.config = Y.merge(this.config,config);

    // Y.log(this.config);

    // 图片容器
    this.imgContainer = Y.one(this.config.imgContainer);
    // 图片元素
    this.imgEl = Y.one(this.config.imgEl);
    // next && next trigger
    this.nextEl = Y.one(this.config.next);
    this.prevEl = Y.one(this.config.prev);

    this.bindEvent();

    KGallery.superclass.constructor.call(this);

  }

  KGallery.NAME = 'k2-gallery';
  /*
   * The attributes this extension provides
   */
  KGallery.ATTRS = {
  };

  Y.extend(KGallery,Y.Base,{
    init:function(){
      var self = this;
      Y.log(this.config);
      this.allImages = [];
      this.getAllImages();

      //Y.log(this.allImages.toString());
      if(this.allImages.length > 0)
        this.currentImage = this.allImages[0];

      Y.log("currentImage:"+this.currentImage.toString());
      this.preloadImages();
      this.currentIndex = 0;
      this.showCurrentImage();

      return this;
    },
    bindEvent:function(){
      if(this.nextEl)
        this.nextEl.on("click",this.nextImage,this);
      if(this.prevEl)
      this.prevEl.on("click",this.prevImage,this);

    },
    getAllImages:function(){
      var self = this;
      var bigImages,smallImages;
      bigImages = this.imageList.all(this.config.bigImage.selector);

      bigImages.each(function(v,index){
        if(!self.allImages[index])
          self.allImages[index] = {};
        var obj = self.allImages[index];

        obj.bigSrc = v.getAttribute(self.config.bigImage['data-src']);
        obj.bigAlt = v.getAttribute(self.config.bigImage['data-alt']);

      });
      if(this.config.smallImage.selector){
        smallImages = this.imageList.all(this.config.smallImage.selector);
        smallImages.each(function(v,index){
          if(!self.allImages[index])
            self.allImages[index] = {};
          var obj = self.allImages[index];

          obj.smallSrc = v.getAttribute(self.config.smallImage['data-src']);
          obj.smallAlt = v.getAttribute(self.config.smallImage['data-alt']);
        });
      };

      //console.log(self.allImages.toString());

    },
    preloadImages:function(){
      var currentImage = this.currentImage,
          index = this.currentIndex,
          images = this.allImages.slice(index,index+this.config.preloadNumber),
          len = images.length,
          preloadedFlag = false,
          self = this;
      // Y.log("preload images:"+images.toString());
      Y.each(images,function(v){
        if(!v.preloaded){
          preloadedFlag = true;
          //Y.log("DOES NOT LOADED:"+v.toString());
          self.preloadImage(v.bigSrc);
        }
      });

      preloadedFlag && this.updatePreloadStatus(index,len);
    },
    updatePreloadStatus:function(index,len){
      var item;
      while(len > 0){
        item = this.allImages[index+len-1];
        if(item){
          item.preloaded = true;
          //Y.log("item:"+item.toString());
        }
        --len;
      }
    },
    preloadImage:function(src){
      Y.log('preload:'+src);
      if(Y.UA.ie){
        new Image().src = src;
      }else{
        var d = document,
        b = document.body;
        o = d.createElement('object');
        o.data  = src;
        o.width = o.height = 0;
        b.appendChild(o);
      }
    },
    autoplay:function(){
      var playFn ;
      if(this.config.direction === 'backward')
        playFn = this.next;
      else
        playFn = this.prev;

      if(this.config.autoPlay)
        this.autoPlayTimer = setTimeout(arguments.callee,this.config.duration);
      else
        playFn();
    },
    gotoIndex:function(index){
      var allImage = this.allImages;
      if(index<0){
        index = allImage.length -1;
      }else if(index>allImage.length-1){
        index = 0;
      }
      this.currentIndex = index;
      this.currentImage = allImage[index];
      //console.log("current image",this.currentImage);
      this.showCurrentImage();
      this.fire(EVENT_CHANGE,{currentImage:this.currentImage,index:this.currentIndex});
    },
    nextImage:function(){
      // var allImg = this.allImages;
      // var index = Y.Array.indexOf(allImg,this.currentImage);
      this.gotoIndex(this.currentIndex+1);
    },
    prevImage:function(){
      // var allImg = this.allImages;
      // var index = Y.Array.indexOf(allImg,this.currentImage);
      this.gotoIndex(this.currentIndex-1);
    },
    next:function(){
      Y.log("show next image... ");
      this.setNextImage();
      this.showCurrentImage();

      this.fire(EVENT_FORWARD,{currentImage:this.currentImage});
      this.fire(EVENT_CHANGE,{currentImage:this.currentImage,index:this.currentI});

      if(this.config.autoPlay){
        this.setAutoplayDirection("forward");
        if(!this.autoPlayTimer)
          this.autoPlay();
      }
      this.preloadImages();
    },
    prev:function(){
      this.setPrevImage();
      this.showCurrentImage();
      if(this.config.autoPlay){
        this.setAutoplayDirection("backward");
        if(!this.autoPlayTimer)
          this.autoPlay();
      }
      this.preloadImages();
    },
    setAutoPlay:function(b){
      this.config.autoPlay = !!b;
    },
    setAutoplayDirection:function(d){
      this.config.direction = b;
    },
    showCurrentImage:function(){
      var imgContainer = this.imgContainer,
          imgEl = this.imgEl,
          imgData = this.currentImage;
      if(imgData){
        imgEl.setAttribute("src",imgData.bigSrc);
        imgEl.setAttribute("alt",imgData.bigAlt);
      }
      this.preloadImages();

      /*
      var animOut = new Y.Anim({
        node:node,
        to:{

        }
      });
       */


    },
    /*
     * @param:index
     * @param:offset*/
    getNextBatch:function(index,offset){
      if(offset>this.allImages.length){
        return this.allImages;
      }else{
        var arr = this.allImages.slice(index,offset);
        if(arr.length < offset)
          arr.push(this.allImages.slice(0,offset - arr.length));
        return arr;
      }
    },
    _hideEffect:function(){

    },
    _showEffect:function(){}
  });


  Y.KGallery = KGallery;


},'1-1-0',{requires:['node-base','oop','base-base']});

  

 

 

 

 

 

posted on 2011-11-19 21:14  wewe.Tom  阅读(346)  评论(0编辑  收藏  举报