Javascript / jQuery - map a range of numbers to another range of numbers

In other programming languages such as processing, there is a function which allows you to convert a number that falls within a range of numbers into a number within a different range. What I want to do is convert the mouse's X coordinate into a range between, say, 0 and 15. So the browser's window dimensions, while different for every user, might be, say, 1394px wide, and the current X coordinate might be 563px, and I want to convert that to the range of 0 to 15.

I'm hoping to find a function of jquery and javascript that has this ability built in. I can figure out the math to do this by myself, but I'd rather do this in a more concise and dynamic way.

I'm already capturing the screen dimensions and mouse dimensions with this code:

var $window = $(window);
var $document = $(document);


$document.ready(function() {
    var mouseX, mouseY; //capture current mouse coordinates
    var screenW, screenH; //capture the current width and height of the window
    var maxMove = 10;
    windowSize();

    $document.mousemove( function(e) {
        mouseX = e.pageX; 
        mouseY = e.pageY;

    });

    $window.resize(function() {
        windowSize();
    });

    function windowSize(){
        screenW = $window.width();
        screenH = $window.height();
    }

});

Thanks for any help you can provide.

Answers:

Answer

You can implement this as a pure Javascript function:

const scale = (num, in_min, in_max, out_min, out_max) => {
  return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Use the function, like this:

const num = 5;
console.log(scale(num, 0, 10, -50, 50)); // 0
console.log(scale(num, -20, 0, -100, 100)); // 150

I'm using scale for the function name, because map is frequently associated with iterating over arrays and objects.


Below is the original answer. I can no longer recommend modification of native prototypes.

If you'd like to have access to this in the Number class, you can add it as…

Number.prototype.map = function (in_min, in_max, out_min, out_max) {
  return (this - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

…wherein you specify in the "minimum" and "maximum" values of expected input and the "minimum" and "maximum" values to be output. This can and will produce out-of-range values if the incoming value itself is not between in_min and in_max.

Use it like this:

var num = 5;
console.log(num.map(0, 10, -50, 50)); // 0
console.log(num.map(-20, 0, -100, 100)); // 150

Edit: I've made this available as a Gist, so you don't have to look this up, in the future.

Answer

If your range always starts from 0 then all you have to do is

mouseValue * range.max / screen.max

A more involved any-range to any-range conversion would require

function convertToRange(value, srcRange, dstRange){
  // value is outside source range return
  if (value < srcRange[0] || value > srcRange[1]){
    return NaN; 
  }

  var srcMax = srcRange[1] - srcRange[0],
      dstMax = dstRange[1] - dstRange[0],
      adjValue = value - srcRange[0];

  return (adjValue * dstMax / srcMax) + dstRange[0];

}

Use like convertToRange(20,[10,50],[5,10]);

Answer

For a general purpose mapping function, which is what the OP asked for, go here:

http://rosettacode.org/wiki/Map_range#JavaScript

Answer
function proportion(value,max,minrange,maxrange) {
    return Math.round(((max-value)/(max))*(maxrange-minrange))+minrange;
}

In your case, use this as proportion(screencoord,screensize,0,15)

You'd also presumably want to get the Client size, not the screen size, as the Screen size refers to the maximum dimensions of the monitor, and not all users maximise their screen.

Answer

Let's say you have 6 variables :

  • minRange (0 in your example)
  • maxRange (15 in your example)
  • x
  • y
  • browserWidth
  • browserHeight

To have the range :

interval = maxRange - minRange;
rangeX = interval * x / browserWidth + minRange
rangeY = interval * y / browserHeight + minRange
Answer

This is simple math.

var screenWidth = $(window).width();
var mousePosition = e.pageX;
var max = 15;
var value = (mousePosition / screenWidth) * max;

Note that this can return a decimal number; if you don't want that, you can use Math.round on the result.

Live example

Answer

I've taken August Miller's idea and added limits to them (value can't go outside the range of in_min and in_max and if it does it returns out_min and out_max respectively) and minified it for those who want a copy paste function for their scripts:

function map(n,i,o,r,t){return i>o?i>n?(n-i)*(t-r)/(o-i)+r:r:o>i?o>n?(n-i)*(t-r)/(o-i)+r:t:void 0}

params are like map(value, in_min, in_max, out_in, out_max)

Answer

well its simple math. well you have two ranges range1 = [a1,a2] and range2 = [b1,b2] and you want to map a value s in range one to a value t in range two. so this is the formula. t = b1 + (s-a1)*(b2-b1)/(a2-a1) in js it will be.

var mapRange = function(from, to, s) {
  return to[0] + (s - from[0]) * (to[1] - to[0]) / (from[1] - from[0]);
};

var range = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (var i = 0; i < range.length; i++) {
  range[i] = mapRange([0, 10], [-1, 0], range[i]);
}

console.log(range);

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.