2011-04-25 54 views
0

我有這個jquery插件可以放大照片,但我想動畫縮放,所以它只是沒有放大,但這樣就像在縮放動畫效果。這可能嗎?如何在jquery iviewer插件上動畫縮放?

這裏是我現在設置插件的頁面。 http://www.buildinfocus.com/clients/gallery_detail.php?title=1&mapid=239

也許這樣的事情

下面是我對插件

(function($){ 

$.fn.iviewer = function(o) 
{ 
    return this.each(function() 
        { 
         $(this).data('viewer', new $iv(this,o)); 
        }); 
} 

var defaults = { 
    /** 
    * start zoom value for image, not used now 
    * may be equal to "fit" to fit image into container or scale in % 
    **/ 
    zoom: "fit", 
    /** 
    * base value to scale image 
    **/ 
    zoom_base: 100, 
    /** 
    * maximum zoom 
    **/ 
    zoom_max: 800, 
    /** 
    * minimum zoom 
    **/ 
    zoom_min: 25, 
    /** 
    * base of rate multiplier. 
    * zoom is calculated by formula: zoom_base * zoom_delta^rate 
    **/ 
    zoom_delta: 1.4, 
    /** 
    * if true plugin doesn't add its own controls 
    **/ 
    ui_disabled: false, 
    /** 
    * if false, plugin doesn't bind resize event on window and this must 
    * be handled manually 
    **/ 
    update_on_resize: true, 
    /** 
    * event is triggered when zoom value is changed 
    * @param int new zoom value 
    * @return boolean if false zoom action is aborted 
    **/ 
    onZoom: null, 
    /** 
    * callback is fired after plugin setup 
    **/ 
    initCallback: null, 
    /** 
    * event is fired on drag begin 
    * @param object coords mouse coordinates on the image 
    * @return boolean if false is returned, drag action is aborted 
    **/ 
    onStartDrag: null, 
    /** 
    * event is fired on drag action 
    * @param object coords mouse coordinates on the image 
    **/ 
    onDrag: null, 
    /** 
    * event is fired when mouse moves over image 
    * @param object coords mouse coordinates on the image 
    **/ 
    onMouseMove: null, 
    /** 
    * mouse click event 
    * @param object coords mouse coordinates on the image 
    **/ 
    onClick: null, 
    /** 
    * event is fired when image starts to load 
    */ 
    onStartLoad: null, 
    /** 
    * event is fired, when image is loaded and initially positioned 
    */ 
    onFinishLoad: null 
}; 

$.iviewer = function(e,o) 
{ 
    var me = this; 

    /* object containing actual information about image 
    * @img_object.object - jquery img object 
    * @img_object.orig_{width|height} - original dimensions 
    * @img_object.display_{width|height} - actual dimensions 
    */ 
    this.img_object = {}; 

    this.zoom_object = {}; //object to show zoom status 
    this.image_loaded = false; 

    //drag variables 
    this.dx = 0; 
    this.dy = 0; 
    this.dragged = false; 

    this.settings = $.extend({}, defaults, o || {}); 
    this.current_zoom = this.settings.zoom; 

    if(this.settings.src === null){ 
     return; 
    } 

    this.container = $(e); 

    this.update_container_info(); 

    //init container 
    this.container.css("overflow","hidden"); 

    if(this.settings.update_on_resize == true) 
    { 
     $(window).resize(function() 
     { 
      me.update_container_info(); 
     }); 
    } 

    this.img_object.x = 0; 
    this.img_object.y = 0; 

    //init object 
    this.img_object.object = $("<img>"). 
    css({ position: "absolute", top :"0px", left: "0px"}). //this is needed, because chromium sets them auto otherwise 
    //bind mouse events 
    mousedown(function(e){ return me.drag_start(e); }). 
    mousemove(function(e){return me.drag(e)}). 
    mouseup(function(e){return me.drag_end(e)}). 
    click(function(e){return me.click(e)}). 
    mouseleave(function(e){return me.drag_end(e)}). 
    mousewheel(function(ev, delta) 
    { 
     //this event is there instead of containing div, because 
     //at opera it triggers many times on div 
     var zoom = (delta > 0)?1:-1; 
     me.zoom_by(zoom); 
     return false; 
    }); 

    this.img_object.object.prependTo(me.container); 
    this.loadImage(this.settings.src); 

    if(!this.settings.ui_disabled) 
    { 
     this.createui(); 
    } 

    if(this.settings.initCallback) 
    { 
     this.settings.initCallback.call(this); 
    } 
} 


var $iv = $.iviewer; 

$iv.fn = $iv.prototype = { 
    iviewer : "0.4.2" 
} 
$iv.fn.extend = $iv.extend = $.extend; 

$iv.fn.extend({ 

    loadImage: function(src) 
    { 
     this.current_zoom = this.settings.zoom; 
     this.image_loaded = false; 
     var me = this; 

     if(this.settings.onStartLoad) 
     { 
      this.settings.onStartLoad.call(this); 
     } 

     this.img_object.object.unbind('load'). 
      removeAttr("src"). 
      removeAttr("width"). 
      removeAttr("height"). 
      css({ top: 0, left: 0 }). 
      load(function(){ 
       me.image_loaded = true; 
       me.img_object.display_width = me.img_object.orig_width = this.width; 
       me.img_object.display_height = me.img_object.orig_height = this.height; 

       if(!me.container.hasClass("iviewer_cursor")){ 
        me.container.addClass("iviewer_cursor"); 
       } 

       if(me.settings.zoom == "fit"){ 
        me.fit(); 
       } 
       else { 
        me.set_zoom(me.settings.zoom); 
       } 

       if(me.settings.onFinishLoad) 
       { 
        me.settings.onFinishLoad.call(me); 
       } 

      //src attribute is after setting load event, or it won't work 
     }).attr("src",src); 
    }, 

    /** 
    * fits image in the container 
    **/ 
    fit: function() 
    { 
     var aspect_ratio = this.img_object.orig_width/this.img_object.orig_height; 
     var window_ratio = this.settings.width/this.settings.height; 
     var choose_left = (aspect_ratio > window_ratio); 
     var new_zoom = 0; 

     if(choose_left){ 
      new_zoom = this.settings.width/this.img_object.orig_width * 100; 
     } 
     else { 
      new_zoom = this.settings.height/this.img_object.orig_height * 100; 
     } 

     this.set_zoom(new_zoom); 
    }, 

    /** 
    * center image in container 
    **/ 
    center: function() 
    { 
     this.setCoords(-Math.round((this.img_object.display_height - this.settings.height)/2), 
         -Math.round((this.img_object.display_width - this.settings.width)/2)); 
    }, 

    /** 
    * move a point in container to the center of display area 
    * @param x a point in container 
    * @param y a point in container 
    **/ 
    moveTo: function(x, y) 
    { 
     var dx = x-Math.round(this.settings.width/2); 
     var dy = y-Math.round(this.settings.height/2); 

     var new_x = this.img_object.x - this.dx; 
     var new_y = this.img_object.y - this.dy; 

     this.setCoords(new_x, new_y); 
    }, 

    /** 
    * set coordinates of upper left corner of image object 
    **/ 
    setCoords: function(x,y) 
    { 
     //do nothing while image is being loaded 
     if(!this.image_loaded) 
     { 
      return; 
     } 

     //check new coordinates to be correct (to be in rect) 
     if(y > 0){ 
      y = 0; 
     } 
     if(x > 0){ 
      x = 0; 
     } 
     if(y + this.img_object.display_height < this.settings.height){ 
      y = this.settings.height - this.img_object.display_height; 
     } 
     if(x + this.img_object.display_width < this.settings.width){ 
      x = this.settings.width - this.img_object.display_width; 
     } 
     if(this.img_object.display_width <= this.settings.width){ 
      x = -(this.img_object.display_width - this.settings.width)/2; 
     } 
     if(this.img_object.display_height <= this.settings.height){ 
      y = -(this.img_object.display_height - this.settings.height)/2; 
     } 

     this.img_object.x = x; 
     this.img_object.y = y; 

     this.img_object.object.css("top",y + "px") 
         .css("left",x + "px"); 
    }, 


    /** 
    * convert coordinates on the container to the coordinates on the image (in original size) 
    * 
    * @return object with fields x,y according to coordinates or false 
    * if initial coords are not inside image 
    **/ 
    containerToImage : function (x,y) 
    { 
     if(x < this.img_object.x || y < this.img_object.y || 
      x > this.img_object.x + this.img_object.display_width || 
      y > this.img_object.y + this.img_object.display_height) 
     { 
      return false; 
     } 

     return { x : $iv.descaleValue(x - this.img_object.x, this.current_zoom), 
       y : $iv.descaleValue(y - this.img_object.y, this.current_zoom) 
     }; 
    }, 

    /** 
    * convert coordinates on the image (in original size) to the coordinates on the container 
    * 
    * @return object with fields x,y according to coordinates or false 
    * if initial coords are not inside image 
    **/ 
    imageToContainer : function (x,y) 
    { 
     if(x > this.img_object.orig_width || y > this.img_object.orig_height) 
     { 
      return false; 
     } 

     return { x : this.img_object.x + $iv.scaleValue(x, this.current_zoom), 
       y : this.img_object.y + $iv.scaleValue(y, this.current_zoom) 
     }; 
    }, 

    /** 
    * get mouse coordinates on the image 
    * @param e - object containing pageX and pageY fields, e.g. mouse event object 
    * 
    * @return object with fields x,y according to coordinates or false 
    * if initial coords are not inside image 
    **/ 
    getMouseCoords : function(e) 
    { 
     var img_offset = this.img_object.object.offset(); 

     return { x : $iv.descaleValue(e.pageX - img_offset.left, this.current_zoom), 
       y : $iv.descaleValue(e.pageY - img_offset.top, this.current_zoom) 
     }; 
    }, 

    /** 
    * set image scale to the new_zoom 
    * @param new_zoom image scale in % 
    **/ 
    set_zoom: function(new_zoom) 
    { 
     if(this.settings.onZoom && this.settings.onZoom.call(this, new_zoom) == false) 
     { 
      return; 
     } 

     //do nothing while image is being loaded 
     if(!this.image_loaded) 
     { 
      return; 
     } 

     if(new_zoom < this.settings.zoom_min) 
     { 
      new_zoom = this.settings.zoom_min; 
     } 
     else if(new_zoom > this.settings.zoom_max) 
     { 
      new_zoom = this.settings.zoom_max; 
     } 

     /* we fake these values to make fit zoom properly work */ 
     if(this.current_zoom == "fit") 
     { 
      var old_x = Math.round(this.settings.width/2 + this.img_object.orig_width/2); 
      var old_y = Math.round(this.settings.height/2 + this.img_object.orig_height/2); 
      this.current_zoom = 100; 
     } 
     else { 
      var old_x = -parseInt(this.img_object.object.css("left"),10) + 
             Math.round(this.settings.width/2); 
      var old_y = -parseInt(this.img_object.object.css("top"),10) + 
             Math.round(this.settings.height/2); 
     } 

     var new_width = $iv.scaleValue(this.img_object.orig_width, new_zoom); 
     var new_height = $iv.scaleValue(this.img_object.orig_height, new_zoom); 
     var new_x = $iv.scaleValue($iv.descaleValue(old_x, this.current_zoom), new_zoom); 
     var new_y = $iv.scaleValue($iv.descaleValue(old_y, this.current_zoom), new_zoom); 

     new_x = this.settings.width/2 - new_x; 
     new_y = this.settings.height/2 - new_y; 

     this.img_object.object.attr("width",new_width) 
         .attr("height",new_height); 
     this.img_object.display_width = new_width; 
     this.img_object.display_height = new_height; 

     this.setCoords(new_x, new_y); 

     this.current_zoom = new_zoom; 

     $.isFunction(this.settings.onAfterZoom) && this.settings.onAfterZoom.call(this, new_zoom); 
     this.update_status(); 
    }, 

    /** 
    * changes zoom scale by delta 
    * zoom is calculated by formula: zoom_base * zoom_delta^rate 
    * @param Integer delta number to add to the current multiplier rate number 
    **/ 
    zoom_by: function(delta) 
    { 
     var closest_rate = this.find_closest_zoom_rate(this.current_zoom); 

     var next_rate = closest_rate + delta; 
     var next_zoom = this.settings.zoom_base * Math.pow(this.settings.zoom_delta, next_rate) 
     if(delta > 0 && next_zoom < this.current_zoom) 
     { 
      next_zoom *= this.settings.zoom_delta; 
     } 

     if(delta < 0 && next_zoom > this.current_zoom) 
     { 
      next_zoom /= this.settings.zoom_delta; 
     } 

     this.set_zoom(next_zoom); 
    }, 

    /** 
    * finds closest multiplier rate for value 
    * basing on zoom_base and zoom_delta values from settings 
    * @param Number value zoom value to examine 
    **/ 
    find_closest_zoom_rate: function(value) 
    { 
     if(value == this.settings.zoom_base) 
     { 
      return 0; 
     } 

     function div(val1,val2) { return val1/val2 }; 
     function mul(val1,val2) { return val1 * val2 }; 

     var func = (value > this.settings.zoom_base)?mul:div; 
     var sgn = (value > this.settings.zoom_base)?1:-1; 

     var mltplr = this.settings.zoom_delta; 
     var rate = 1; 

     while(Math.abs(func(this.settings.zoom_base, Math.pow(mltplr,rate)) - value) > 
       Math.abs(func(this.settings.zoom_base, Math.pow(mltplr,rate+1)) - value)) 
     { 
      rate++; 
     } 

     return sgn * rate; 
    }, 

    /* update scale info in the container */ 
    update_status: function() 
    { 
     if(!this.settings.ui_disabled) 
     { 
      var percent = Math.round(100*this.img_object.display_height/this.img_object.orig_height); 
      if(percent) 
      { 
       this.zoom_object.html(percent + "%"); 
      } 
     } 
    }, 

    update_container_info: function() 
    { 
     this.settings.height = this.container.height(); 
     this.settings.width = this.container.width(); 
    }, 

    /** 
    * callback for handling mousdown event to start dragging image 
    **/ 
    drag_start: function(e) 
    { 
     if(this.settings.onStartDrag && 
      this.settings.onStartDrag.call(this,this.getMouseCoords(e)) == false) 
     { 
      return false; 
     } 

     /* start drag event*/ 
     this.dragged = true; 
     this.container.addClass("iviewer_drag_cursor"); 

     this.dx = e.pageX - this.img_object.x; 
     this.dy = e.pageY - this.img_object.y; 
     return false; 
    }, 

    /** 
    * callback for handling mousmove event to drag image 
    **/ 
    drag: function(e) 
    { 
     this.settings.onMouseMove && 
       this.settings.onMouseMove.call(this,this.getMouseCoords(e)); 

     if(this.dragged){ 
      this.settings.onDrag && 
        this.settings.onDrag.call(this,this.getMouseCoords(e)); 

      var ltop = e.pageY -this.dy; 
      var lleft = e.pageX -this.dx; 

      this.setCoords(lleft, ltop); 
      return false; 
     } 
    }, 

    /** 
    * callback for handling stop drag 
    **/ 
    drag_end: function(e) 
    { 
     this.container.removeClass("iviewer_drag_cursor"); 
     this.dragged=false; 
    }, 

    click: function(e) 
    { 
     this.settings.onClick && 
       this.settings.onClick.call(this,this.getMouseCoords(e)); 
    }, 

    /** 
    * create zoom buttons info box 
    **/ 
    createui: function() 
    { 
     var me=this; 

     $("<div>").addClass("iviewer_zoom_in").addClass("iviewer_common"). 
     addClass("iviewer_button"). 
     mousedown(function(){me.zoom_by(1); return false;}).appendTo(this.container); 

     $("<div>").addClass("iviewer_zoom_out").addClass("iviewer_common"). 
     addClass("iviewer_button"). 
     mousedown(function(){me.zoom_by(- 1); return false;}).appendTo(this.container); 

     $("<div>").addClass("iviewer_zoom_zero").addClass("iviewer_common"). 
     addClass("iviewer_button"). 
     mousedown(function(){me.set_zoom(100); return false;}).appendTo(this.container); 

     $("<div>").addClass("iviewer_zoom_fit").addClass("iviewer_common"). 
     addClass("iviewer_button"). 
     mousedown(function(){me.fit(this); return false;}).appendTo(this.container); 

     this.zoom_object = $("<div>").addClass("iviewer_zoom_status").addClass("iviewer_common"). 
     appendTo(this.container); 

     this.update_status(); //initial status update 
    } 
}); 

$iv.extend({ 
    scaleValue: function(value, toZoom) 
    { 
     return value * toZoom/100; 
    }, 

    descaleValue: function(value, fromZoom) 
    { 
     return value * 100/fromZoom; 
    } 
}); 

})(jQuery); 

回答

0

該插件的最後一個版本(0.5)支持平滑縮放,請嘗試一下。