This movie requires Flash Player 10
AutoPan Source Files (987)
I created an AS2 version of this years ago, and shared it on kirupa.com. It was a very popular small class. So, I’ve rebuilt the class in AS3. I hope some people find it useful. There isn’t anything profound here, but it makes for a quick and easy way to set up panning on large images, maps, etc. I haven’t tested this thoroughly, so if you see a bug let me know – accept it as-is for now.
The image I’m using in this sample was generated in Flash – I was playing around with color, motion, and generative renderings. I hope to post more samples of how that was created in the near future.
Here is the AutoPan Class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | /** * Author: Lex Talkington Design, Inc * August 7, 2009 * http://www.lextalkington.com/blog * * VERSION 1.0; * * Copyright (c) 2009 Lex Talkington and Lex Talkington Design, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * * */ /** * EXAMPLE: * Assuming there is a display object on the displaylist namesd "mc" * * var xPos:Number = 55; * var yPos:Number = 55; * var visibleWidth:Number = 430; * var visibleHeight:Number = 430; * var startingViewableX:Number = (mc.width-visibleWidth)/2; * var startingViewableY:Number = (mc.height-visibleHeight)/2; * var ease:Number = 0.7; * var cacheIt:Boolean = true; * var _autoPan:AutoPan = new AutoPan(mc, xPos, yPos, visibleWidth, visibleHeight, startingViewableX, startingViewableY, ease, cacheIt); * * PUBLIC METHODS * _autoPan.slideToPoint(370,250); * _autoPan.slideToPoint(10,10); * _autoPan.stopMotion(); * _autoPan.activateMotion(); * * TO REMOVE DISPOSE * _autoPan.dispose(); * _autoPan = null; * * */ package com.lextalkington.autopan { /** * Class description. * * @langversion ActionScript 3.0 * @playerversion Flash 9.0 * * @author Lex Talkington * @since 07.08.2009 */ import flash.display.*; import flash.events.*; import flash.geom.Rectangle; public class AutoPan extends Sprite { //------------- CONSTANTS public static const VERSION:String = "1.0"; //------------- PRIVATE PROPERTIES private var _clip:DisplayObject; private var _xp:Number; private var _yp:Number; private var _aw:Number; private var _ah:Number; private var _offsetx:Number; private var _offsety:Number; private var _ease:Number; private var _easeSlideTo:Number; private var _cache:Boolean; private var _rectangle:Rectangle; private var _clipParent:DisplayObject; private var _clipW:Number; private var _clipH:Number; private var _yRatio:Number; private var _yPos:Number; private var _xRatio:Number; private var _xPos:Number; private var _motionActive:Boolean; private var _toX:Number = 0; private var _toY:Number = 0; //---------------------------------------------------------------------------- //-------------------------------------- CONSTRUCTOR //---------------------------------------------------------------------------- /** * @Constructor * * CURRENTLY, THIS IS SET UP ONLY TO HANDLE MOVEMENT ON A DISPLAYOBJECT THAT EXISTS ON THE DISPLAY LIST * @clip reference to a DisplayObject that has been added to Display List * @xp the x position of the rendered autopan * @yp the y position of the rendered autopan * @aw the aperture width of the autopan * @ah the aperture height of the autopan * @offsetx the starting postion of the image, calculated to the left of zero * @offsety the starting postion of the image, calculated above zero * @ease contols the amount of ease from 0-1, default is 0.7 * @cache toggles cacheAsBitmap, default is true * */ public function AutoPan(clip:DisplayObject, xp:Number, yp:Number, aw:Number, ah:Number, offsetx:Number, offsety:Number, ease:Number=0.7, cache:Boolean=true) { _clip = clip; _xp = xp; _yp = yp; _aw = aw; _ah = ah; _offsetx = offsetx; _offsety = offsety; _ease = ease; _easeSlideTo = ease*0.5; // we reduce the provided easing by half to use withing the moveToPoint method _cache = cache; init(); } //---------------------------------------------------------------------------- //-------------------------------------- PRIVATE METHODS //---------------------------------------------------------------------------- //----------------------------------- // init //----------------------------------- private function init():void { _clip.x = _xp; _clip.y = _yp; _clipW = _clip.width; _clipH = _clip.height; try { _clipParent = _clip.parent; } catch(e:*) { throw new Error("The clip ("+_clip+") you passed to AutoPan does not have a parent - it is probably not on the display list which is necessary for AutoPan to work"); return; } // set cache if(_cache) _clip.cacheAsBitmap = true; // create rectangle for scrollrect _rectangle = new Rectangle(_offsetx, _offsety, _aw, _ah); // set scrollrect on displayObject _clip.scrollRect = _rectangle; // set mouse event to start movement _clip.addEventListener(MouseEvent.MOUSE_OVER, initiateMovement, false, 0, true); // allow motion _motionActive = true; } //----------------------------------- // initiate movement //----------------------------------- private function initiateMovement(e:Event):void { if(hasEventListener(Event.ENTER_FRAME)) { removeEventListener(Event.ENTER_FRAME, move); removeEventListener(Event.ENTER_FRAME, moveToPoint); } _clip.removeEventListener(MouseEvent.MOUSE_OVER, initiateMovement); addEventListener(Event.ENTER_FRAME, move); } //----------------------------------- // move //----------------------------------- private function move(e:Event):void { var xm:int = _clipParent.mouseX; var ym:int = _clipParent.mouseY; // This catches a firefox issue where if the clip is in motion, and if you commmand-n open a new window, the ENTER_FRAME continues to fire. if(checkMouseLeave(xm,ym)) return; _clip.scrollRect = getXY(xm,ym); // check if the mouse is over the visible clip area if(!_clip.hitTestPoint(mouseX,mouseY,true)) { killMovement(); } } //----------------------------------- // check if the mouse has left the stage - added as a FireFox catch //----------------------------------- private function checkMouseLeave(xp:int,yp:int):Boolean { // However, it appears that all mouse x,y coords come through as negative integers when this out-of-window tracking happens. The numbers usually appear as -107374182, -107374182 // To avoid having to add this instance to the stage and utilize the MOUSE_LEAVE event, // I'm killing motion if the mouse x,y are above 10,000 if(xp<0) xp = -xp; if(yp<0) yp = -yp; if(xp>10000 || xp>10000) { killMovement(); return true; } return false; } //----------------------------------- // get X,Y : calculate x,y based on mouse position //----------------------------------- private function getXY(xp:Number,yp:Number):Rectangle { // calculate the X offset / positions _xRatio = (xp-_clip.x)/_rectangle.width; _xPos = _xRatio*(_clipW-_rectangle.width); // calculate the Y offset / positions _yRatio = (yp-_clip.y)/_rectangle.height; _yPos = _yRatio*(_clipH-_rectangle.height); // set the rectangles offsets _rectangle.x = _xPos-(_xPos-_rectangle.x)*_ease; _rectangle.y = _yPos-(_yPos-_rectangle.y)*_ease; return _rectangle; } //----------------------------------- // kill movement //----------------------------------- private function killMovement():void { if(hasEventListener(Event.ENTER_FRAME)) { removeEventListener(Event.ENTER_FRAME, move); removeEventListener(Event.ENTER_FRAME, moveToPoint); } if(_motionActive) { if(!_clip.hasEventListener(MouseEvent.MOUSE_OVER)) { _clip.addEventListener(MouseEvent.MOUSE_OVER, initiateMovement, false, 0, true); } } else { if(_clip.hasEventListener(MouseEvent.MOUSE_OVER)) _clip.removeEventListener(MouseEvent.MOUSE_OVER, initiateMovement); } } //----------------------------------- // move to point //----------------------------------- private function moveToPoint(e:Event):void { _rectangle.x += (_toX-_rectangle.x)*_easeSlideTo; _rectangle.y += (_toY-_rectangle.y)*_easeSlideTo; var disx:Number = _toX-_rectangle.x; var disy:Number = _toX-_rectangle.x; if(disx<0) disx = -disx; if(disy<0) disy = -disy; if(disx<1) { if(disy<1) { // if the clip has reached it's destination, stop motion, // set the end destination to actual, exact position requested: _toX, _toY killMovement(); _rectangle.x = _toX; _rectangle.y = _toY; _clip.scrollRect = _rectangle; return; } } _clip.scrollRect = _rectangle; } //---------------------------------------------------------------------------- //-------------------------------------- PUBLIC METHODS //---------------------------------------------------------------------------- /** * slide to point * @xp Number representing a distance, in pixels, to the left of the left edge of the visible aperture * @yp Number representing a distance, in pixels, above the top edge of the visible aperture * * */ public function slideToPoint(xp:Number,yp:Number):void { _toX = xp; _toY = yp; killMovement(); addEventListener(Event.ENTER_FRAME, moveToPoint); } //----------------------------------- // stop motion //----------------------------------- public function stopMotion():void { _motionActive = false; killMovement(); } //----------------------------------- // activate motion //----------------------------------- public function activateMotion():void { _motionActive = true; killMovement(); } //----------------------------------- // dispose - removes all events, sets scrollrect to null //----------------------------------- public function dispose():void { _motionActive = false; killMovement(); _clip.scrollRect = null; _clip = null; _rectangle = null; _clipParent = null; } //---------------------------------------------------------------------------- //-------------------------------------- UTILITY METHODS //---------------------------------------------------------------------------- private function tracer(str:*):void { trace("[ AutoPan ] :: ", str); } } } |
14 Comments
I responded to your question at kirupa (see here) as well as provided (or tried to) an explanatory FLA showing how scrollRect responds to a scaled clip. Hopefully that helps get you on the right track.
Great class! I’m trying to add zoom functionality to this for a project I’m working on, and have run into a small issue. I want to keep the viewable area locked when zooming, and only affect the mc, however, even with setting dimensions for the _rectangle, and defining the aperture width and height as the same, when I scale mc, I get a scale for the viewing window as well. Any ideas?
HI Ricardo—my classes aren’t set up for that type of functionality. You’d have to dig into the AutoPan Class and add that type of functionality. Basically, the _aw and _ah (aperture width and height) properties would need to be set to the stage.stageWidth stage.stageHeight. But you’d also have to set the width and height of the _rectangle object that is use for the scrollRect. And lastly, set _clip.scrollRect = _rectangle; Hope this helps lead you in the right direction.
Lex!
Not so long ago i thanked you for your Points around a Circle class. And now this!
Keep up the great work dude.
Clark.
Theres a way to use it relaative to the Stage width and height, replacing the visibleWidth and visibleHeight with onResize handler?
Tanks in advance
Hi, I’m new to as3. It seems than you have used flash cs4 to create this. I’m trying to use it in a project I’m working on. If I save the file to cs3 and reopen it and publish an error message appears: 1046: Type was not found or was not a compile-time constant: MovieClip.
Do you know what should I fix to make it work again? Thanks
Good post. Thank you for this.
Hi Lex,
Thanks for the code! I am trying to invoke the public methods, stopMotion(),etc. to buttons within the mc instance.
My goal was to stop the panning when I click on the thumbnail that creates the child and then return to panning when I close the child.
I have tried things like this.parent.stopMotion() and MovieClip(this.parent).stopMotion()
I get various errors.
TypeError: Error #1034: Type Coercion failed: cannot convert com.lextalkington.autopan::AutoPanDocument@3d102681 to flash.display.MovieClip.
1061: Call to a possibly undefined method stopMotion through a reference with static type flash.display:DisplayObjectContainer.
Lex, phenominal class.
A world of help and just exactly the type of effect I was looking for.
Thanks so much.
@Chris – You should be able to play with this line within the constructor:
The easing value you pass into the constructor is cut in half there – if you change 0.5 to something else, you’ll have some control over the speed. Hope this helps!
Fantastic class! Any way to control the speed of the slideToPoint function?
Thanks a lot for such useful class!!!
It works really good and saved me lots of time, thanks again
I reposted the AS2 version – however, it has a few bugs, mainly the one FireFox bug that has been repaired in the AS3 version – so you may have to deal with that, but you can download the AS2 version here
Hi there!
Really cool panning tool. Do you possibly still have the AS2 version somewhere?
Thanks