First time I saw the map() function was in the Processing language reference. So simple and so useful. And what does it do? From the Processing page:

– Re-maps a number from one range to another.

Best way to understand is with an example (always):

map(num, min1, max1, min2, max2)
 
map(20, 0, 100, 0, 400) // outputs 80

In other words, it gets a number (20), finds its percentage within the first range (0 – 100) which results to 0.2 and maps it to the second range (0 – 400) which results to 80. In this example it is the same as finding 20% of 400, which is easy enough, we don’t need a function for it.

Now another example:

map(1152, 1000, 1440, 130, 230) // outputs 164.54

That’s a bit harder to calculate. The percentage of 1152 within the range 1000 – 1440 is 0.3454… And that mapped to the range 130 – 230 results in 164.5454…
I’ve came to hundreds of situations where I need to map a value from one range to another. The most frequent one is to position or scale objects according to the stage size.

Let’s take a look at the previous example again:

map(1152, 1000, 1440, 130, 230)
 
num  = 1152 // current stageWidth
min1 = 1000 // minimum supported stage width
max1 = 1440 // maximum supported stage width
min2 = 130  // x position of an object in the minimum width layout
max2 = 230  // x position of an object in the maximum width layout

If the user is viewing your Flash in a small screen resolution and the stageWidth is 1000, object is positioned at x 130. If your user has a big screen and the stageWidth is 1440, object is repositioned to x 230. And every screen size in between will make object.x change proportionally.

Click the image below for an example of resize / reposition:

Resize Example

 

I guess the best place to put a map() function is in a MathUtils static class. That’s what I did. I have also added round, constrainMin and constrainMax parameters that are also very useful.

public static function map(num:Number, min1:Number, max1:Number, min2:Number, max2:Number, round:Boolean = false, constrainMin:Boolean = true, constrainMax:Boolean = true):Number
{
	if (constrainMin && num < min1) return min2;
	if (constrainMax && num > max1) return max2;
 
	var num1:Number = (num - min1) / (max1 - min1);
	var num2:Number = (num1 * (max2 - min2)) + min2;
	if (round) return Math.round(num2);
	return num2;
}

 

LINKS
Example
MathUtils.as

 


One Comment on “MathUtils.map()”

You can track this conversation through its atom feed.

  1. Vincent says:

    A more elegant solution with lesser code, which also doesn’t constrain values thus truly maps values, would be

    function map ( v : Number, a : Number, b : Number, x : Number, y : Number ) : Number
    {
    return (v / (b – a)) * (y – x);
    }

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>