Niklas Grewe
Niklas Grewe

Reputation: 153

How can i calculate the range between multiple values?

I am using the following translateRange function to calculate the range between multiple factors like this:

function translateRange(
    input,
    inputMin,
    inputMax,
    outputMin,
    outputMax
) {
    let inputMinA = Math.min(inputMin, input);
    let inputMaxA = Math.max(inputMax, input);

    return (
        outputMin +
        ((outputMax - outputMin) * (input - inputMinA)) /
            (inputMaxA - inputMinA)
    );
};


let opacity = translateRange(
  scrollY, //input
  0, //animation start
  100, //animation end
  0, // from 0
  1 // to
);

This works best, but i want to pass multiple values to the function. For e.g. i want to pass xand y values for transform animations at the same time. How can i change the function to get this working? I would like to end with something like this:

let translate3d = translateRange(
   scrollY,
   0,
   100,
   [-10, -5], // x values (start and end)
   [-4, 1] // y values (start and end)
);

When you scroll, i want to get the calculated values like this:

-10, -4 // x and y start values

Upvotes: 0

Views: 434

Answers (2)

JasperZelf
JasperZelf

Reputation: 2844

I would not recommend doing thin in one single function. It gets quite messy keeping track of all the values.

A cleaner solution would be to calculate it separately for each input as done here:
https://jsfiddle.net/er0zyb4w/

If you want a single function that takes all the inputs: here you go:

(function() {
    document.onmousemove = handleMouseMove;
})();

//https://stackoverflow.com/questions/7790725/javascript-track-mouse-position
function handleMouseMove(event) {
  var eventDoc, doc, body;
  event = event || window.event;
  if (event.pageX == null && event.clientX != null) {
    eventDoc = (event.target && event.target.ownerDocument) || document;
    doc = eventDoc.documentElement;
    body = eventDoc.body;

    event.pageX = event.clientX +
      (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
      (doc && doc.clientLeft || body && body.clientLeft || 0);
    event.pageY = event.clientY +
      (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
      (doc && doc.clientTop  || body && body.clientTop  || 0 );
  }

  // Use event.pageX / event.pageY here
  [opacity, rotation] = translateRange(
    [event.pageX, event.pageY], //input
    [0,0], //animation start
    [500, 200], //animation end
    [1, 0], // from 
    [0, 90] // to
  );
  
  const el = document.getElementById("test");
  el.style.opacity = opacity;
  el.style.transform = `rotate(${rotation}deg)`;
}

function translateRange(
    inputs, // array of input values, x and y for example
    inputsMin, // array of animation start values
    inputsMax, // array of animation stop values
    outputsMin, // array of output min values
    outputsMax // array of output max values
) {
    return inputs.map((_, i)=>{
    let inputsMinA = Math.min(inputsMin[i], inputs[i]);
    let inputsMaxA = Math.max(inputsMax[i], inputs[i]);

    return (
        outputsMin[i] +
        ((outputsMax[i] - outputsMin[i]) * (inputs[i] - inputsMinA)) /
            (inputsMaxA - inputsMinA)
    );
  });
    
};
#test{
  position: fixed;
  top: 100px;
  left: 100px;
  width: 100px;
  height: 100px;
  background: red;
}
<div id="test"></div>
Move your mouse. <br/>
X - axis should change opacity 0 to 500px ==> opacity 1 to 0<br/> 
Y - axis should change rotation 0 to 200px ==> rotation 0 to 90 degrees

Upvotes: 1

Hao Wu
Hao Wu

Reputation: 20699

Why not reuse your function like this?

function translateRange(
    input,
    inputMin,
    inputMax,
    outputMin,
    outputMax
) {
    let inputMinA = Math.min(inputMin, input);
    let inputMaxA = Math.max(inputMax, input);

    return (
        outputMin +
        ((outputMax - outputMin) * (input - inputMinA)) /
            (inputMaxA - inputMinA)
    );
};

const translateArray = (input, inputMin, inputMax, outputMin, outputMax) => 
    outputMax.map((_, i) => translateRange(input[i] ?? input, inputMin[i] ?? inputMin, inputMax[i] ?? inputMax, outputMin[i] ?? outputMin, outputMax[i] ?? outputMax));

const translate3d_1 = translateArray([0, 50], [0, 0], [100, 100], [-10, -5], [-4, 1]);

const translate3d_2 = translateArray(50, 0, 100, [-10, -5], [-4, 1]);

console.log(translate3d_1);
console.log(translate3d_2);

Upvotes: 1

Related Questions