受控数字尺度映射

Controled number scale mapping

我需要将以度为单位的旋转角度刻度映射到从 0.0 到 0.9 的光强度刻度(旋转的太阳)。这是我正在使用的映射函数:

function map (num, in_min, in_max, out_min, out_max)
{
    return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

//(degree, degree in min, degree in max, light intensity out min, light intensity out max
var fade = map(30, 180, 360, 0.0, 0.9);

但是,淡入和淡出太慢,当光强度达到最大值时,只留下一小段时间。我需要更多地控制比例映射的完成方式 - 我该如何实现?

如前所述,您可以通过 Math.pow(x,<1) 实现初始快速变化和长时间的低变化。

要使其淡入然后再次淡出,您可以将值缩放 2,然后用该值减去 1 以上的部分。

function map(num, in_min, in_max, out_min, out_max, factor)
{
  var delta = Math.max(0,num-in_min)
  var scale = delta/(in_max-in_min)

  return Math.pow(Math.min(1,scale*2)-Math.max(0,scale*2-1),factor)
}

factor为1时是线性的。当它小于 1 时,它是多项式。

见图:

function map(num, in_min, in_max, out_min, out_max, factor)
{
  var delta = Math.max(0,num-in_min)
  var scale = delta/(in_max-in_min)
  
  return Math.pow(Math.min(1,scale*2)-Math.max(0,scale*2-1),factor)
}



// UI

var degrees_slider = document.getElementById('degrees')
var factor_slider = document.getElementById('factor')
var degrees_disp = document.getElementById('degrees_disp')
var factor_disp = document.getElementById('factor_disp')
var intensity_disp = document.getElementById('intensity_disp')

degrees_slider.oninput = factor_slider.oninput = update

function update(){
  var num = degrees_slider.value
  var fact = factor_slider.value
  
  degrees_disp.innerHTML = num
  factor_disp.innerHTML = fact
  intensity_disp.innerHTML = toPercent(map(num, 180, 360, 0.0, 0.9, fact))
  
}

function toPercent(val){
  return Math.round(val*100)+'%'
}

update()
#intensity_disp{
  font-size: 32pt;
  margin-top: 25px;
}
<label for="degrees">Degrees</label>
<br>
<input type="range" id="degrees" min="0" max="360" step="1"/>
<span id="degrees_disp"></span>

<br><br>

<label for="degrees">Linearity</label>
<br>
<input type="range" id="factor" min="0" max="1" step="0.01"/>
<span id="factor_disp"></span>

<div id="intensity_disp"></div>

如果您需要一个从一个数字上升到一个更高数字的比例(这就是我所要求的),上面@Manuel Otto 的回答是正确的。但是,我需要更大的灵活性,因为我在测试时临时调整我的太阳位置,我下面的最终函数也将 运行 从一个数字调整到一个较低的数字(因为它是度数,它被重置为 360 到0) - 例如 180 -> 60(180 到 360,然后 0 到 60 = 240 度):

//input degree, minimum degree possible, maximum degree possible, scale minimum, scale maximum, speed of scale fades (0.0 - 1.0 = fast to slow) 
function map(num, in_min, in_max, out_min, out_max, factor)
{
    //if input degree is greater than minimum degree possible
    if (num >= in_min)
    {
        //simple subtraction
        var delta = Math.max(0, num - in_min);
    } else {
        //subtract from 360 and add the input degree
        var delta = Math.max(0, ((360 - in_min) + num));
    }

    //if the maximum degree possible is greater than the minimum degree possible
    if (in_max >= in_min)
    {
        //simple subtraction
        var scale = delta / (in_max - in_min);
    } else {
        //subtract from 360 and add the maximum degree possible
        var scale = delta / ((360 - in_min) + in_max);
    }

    return Math.pow(Math.min(1, scale * 2) - Math.max(0, scale * 2 - 1), factor);
}

张贴在这里以防对其他人有用。