【问题标题】:Javascript / jQuery - map a range of numbers to another range of numbersJavascript / jQuery - 将一个数字范围映射到另一个数字范围
【发布时间】:2021-10-19 14:42:04
【问题描述】:

在其他编程语言(例如处理)中,有一个函数允许您将一个数字范围内的数字转换为不同范围内的数字。我想要做的是将鼠标的 X 坐标转换为介于 0 和 15 之间的范围。因此,浏览器的窗口尺寸虽然对每个用户都不同,但可能是 1394 像素宽,而当前的 X 坐标可能是 563 像素,我想将其转换为 0 到 15 的范围。

我希望找到一个 jquery 和 javascript 的函数,它内置了这个功能。我可以自己算出数学来做这件事,但我宁愿以更简洁和动态的方式来做。

我已经用这段代码捕获了屏幕尺寸和鼠标尺寸:

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();
    }

});

感谢您提供的任何帮助。

【问题讨论】:

  • 我不明白这个问题还是只是三规则?

标签: javascript jquery


【解决方案1】:

您可以将其实现为纯 Javascript 函数:

function scale (number, inMin, inMax, outMin, outMax) {
    return (number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}

使用函数,像这样:

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

我使用scale 作为函数名,因为map 经常与遍历数组和对象相关联。

【讨论】:

  • 分钟:Number.prototype.map=function(a,b,c,d){return c+(d-c)*((this-a)/(b-a))};
  • const map = (num, in_min, in_max, out_min, out_max) => (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min 应该包括在内以使用 ES6 语法.
【解决方案2】:

如果你的范围总是从 0 开始,那么你所要做的就是

mouseValue * range.max / screen.max

更复杂的任意范围到任意范围的转换需要

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];

}

convertToRange(20,[10,50],[5,10]);一样使用

【讨论】:

  • 太棒了! +1 但是“ if value ”应该返回最小值(dstRange[0])或最大值(dstRange[1])......
【解决方案3】:

对于 OP 要求的通用映射功能,请转到此处:

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

【讨论】:

  • 这很好,但需要underscore.js,这可能是OP的额外依赖,因为他提到只使用jQuery。
  • 是的 - 好地方。如果向上滚动,有一个更广泛的向后兼容解决方案:rosettacode.org/wiki/Map_range#JavaScript
【解决方案4】:

这是简单的数学运算。

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

注意,这可以返回一个十进制数;如果你不想这样,你可以在结果上使用Math.round

Live example

【讨论】:

    【解决方案5】:
    function proportion(value,max,minrange,maxrange) {
        return Math.round(((max-value)/(max))*(maxrange-minrange))+minrange;
    }
    

    在您的情况下,将其用作proportion(screencoord,screensize,0,15)

    您可能还想获得客户端尺寸,而不是屏幕尺寸,因为屏幕尺寸是指显示器的最大尺寸,并不是所有用户都最大化他们的屏幕。

    【讨论】:

      【解决方案6】:

      假设你有 6 个变量:

      • minRange(在您的示例中为 0)
      • maxRange(在您的示例中为 15)
      • x
      • 浏览器宽度
      • 浏览器高度

      要有范围:

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

      【讨论】:

        【解决方案7】:

        它的简单数学。 好吧,您有两个范围range1 = [a1,a2]range2 = [b1,b2],并且您想将范围一中的值s 映射到范围二中的值t。所以这是公式。 t = b1 + (s-a1)*(b2-b1)/(a2-a1) 在 js 中会这样。

        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);
        

        【讨论】:

          【解决方案8】:

          Floats 应始终计算。

          function scale(
              srcNum: number,
              src: [start: number, end: number],
              dst: [start: number, end: number]
          ): number {
              return ((srcNum - src[0]) * (dst[1] - dst[0])) / (src[1] - src[0]) + dst[0];
          }
          
          scale(1, [0, 10], [0, 255]);   // 25.5
          scale(1.5, [0, 10], [0, 255]); // 38.25
          scale(2, [0, 10], [0, 255]);   // 51
          

          Integers,一个有效的方法是创建一个映射,所以不需要更多的计算。但这实际上取决于src 范围的大小。对于大范围scale(...) 应该更有效。

          function createScale(
              src: [start: number, end: number],
              dst: [start: number, end: number]
          ): Record<number, number> {
              const map: Record<number, number> = {};
              for (let i = src[0]; i <= src[1]; i++) {
                  map[i] = ((i - src[0]) * (dst[1] - dst[0])) / (src[1] - src[0]) + dst[0];
              }
              return map;
          }
          
          createScale([0, 10], [0, 255]);
          // {
          //     "1": 25.5,
          //     "2": 51,
          //     "3": 76.5,
          //     "4": 102,
          //     "5": 127.5,
          //     "6": 153,
          //     "7": 178.5,
          //     "8": 204,
          //     "9": 229.5,
          //     "10": 255
          // }
          

          【讨论】:

            【解决方案9】:

            我采纳了 August Miller 的想法并对它们添加了限制(值不能超出 in_min 和 in_max 的范围,如果超出,则分别返回 out_min 和 out_max)并为那些想要复制粘贴功能的人缩小它对于他们的脚本:

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

            参数类似于 map(value, in_min, in_max, out_in, out_max)

            【讨论】:

            • 我喜欢这个,因为它不可读,但它似乎不尊重 in_min。如果我做 map(8, 10,20, 40,50) 它会导致“38”。 in_max 虽然有效。无论如何使用它。谢谢。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-03-03
            • 2021-10-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-03
            • 1970-01-01
            相关资源
            最近更新 更多