I am very fond of Processing, and the way it easily makes it possible to experiment with design ideas. One of the powerful features are it’s map() function, that takes a value and remaps it from one range to another. I haven’t seen a similar function in the ActionScript 3.0 reference, so I decided to make one to my own utils-library, because it is something the can come in handy in many situations. First I looked at using the Point() class, and interpolation to describe the ratios, but actually found it easier to just do it with regular math.
I haven’t looked at performance yet, and there is possibly a lot of ways to optimize this code – this article can be a start for further fine tuning. The helper function looks like this:
function map(val:Number, inMin:Number, inMax:Number, outMin:Number, outMax:Number, decimals:uint=0):Number { var returnVal:Number; // Sets the total range for both in and out var inRange:Number = inMax - inMin; var outRange:Number = outMax - outMin; //calculates the ratio for the value in relation to the in range var ratio:Number = (val - inMin)/inRange; //makes sure that the value is within range val = Math.max(inMin, val); val = Math.min(inMax, val); //Finds the same ratio in the out range and shift it into place returnVal = (outRange * ratio) + outMin; //rounding of the decimals var factor:int = Math.pow(10,decimals); returnVal = Math.round(returnVal*factor)/factor; return returnVal; }
The function takes the the following arguments:
- val: the number to be remapped
- inMin and inMax: The original range, in which the value is measures in relation to.
- outMin and outMax: The destination range, that the value will be re-mapped to
- decimals: sets the precision in decimals (optional)
var inRange:Number = inMax - inMin; var outRange:Number = outMax - outMin;
val = Math.max(inMin, val); val = Math.min(inMax, val);
var ratio:Number = (val - inMin)/inRange;
returnVal = (outRange * ratio) + outMin;
var factor:int = Math.pow(10,decimals); returnVal = Math.round(returnVal*factor)/factor;
- factor is 1000 (3 digits)
- value is 134.744637
- Multiplication results in 134744.637
- Rounding returns 134745
- divided by 1000 gives the result 134.745
Optimization
An example
import flash.display.Sprite; import flash.events.MouseEvent; //make the small square and color it dark grey var inArea:Sprite = new Sprite(); inArea.graphics.beginFill(0x333333); inArea.graphics.drawRect(0,0,100, 100); inArea.graphics.endFill(); addChild(inArea); //make the large square and color it black var outArea:Sprite = new Sprite(); outArea.graphics.beginFill(0x000000); outArea.graphics.drawRect(0,0,400,400); outArea.graphics.endFill(); outArea.graphics.lineStyle(1, 0xFFFFFF, 0.3); addChild(outArea); outArea.x = inArea.width; //adds a listener for the small square, that listens for mouse movement inArea.addEventListener(MouseEvent.MOUSE_MOVE, updateDrawing, false, 0, true); function updateDrawing(event:MouseEvent):void { //Map the local coordinates from the mouse movement to the size of the large square var targetX:int = map(event.localX, 0, event.target.width, 0, outArea.width); var targetY:int = map(event.localY, 0, event.target.height, 0, outArea.height); //Draws the line in the large square. outArea.graphics.lineTo(targetX, targetY); } //Helper function function map(val:Number, inMin:Number, inMax:Number, outMin:Number, outMax:Number, decimals:uint=0):Number { var returnVal:Number; // Sets the total range for both in and out var inRange:Number = inMax - inMin; var outRange:Number = outMax - outMin; //makes sure that the value is within range val = Math.max(inMin,val); val = Math.min(inMax,val); //calculates the ratio for the value in relation to the in range var ratio:Number = (val - inMin) / inRange; //Finds the same ratio in the out range and shift it into place returnVal = (outRange * ratio) + outMin; //rounding of the decimals var factor:int = Math.pow(10,decimals); returnVal = Math.round(returnVal*factor)/factor; return returnVal; }

