|
||||||||
PREV NEXT | FRAMES NO FRAMES |
Mapserv class provides support functions for advanced
web clients using the MapServer. Performs coordinate management,
layer management, and url construction services.
Class Summary | |
Mapserv | This is the basic Mapserv class. |
Method Summary | |
static void
|
do_query()
function to be called at query time. |
static void
|
map_draw()
function to be called at map draw time. |
/** * @fileoverview Mapserv class provides support functions for advanced * web clients using the MapServer. Performs coordinate management, * layer management, and url construction services. */ // Support functions for advanced web clients using the // MapServer. Original coding 02-25-2000. - SDL - // // Re-write for MapServer 3.6+ and DHTML standardization July 2002. - SDL - // Simplified layer handling with the addition of DHTML legend containers (11/4/2004). - SDL - // Big-time re-write to de-couple from dbox.js etc... (04/10/2006). - SDL - var MAPSERV_UNITS_METERS = 0; // unit types var MAPSERV_UNITS_FEET = 1; var MAPSERV_UNITS_MILES = 2; var MAPSERV_UNITS_KILOMETERS = 3; var MAPSERV_UNITS_DD = 4; var MAPSERV_DRAW = 0; // callback types var MAPSERV_QUERY = 1; /** * Construct a new Mapserv object. * @class This is the basic Mapserv class. * * @constructor * @param {String} mapserver The url for the MapServer instance that will create maps. * @param {String} mapfile The mapfile to be used. * @param {Double} minx The minimum x coordinate for the initial (default) map extent. * @param {Double} miny The minimum y coordinate for the initial (default) map extent. * @param {Double} maxx The maximum x coordinate for the initial (default) map extent. * @param {Double} maxy The maximum y coordinate for the initial (default) map extent. * @param {Integer} width The width (in pixels) of the maps to be created. * @param {Integer} height The height (in pixels) of the maps to be created. * @return A new mapserv object */ function Mapserv(mapserver, mapfile, minx, miny, maxx, maxy, width, height) { /** * mode in which the MapServer executable will be called. * <p>Valid values are map, query and nquery although it is certainly possible * to create more complex queries outside of the Mapserv object.</p> * @type String */ this.mode = 'map'; /** * a complete url for a map draw or query operation. * @type String */ this.url = ''; /** * an associative array of layer status, keyed by layer name; values * are booleans. * @type Array */ this.layers = new Array(); /** * the url for the MapServer executable that will create maps. * @type String */ this.mapserver = mapserver; /** * the url for the MapServer executable that will handle queries. * @type String */ this.queryserver = mapserver; /** * the MapServer configuration file for map draws. * @type String */ this.mapfile = mapfile; /** * the MapServer configuration file for query operations. * @type String */ this.queryfile = mapfile; /** * a four-member array of Doubles defining the rectangular extent of * the map (in map coordinates). * <p> * <ul> * <li>extent[0] - minimum x map coordinate</li> * <li>extent[1] - minimum y map coordinate</li> * <li>extent[2] - maximum x map coordinate</li> * <li>extent[3] - maximum y map coordinate</li> * </ul> * </p> * @type Array */ this.extent = new Array(minx, miny, maxx, maxy); /** * a two-member array of Doubles defining a point of interest (in map * coordinates) to the current operation (typically from a user's * mouse click). * <p> * <ul> * <li>point[0] is x</li> * <li>point[1] is y</li> * </ul> * </p> * @type Array */ this.point = new Array(-1, -1); /** * a four-member array of Doubles defining a rectangular extent (in * map coordinates) for a query operation. * <p> * <ul> * <li>queryextent[0] is minimum x</li> * <li>queryextent[1] is minimum y</li> * <li>queryextent[2] is maximum x</li> * <li>queryextent[3] is maximum y</li> * </ul> * </p> * @type Array */ this.queryextent = new Array(-1, -1, -1, -1); /** * a two-member array of Doubles defining a point of interest (in * image coordinates) to the current query operation (typically from * a user's mouse click). * <p> * <ul> * <li>querypoint[0] is x</li> * <li>querypoint[1] is y</li> * </ul> * </p> * @type Array */ this.querypoint = new Array(-1, -1); /** * the width of the map image (in pixels). * @type Integer */ this.width = width; /** * the height of the map image (in pixels). * @type Integer */ this.height = height; /** * a url query string ("&this=that&some=other") used to pass any * application-specific options for a map draw operation that are * not covered in the {@link #draw} method. * @type String */ this.options = ''; /** * a url query string ("&this=that&some=other") used to store any * application-specific options for a query operation that are not * covered in the {@link #query} method. * @type String */ this.queryoptions = ''; /** * a reference map object. * @type Mapserv */ this.referencemap = null; /** * calculated length of a pixel side in map units. * @type Double */ this.cellsize = adjustExtent(this.extent, this.width, this.height); /** * the extent that was passed to this Mapserv instance at construction. * @type Array */ this.defaultextent = this.extent; /** * the zoom factor to be applied on zoom-in operations (the inverse * is taken for zoom-out operations). */ this.zoomsize = 2; /** * direction of zoom. * <p> * <ul> * <li>-1 = out</li> * <li>0 = none (pan)</li> * <li>1 = in</li> * </ul> * </p> * @type Integer */ this.zoomdir = 0; // pan to start /** * minimum scale to allow for map draws. * <p>value used is denominator of the representative fraction * (1:<b>x</b>)</p> * <p>value of -1 indicates no minimum</p> * @type Integer */ this.minscale = -1; /** * maximum scale to allow for map draws. * <p>value used is denominator of the representative fraction * (1:<b>x</b>)</p> * <p>value of -1 indicates no maximum</p> * @type Integer */ this.maxscale = -1; /** * amount by which to move the map in automatic pan operations. * <p>0 < pansize < 1</p> * @type Float */ this.pansize = .8; /** * a value used in scale calculations. * <p>default: 72 (typical monitor resolution)</p> * @type Integer */ this.pixelsPerInch = 72; /** * number of inches in the current map unit. * <p>default: 39.3701 (inches in a meter)</p> * @type Float */ this.inchesPerMapUnit = 39.3701; // handlers/callbacks /** * function to be called at map draw time. * <p>Must be defined and set (via {@link #setHandler}) elsewhere in * the application, or nothing happens at draw time.</p> * <p>A minimal setup, handling nothing but the map draw, might be:<br> * <font size="-1">(note the "ms" variable below is a Mapserv object * instance, and "function" is intentionally mispelled to avoid * confusing our documentation generator)</font><p> * <pre> * function map_draw() { * main.setImage(ms.url); * } * ms.setHandler(MAPSERV_DRAW, map_draw); * </pre> * <p>Typically, the function would be more complex, handling * reference map, scalebar, and legend drawing as well. Developers * are free to implement essentially any desired functionality * here.</p> * @type Function */ this.drawHandler = null; /** * function to be called at query time. * <p>Must be defined and set (via {@link #setHandler}) elsewhere in * the application, or nothing happens at query time.</p> * <p>A setup to display query results in a new window might be:<br> * <font size="-1">(note the "ms" variable below is a Mapserv object * instance, and "function" is intentionally mispelled to avoid * confusing our documentation generator)</font><p> * <pre> * function do_query() { * querywin = window.open(ms.url, 'querywin'); * querywin.focus(); * } * ms.setHandler(MAPSERV_QUERY, do_query); * </pre> * <p>Developers are free to implement essentially any desired * functionality here.</p> * @type Function */ this.queryHandler = null; /** * object reference to avoid "this" conflicts with callbacks and event handlers * @private * @type Mapserv */ var self = this; // // private functions // /** * adjust values of given extent to fit {@link #width} and {@link * #height} * @private * @param {Array} extent extent Array to be adjusted * @param {Integer} width width of map image in pixels * @param {Integer} height of map image in pixels * @returns {Double} ground resolution of pixels in map image */ function adjustExtent(extent, width, height) { var cellsize = Math.max((extent[2] - extent[0])/width, (extent[3] - extent[1])/height); if(cellsize > 0) { var ox = Math.max((width - (extent[2] - extent[0])/cellsize)/2,0); var oy = Math.max((height - (extent[3] - extent[1])/cellsize)/2,0); extent[0] = extent[0] - ox*cellsize; extent[1] = extent[1] - oy*cellsize; extent[2] = extent[2] + ox*cellsize; extent[3] = extent[3] + oy*cellsize; } return(cellsize); } /** * convert an extent array to a polygon array. * @private * @param {Array} extent extent array to be converted * @returns {Array} polygon array (essentially a set of five * coordinate pairs) */ function extentToPolygon(extent) { var polygon = new Array(10); polygon[0] = extent[0]; polygon[1] = extent[3]; polygon[2] = extent[2]; polygon[3] = extent[3]; polygon[4] = extent[2]; polygon[5] = extent[1]; polygon[6] = extent[0]; polygon[7] = extent[1]; polygon[8] = extent[0]; polygon[9] = extent[3]; return(polygon); } // // function prototypes follow (potential callbacks use 'self' instead of 'this') // /** * set the map units. * @param {Enumerated} type constant for desired units type. Valid * type values are: * <ul> * <li>MAPSERV_UNITS_METERS (0)</li> * <li>MAPSERV_UNITS_FEET (1)</li> * <li>MAPSERV_UNITS_MILES (2)</li> * <li>MAPSERV_UNITS_KILOMETERS (3)</li> * <li>MAPSERV_UNITS_DD (4)</li> * </ul> */ this.setUnits = function(type) { if (type == MAPSERV_UNITS_METERS) self.inchesPerMapUnit = 39.3701; else if (type == MAPSERV_UNITS_FEET) self.inchesPerMapUnit = 12.0; else if (type == MAPSERV_UNITS_MILES) self.inchesPerMapUnit = 63360.0; else if (type == MAPSERV_UNITS_KILOMETERS) self.inchesPerMapUnit = 39370.1; else if (type == MAPSERV_UNITS_DD) self.inchesPerMapUnit = 4374754; // at the equator } /** * set a handler function for draw/query operations. * @param {Enumerated} type constant for handler type to be set. * Valid type values are: * <ul> * <li>MAPSERV_DRAW (0)</li> * <li>MAPSERV_QUERY (1)</li> * </ul> * @param {Function} handler function to be called * @see #drawhandler * @see #queryhandler */ this.setHandler = function(type, handler) { if (type == MAPSERV_DRAW) self.drawHandler = handler; else if (type == MAPSERV_QUERY) self.queryHandler = handler; } /** * convert an image coordinate pair to a map coordinate pair, and * store in the {@link #point} field. * @param {Integer} x the x image coordinate * @param {Integer} y the y image coordinate */ this.imageToMap = function(x, y) { var dx, dy; dx = this.extent[2] - this.extent[0]; dy = this.extent[3] - this.extent[1]; this.point[0] = this.extent[0] + this.cellsize*x; this.point[1] = this.extent[3] - this.cellsize*y; } /** * set the draw/query status of a layer. * @param {String} name The name of the layer to set status for * @param {Boolean} status <b>0/false</b> - off; <b>1/true</b> - on */ this.setLayer = function(name, status) { self.layers[name] = status; } /** * Set draw/query status for all layers to off. */ this.layersOff = function() { self.layers = new Array(); } /** * Get the list of currently active layers. * @param {String} delimiter the character(s) to use to delimit the returned list * @returns A delimited string of active layers * @type String */ this.getLayers = function(delimeter) { var list = new Array(); var keys; for (key in this.layers) if(this.layers[key]) list.push(key); return list.join(delimeter); } /** * convert a box defined in image coordinates to an extent defined in * map coordinates and store in the {@link #extent} field. * @param {Integer} minx minimum x image coordinate * @param {Integer} miny minimum y image coordinate * @param {Integer} maxx maximum x image coordinate * @param {Integer} maxy maximum y image coordinate */ this.applyBox = function(minx, miny, maxx, maxy) { var temp = new Array(4); temp[0] = this.extent[0] + this.cellsize*minx; temp[1] = this.extent[3] - this.cellsize*maxy; temp[2] = this.extent[0] + this.cellsize*maxx; temp[3] = this.extent[3] - this.cellsize*miny; this.extent = temp; this.cellsize = adjustExtent(this.extent, this.width, this.height); if(this.minscale != -1 && this.getScale() < this.minscale) { x = (this.extent[2] + this.extent[0])/2; y = (this.extent[3] + this.extent[1])/2; this.setExtentFromScale(x, y, this.minscale); } if(this.maxscale != -1 && this.getScale() > this.maxscale) { x = (this.extent[2] + this.extent[0])/2; y = (this.extent[3] + this.extent[1])/2; this.setExtentFromScale(x, y, this.maxscale); } } /** * calculate a new map extent based on {@link #zoomdir}, {@link * #zoomsize}, and the passed point (in image coordinates), and store * in the {@link #extent} field. * @param {Integer} x image coordinate x * @param {Integer} y image coordinate y */ this.applyZoom = function(x, y) { var dx, dy, mx, my; var zoom; if(this.zoomdir == 1 && this.zoomsize != 0) zoom = this.zoomsize; else if(this.zoomdir == -1 && this.zoomsize != 0) zoom = 1/this.zoomsize; else zoom = 1; dx = this.extent[2] - this.extent[0]; dy = this.extent[3] - this.extent[1]; mx = this.extent[0] + this.cellsize*x; // convert *click* to map coordinates my = this.extent[3] - this.cellsize*y; this.extent[0] = mx - .5*(dx/zoom); this.extent[1] = my - .5*(dy/zoom); this.extent[2] = mx + .5*(dx/zoom); this.extent[3] = my + .5*(dy/zoom); this.cellsize = adjustExtent(this.extent, this.width, this.height); if(this.minscale != -1 && this.getScale() < this.minscale) { x = (this.extent[2] + this.extent[0])/2; y = (this.extent[3] + this.extent[1])/2; this.setExtentFromScale(x, y, this.minscale); } if(this.maxscale != -1 && this.getScale() > this.maxscale) { x = (this.extent[2] + this.extent[0])/2; y = (this.extent[3] + this.extent[1])/2; this.setExtentFromScale(x, y, this.maxscale); } } /** * calculate a new map extent to be centered on an image coordinate * from the reference map image, and store in the {@link #extent} * field. * @param {Integer} x reference map image coordinate x value * @param {Integer} y reference map image coordinate y value */ this.applyReference = function(x,y) { var mx, my; var dx, dy; if(!this.referencemap) return; dx = this.extent[2] - this.extent[0]; dy = this.extent[3] - this.extent[1]; mx = this.referencemap.extent[0] + this.referencemap.cellsize*x; my = this.referencemap.extent[3] - this.referencemap.cellsize*y; this.extent[0] = mx - .5*dx; this.extent[1] = my - .5*dy; this.extent[2] = mx + .5*dx; this.extent[3] = my + .5*dy; this.cellsize = adjustExtent(this.extent, this.width, this.height); } /** * construct a four-member query extent array in image coordinates * and store in the {@link #queryextent} field. * @param {Integer} minx minimum x image coordinate * @param {Integer} miny minimum y image coordinate * @param {Integer} maxx maximum x image coordinate * @param {Integer} maxy maximum y image coordinate */ this.applyBoxQuery = function(minx, miny, maxx, maxy) { var temp = new Array(4); // convert to map coordinates // temp[0] = this.extent[0] + this.cellsize*minx; // temp[1] = this.extent[3] - this.cellsize*maxy; // temp[2] = this.extent[0] + this.cellsize*maxx; // temp[3] = this.extent[3] - this.cellsize*miny; // leave in pixel coordinates temp[0] = minx; temp[1] = miny; temp[2] = maxx; temp[3] = maxy; this.queryextent = temp; } /** * construct a two-member query point array in image coordinates * and store in the {@link #querypoint} field. * @param {Integer} x image coordinate x value * @param {Integer} y image coordinate y value */ this.applyPointQuery = function(x,y) { var dx, dy; // convert to map coordinates // dx = this.extent[2] - this.extent[0]; // dy = this.extent[3] - this.extent[1]; // this.querypoint[0] = this.extent[0] + this.cellsize*x; // this.querypoint[1] = this.extent[3] - this.cellsize*y; // leave in pixel coordinates this.querypoint[0] = x; this.querypoint[1] = y; } /** * construct a query url using the current settings of various * fields, store in the {@link #url} field, and call the {@link * #queryHandler}. * <p>Fields/methods used in assembling the url are:</p> * <ul> * <li>{@link #queryserver}</li> * <li>(mode=) {@link #mode}</li> * <li>(map=) {@link #queryfile}</li> * <li>(imgext=) {@link #extent}</li> * <li>(imgxy=) {@link #querypoint}</li> * <li>(imgbox=) {@link #queryextent}</li> * <li>(imgsize=) {@link #width} {@link #height}</li> * <li>(layers=) {@link #getLayers}</li> * <li>{@link #queryoptions}</li> * </ul> */ this.query = function() { var layerlist = this.getLayers('+'); // point or box based queries this.url = this.queryserver + '?mode=' + this.mode + '&map=' + this.queryfile + '&imgext=' + this.extent.join('+') + '&imgxy=' + this.querypoint.join('+') + '&imgbox=' + this.queryextent.join('+') + '&imgsize=' + this.width + '+' + this.height; if(layerlist) this.url += '&layers=' + layerlist; if(this.queryoptions) this.url += this.queryoptions; if (self.queryHandler) self.queryHandler(); return; } /** * construct a pair of urls (one for the main map and one for the * reference map, if applicable) using the current settings of * various fields, store them in the {@link #url} and {@link * #referencemap}.url fields, respectively, and call the {@link * #drawHandler}. * <p>Fields/methods used in assembling the url for the main map * are:</p> * <ul> * <li>{@link #mapserver}</li> * <li>(map=) {@link #mapfile}</li> * <li>(mapext=) {@link #extent}</li> * <li>(mapsize=) {@link #width}+{@link #height}</li> * <li>(layers=) {@link #getLayers}</li> * <li>{@link #options}</li> * </ul> * <p>Fields/methods used in assembling the url for the reference map * are:</p> * <ul> * <li>{@link #mapserver}</li> * <li>(map=) {@link #referencemap}.mapfile</li> * <li>(mapext=) {@link #extent}</li> * <li>(mapsize=) {@link #width}+{@link #height}</li> * </ul> */ this.draw = function() { var layerlist = this.getLayers('+'); if(this.referencemap) this.referencemap.url = this.mapserver + '?mode=reference' + '&map=' + this.referencemap.mapfile + '&mapext=' + this.extent.join('+') + '&mapsize=' + this.width + '+' + this.height; this.url = this.mapserver + '?mode=map' + '&map=' + this.mapfile + '&mapext=' + this.extent.join('+') + '&mapsize=' + this.width + '+' + this.height + '&layers=' + layerlist + this.options; if (self.drawHandler) self.drawHandler(); } /** * redraw the map at the default extent. * @see #defaultextent */ this.zoomDefault = function() { this.mode = map; this.extent = this.defaultextent; this.cellsize = adjustExtent(this.extent, this.width, this.height); this.draw(); } /** * set {@link #extent} using the given values. * @param {Double} minx minimum x coordinate * @param {Double} miny minimum y coordinate * @param {Double} maxx maximum x coordinate * @param {Double} maxy maximum y coordinate */ this.setExtent = function(minx, miny, maxx, maxy) { this.extent[0] = minx; this.extent[1] = miny; this.extent[2] = maxx; this.extent[3] = maxy; this.cellsize = adjustExtent(this.extent, this.width, this.height); if(this.minscale != -1 && this.getScale() < this.minscale) { x = (this.extent[2] + this.extent[0])/2; y = (this.extent[3] + this.extent[1])/2; this.setExtentFromScale(x, y, this.minscale); } if(this.maxscale != -1 && this.getScale() > this.maxscale) { x = (this.extent[2] + this.extent[0])/2; y = (this.extent[3] + this.extent[1])/2; this.setExtentFromScale(x, y, this.maxscale); } } /** * set {@link #extent} to be centered on the given point and minimally * fit the circle defined by the point and supplied radius. * @private * @param {Double} x map coordinate x value * @param {Double} y map coordinate y value * @param {Double} radius desired distance from given point to edge of map */ this.setExtentFromRadius = function(x, y, radius) { this.extent[0] = x - radius; this.extent[1] = y - radius; this.extent[2] = x + radius; this.extent[3] = y + radius; this.cellsize = adjustExtent(this.extent, this.width, this.height); if(this.minscale != -1 && this.getScale() < this.minscale) { x = (this.extent[2] + this.extent[0])/2; y = (this.extent[3] + this.extent[1])/2; this.setExtentFromScale(x, y, this.minscale); } if(this.maxscale != -1 && this.getScale() > this.maxscale) { x = (this.extent[2] + this.extent[0])/2; y = (this.extent[3] + this.extent[1])/2; this.setExtentFromScale(x, y, this.maxscale); } } /** * draw a new map centered on the given point, with an {@link #extent} * that minimally fits the circle defined by the point and supplied radius. * @param {Double} x map coordinate x value * @param {Double} y map coordinate y value * @param {Double} radius desired distance from given point to edge of map */ this.zoomRadius = function(x, y, radius) { this.setExtentFromRadius(x, y, radius); this.draw(); } /** * get the nominal scale based on current settings. * @returns {Double} scale the nominal scale */ this.getScale = function() { var gd, md; md = (this.width-1)/(this.pixelsPerInch*this.inchesPerMapUnit); gd = this.extent[2] - this.extent[0]; return(gd/md); } /** * set {@link #extent} centered on the given point using the given * scale. * @param {Double} x map coordinate x value * @param {Double} y map coordinate y value * @param {Integer} scale desired scale, given as denominator of the * representative fraction (1:<b>x</b>) */ this.setExtentFromScale = function(x, y, scale) { // remove leading 1: and any commas // var scale = 1.0*scale.replace(/,|1:/g,""); if((this.minscale != -1) && (scale < this.minscale)) scale = this.minscale; if((this.maxscale != -1) && (scale > this.maxscale)) scale = this.maxscale; this.cellsize = (scale/this.pixelsPerInch)/this.inchesPerMapUnit; this.extent[0] = x - this.cellsize*this.width/2.0; this.extent[1] = y - this.cellsize*this.height/2.0; this.extent[2] = x + this.cellsize*this.width/2.0; this.extent[3] = y + this.cellsize*this.height/2.0; this.cellsize = adjustExtent(this.extent, this.width, this.height); } /** * recenter the map at the given point, using the current scale. * @param {Double} x map coordinate x value * @param {Double} y map coordinate y value */ this.recenter = function(x, y) { this.setExtentFromScale(x, y, this.getScale()); this.draw(); } /** * recenter the map at the given point, using the given scale. * @param {Double} x map coordinate x value * @param {Double} y map coordinate y value * @param {Integer} scale desired scale, given as denominator of the * representative fraction (1:<b>x</b>) */ this.zoomScale = function(x, y, scale) { this.setExtentFromScale(x, y, scale); this.draw(); } /** * zoom in centered on the given point, using the current {@link * #zoomsize} setting. * @param {Double} x map coordinate x value * @param {Double} y map coordinate y value */ this.zoomIn = function(x,y) { this.zoomdir = 1; this.applyZoom(x,y); this.draw(); this.zoomdir = 0; } /** * zoom out centered on the given point, using the inverse of the * current {@link #zoomsize} setting. * @param {Double} x map coordinate x value * @param {Double} y map coordinate y value */ this.zoomOut = function(x,y) { this.zoomdir = -1; this.applyZoom(x,y); this.draw(); this.zoomdir = 0; } /** * pan map in the given direction, using the current {@link * #pansize} setting. * @param {Enumerated} direction direction to pan. Specified as a * lowercase abbreviation of one of the eight cardinal/primary * intercardinal directions: * <p> * <ul> * <li>n</li> * <li>ne</li> * <li>e</li> * <li>se</li> * <li>s</li> * <li>sw</li> * <li>w</li> * <li>nw</li> * </ul> * </p> */ this.pan = function(direction) { this.zoomdir = 0; if(direction == 'n') { x = (this.width-1)/2.0; y = 0 - this.height*this.pansize + this.height/2.0; } else if(direction == 'nw') { x = 0 - this.width*this.pansize + this.width/2.0; y = 0 - this.height*this.pansize + this.height/2.0; } else if(direction == 'ne') { x = (this.width-1) + this.width*this.pansize - this.width/2.0; y = 0 - this.height*this.pansize + this.height/2.0; } else if(direction == 's') { x = (this.width-1)/2.0; y = (this.height-1) + this.height*this.pansize - this.height/2.0; } else if(direction == 'sw') { x = 0 - this.width*this.pansize + this.width/2.0; y = (this.height-1) + this.height*this.pansize - this.height/2.0; } else if(direction == 'se') { x = (this.width-1) + this.width*this.pansize - this.width/2.0; y = (this.height-1) + this.height*this.pansize - this.height/2.0; } else if(direction == 'e') { x = (this.width-1) + this.width*this.pansize - this.width/2.0; y = (this.height-1)/2.0; } else if(direction == 'w') { x = 0 - this.width*this.pansize + this.width/2.0; y = (this.height-1)/2.0; } this.applyZoom(x,y); this.draw(); } }
|
||||||||
PREV NEXT | FRAMES NO FRAMES |