API Docs for:
Show:

File: src/main/resources/js/TiledImage.js

/**
 * javascript library for TiledImage 
 * $Id: TiledImage.js 16 2013-04-13 09:02:12Z nazotoko $
 * @author Copyright 2013 Shun N. Watanabe <nazotoko (a+) users.sourceforge.net>
 * @module TiledImage
 * @main
 */

/**
 * TiledImage top level Object. Before calling the contsructor, create div element
 * in HTML part. This constructor needs the id name of the div element.
 * @example
     <div id="id_name" style="height:123px;width:456px;"></div>
     <script>
     new TiledImage("id_name")
     .addLayer(new TilesLayer("tile","test/z${z}/${x}_${y}.jpg",4000,3000))
     .addControl(new ButtonControl());
     </script>

 * @class TiledImage
 * @constructor
 * @parm id {String} Id of the div for top level
 **/
function TiledImage(id){
    /**
     * self: private scope of this
     * @property self
     * @type object
     * @private
     * @default this
     */
    var self=this,
    /**
     * property of current zoom
     * @property z_
     * @private
     * @type Number
     * @default 0
     */
    z_=0,
    /**
     * maxSize
     * @property maxSize
     * @private
     * @type Array[Number,Number]
     * @default [0,0]
     */
    maxSize=[0,0],
    /**
     * wrap flag
     * @property wrap
     * @private
     * @type Array[boolean,boolean]
     * @default [false,false]
     */
    wrap=[false,false],
    /**
     * position of top-left
     * @property position
     * @private
     * @type Array[Number,Number]
     * @default [0,0]
     */
    position=[0,0],
    /**
     * windowSize
     * @property windowSize
     * @private
     * @type Array[Number,Number]
     * @default [0,0]
     */
    windowSize=[0,0],
    /**
     * max Zoom level
     * @property maxZ
     * @private
     * @type Number
     * @default 0
     */
    maxZ=0,
    /**
     * min Zoom level
     * @property minZ
     * @private
     * @type Number
     * @default 10
     */
    minZ=10,
    /**
     * array of Controls
     * @property aCont
     * @private
     * @type Array[Object]
     * @default []
     */
    aCont=[],
    /**
     * array of Layer object
     * @property aLayers
     * @private
     * @type Array[Object]
     * @default []
     */
    aLayers=[],
    /**
     * array of Layer Listener
     * @property aChgL
     * @private
     * @type Array[Object]
     * @default []
     */
    aChgL=[],
    /**
     * array of move Listener
     * @property aChgM
     * @private
     * @type Array[Object]
     * @default []
     */
    aChgM=[],
    /**
     * array of zoom Listener
     * @property aChgZ
     * @private
     * @type Array[Object]
     * @default []
     */
    aChgZ=[],
    /**
     * array of resize Listener
     * @property aChgS
     * @private
     * @type Array[Object]
     * @default []
     */
    aChgS=[];
    
    var 
    /**
     * remove all the elements in each Layers
     * @private
     * @method removeAll
     */
    removeAll=function(){
	for(var i in aLayers){
	    aLayers[i].l.removeAll();
	}
    },
    /**
     * append elements in each Layers within the view
     * @private
     * @method append
     */
    append=function(){
	var p=position,w=windowSize,i;
	for(i in aLayers){
	    if(aLayers[i].show){
		aLayers[i].l.append(p[0],p[1],p[0]+w[0],p[1]+w[1]);
	    }
	}
	for(i in aChgM){
	    aChgM[i](self.getPosition());
	}
    },
    /**
     * wrapPosition 
     * @private
     * @method wrapPosition
     */
    wrapPosition=function(){
	var t,i=2;
	while(--i>=0){
	    t= maxSize[i]>>(maxZ-z_);
	    while(position[i]<-t){
		position[i]+=t;
	    }
	    position[i]%=t;
	}
    };

    d.mod(this,{
	/**
	 * set zoom level
	 * @public
	 * @method setZoom
	 * @param {Number} z zoom level
	 */
	setZoom:function(z){
	    if(z>maxZ)
		z=maxZ;
	    else if(z<minZ)
		z=minZ;
	    if(z==z_)return;
	    removeAll();

	    wrapPosition();
	    var p=position,w=windowSize,i=2,dz=z-z_;
	    while(--i>=0){
		p[i]+=w[i]/2;
		if(dz>0){ // zooming
		    p[i]<<=dz;
		}else {
		    p[i]>>=-dz;
		}
	    }
	    z_=z;
	    for(i in aLayers){
		aLayers[i].l.setZoom(z);
	    }
	    for(i in aChgZ){
		aChgZ[i](this.getZooms());
	    }
	    this.move(-w[0]/2,-w[1]/2);
	},
	/**
	 * set position (absolute jump)
	 * @public
	 * @method setPosition
	 * @param {Number} x position of originl image in x
	 * @param {Number} y position of originl image in y
	 */
	setPosition:function(x,y){
	    var	z=maxZ-z_;
	    position[0]=(x>>z)-windowSize[0]/2;
	    position[1]=(y>>z)-windowSize[1]/2;
	    d.go(this.map,[-position[0],-position[1]]);
	    append();
	},
	/**
	 * get absolute position (jump)
	 * @public
	 * @method getPosition
	 * @return {Array} [x,y] position of originl image in x,y
	 */
	getPosition:function(){
	    var	z=maxZ-z_,
	    w=windowSize,
	    x=[],i=2;
	    while(--i>=0){
		x[i]=(position[i]+w[i]/2)<<z;
	    }
	    return x;
	},
	/**
	 * move pixels in the zoom level
	 * @public
	 * @method move
	 * @param {Number} x pixels in the view in x
	 * @param {Number} y pixels in the view in y
	 */
	move:function(x,y){
	    var	z=maxZ-z_,
	    p=position,
	    i=2,t;
	    p[0]+=x;p[1]+=y;
	    while(--i>=0){
		if(!wrap[i]){
		    t=(maxSize[i]>>z)-windowSize[i];
		    if(t<0){
			p[i]=t/2;
		    } else if(p[i]<0){
			p[i]=0;
		    }else if(p[i]>t){
			p[i]=t;
		    }
		}
	    }
	    d.go(this.map,[-p[0],-p[1]]);
	    append();
	},
	/**
	 * get curent zoom level
	 * @public
	 * @method getZoom
	 * @return {Number} current zoom level
	 */
	getZoom:function(){
	    return z_;
	},
	/**
	 * get min, curent, max zoom levels
	 * @public
	 * @method getZooms
	 * @return {Array[Number,Number,Number]} [min, curent, max] zoom levels
	 */
	getZooms:function(){
	    return [minZ,z_,maxZ];
	},
	/**
	 * get current windows size
	 * @public
	 * @method getWindowSize
	 * @return {Array[Number,Number]} curent window size
	 */
	getWindowSize:function(){
	    return [windowSize[0],windowSize[1]];
	},
	/**
	 * add Control objects under this TiledImage object
	 * @public
	 * @method addControl
	 * @chainable
	 * @return this
	 */
	addControl:function(cont){
	    var elist=cont.setParent(this),
	    i=0,o;
	    for(;i<elist.length;i++){
		o=elist[i];
		if(o.m=='changelayer'){
		    /**
		     * Fire if layers status changed.
		     * @event changelayer
		     * @param aLayers {Array[Object]} array of layers status object.
		     * <ul><li>object{<ul>
		     * <li>l: layer object</li>
		     * <li>show: boolean for the showing status</li>
		     * </ul></li>
		     * </ul>
		     */
		    aChgL[aChgL.length]=o.f;
		    o.f(aLayers);
		} else if(o.m=='changezoom'){
		    /**
		     * Fire if zooms status changed.
		     * @event changezoom
		     * @param zooms {Array[Object]} array of [minZ, curZ, maxZ].
		     */
		    aChgZ[aChgZ.length]=o.f;
		    o.f(this.getZooms());
		} else if(o.m=='resize'){
		    /**
		     * Fire if the view window size changed.
		     * @event resize
		     * @param windowSize {Array[Number,Number]} array of [width, height].
		     */
		    aChgS[aChgS.length]=o.f;
		    o.f(this.getWindowSize());
		} else if(o.m=='move'){
		    /**
		     * Fire if the view is moved.
		     * @event move
		     * @param position {Array[Number,Number]} array of absolute Position.
		     */
		    aChgM[aChgM.length]=o.f;
		    o.f(this.getPosition());
		} else {
		    d.addEv(o);
		}
	    }
	    aCont[aCont.length]=cont;
	    return this
	},
	/**
	 * Add Layers objects under this TiledImage object
	 * @public
	 * @method addLayer
	 * @chainable
	 * @return this
	 */
	addLayer:function(layer,over){
	    aLayers[aLayers.length]={l:layer,show:true,over:over};
	    layer.setParent(this);

	    var i,z,max=layer.getWrap();
	    for(i=0;i<2;i++){
		wrap[i]|=max[i];
	    }

	    max=layer.getMaxZ();
	    if (max>maxZ){
		maxZ=max;
	    }

	    max=layer.getMaxSize();

	    z=0;
	    for(i=0;i<2;i++){
		if(maxSize[i]<max[i]){
		    maxSize[i]=max[i];
		    while(max[i]>>z >windowSize[i]){
			z++;
		    }
		}
	    }
	    if(minZ>maxZ-z){
		minZ=maxZ-z;
	    }
	    if(z_<minZ || z_>maxZ){
		this.setZoom(z_);
	    }else {
		layer.setZoom(z_);
		append();
	    }
	    for(i in aChgL){
		aChgL[i](aLayers);
	    }
	    return this
	},
	/**
	 * modulate Layer attribute
	 * @public
	 * @method modLayer
	 * @param {String} name nameof the layer 
	 * @param {boolean} v visibility
	 */
	modLayer:function(name,v){
	    var i,ls=aLayers;
	    for(i in aLayers){
		if(ls[i].l.getName()==name){
		    ls[i].show=v;
		    if(v){
			append();
		    } else {
			ls[i].l.removeAll();
		    }
		}
	    }
	    for(i in aChgL){
		aChgL[i](aLayers);
	    }
	},
	/**
	 * removeLayer attribute
	 * @public
	 * @method removeLayer
	 * @param {String} name of the layer 
	 */
	removeLayer:function(name){
	    var i,mz=0,ms=[0,0],z;
	    for(i=0;i<aLayers.length;i++){
		if(aLayers[i].l.getName()==name){
		    aLayers[i].l.detach();
		    z=i;
		    while(z<aLayers.length-1){
			aLayers[z]=aLayers[z+1];
			z++;
		    }
		    aLayers.length--;
		    i--;
		} else {
		    z=aLayers[i].l.getMaxZ();
		    if(mz<z){mz=z;}
		    z=aLayers[i].l.getMaxSize();
		    if(ms[0]<z[0]){ms[0]=z[0];}
		    if(ms[1]<z[1]){ms[1]=z[1];}
		}
	    }
	    maxZ=mz;
	    maxSize=ms;
	    for(z=i=0;i<2;i++){
		while(ms[i]>>z >windowSize[i]){
		    z++;
		}
	    }
	    minZ=mz-z;
	    this.setZoom(z_);
	    for(i in aChgL){
		aChgL[i](aLayers);
	    }
	},
	/**
	 * get Max Size
	 * @public
	 * @method getMaxSize
	 * @return {Array} maxSize
	 */
	getMaxSize:function(){
	    var r=[maxSize[0],maxSize[1]];
	    return r;
	},
	/**
	 * resize windows
	 * @public
	 * @method resize
	 * @param {Number} w width of the window
	 * @param {Number} h height of the window
	 */
	resize:function(w,h){
	    windowSize=[w,h];
	    d.mod(this.target,{style:{width:w+'px',height:h+'px'}});
	    append();
	    for(var i in aChgS){
		aChgS[i](this.getWindowSize());
	    }
	}
    });
    // initialize
    var e;
    /**
     * The target DOM Element of TiledImage
     * @property target
     * @public
     * @type DOMElement
     */
    (e=this.target=d.get(id)).className='tiledImage'; // top layer
    windowSize=[
	e.style.width.replace('px','')-0,
	e.style.height.replace('px','')-0
    ];

    /**
     * DOM Element of the moving layer
     * @property map
     * @public
     * @type DOMElement
     */
    d.go(this.map=d.app(e,'div', // map layer
		   {className:'map',onselectstart:'return false;'}),[0,0]);

};