All files / src/features/tilt Tilt.ts

100% Statements 42/42
100% Branches 16/16
100% Functions 7/7
100% Lines 42/42

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75          14x           23x 23x 23x 23x   43x 43x 43x 43x 43x     43x 43x 43x   43x 43x 43x     43x 43x   43x 43x 35x 35x 35x 35x       43x 43x 43x 43x     43x 43x   43x 43x   43x 43x 4x 4x       47x 47x   47x 47x     8x 8x      
import { constrainToRange } from '@/utils/helperFns';
import type { ClientPosition } from '@/utils/types';
 
import type { TiltProps } from './types.public';
 
const TILT_ANGLE_CONSTRAINT = 90;
 
// All props are initialized by default with non-null values
/* eslint-disable @typescript-eslint/no-non-null-assertion */
 
export class Tilt {
  public tiltAngleX = 0;
  public tiltAngleY = 0;
  public tiltAngleXPercentage = 0;
  public tiltAngleYPercentage = 0;
 
  public update = (wrapperElClientPosition: ClientPosition, props: TiltProps): void => {
    this.updateTilt(wrapperElClientPosition, props);
    this.updateTiltManualInput(wrapperElClientPosition, props);
    this.updateTiltReverse(props);
    this.updateTiltLimits(props);
  };
 
  private updateTilt = (wrapperElClientPosition: ClientPosition, props: TiltProps): void => {
    const { xPercentage, yPercentage } = wrapperElClientPosition;
    const { tiltMaxAngleX, tiltMaxAngleY } = props;
 
    const tiltTowardMouse = -1;
    this.tiltAngleX = (xPercentage * tiltMaxAngleX!) / 100;
    this.tiltAngleY = ((yPercentage * tiltMaxAngleY!) / 100) * tiltTowardMouse;
  };
 
  private updateTiltManualInput = (wrapperElClientPosition: ClientPosition, props: TiltProps): void => {
    const { tiltAngleXManual, tiltAngleYManual, tiltMaxAngleX, tiltMaxAngleY } = props;
 
    const isManualInputIgnoreOtherInputs = tiltAngleXManual !== null || tiltAngleYManual !== null;
    if (isManualInputIgnoreOtherInputs) {
      this.tiltAngleX = tiltAngleXManual !== null ? tiltAngleXManual! : 0;
      this.tiltAngleY = tiltAngleYManual !== null ? tiltAngleYManual! : 0;
      wrapperElClientPosition.xPercentage = (100 * this.tiltAngleX) / tiltMaxAngleX!;
      wrapperElClientPosition.yPercentage = (100 * this.tiltAngleY) / tiltMaxAngleY!;
    }
  };
 
  private updateTiltReverse = (props: TiltProps): void => {
    const tiltReverse = props.tiltReverse ? -1 : 1;
    this.tiltAngleX = tiltReverse * this.tiltAngleX;
    this.tiltAngleY = tiltReverse * this.tiltAngleY;
  };
 
  private updateTiltLimits = (props: TiltProps): void => {
    const { tiltAxis } = props;
 
    this.tiltAngleX = constrainToRange(this.tiltAngleX, -TILT_ANGLE_CONSTRAINT, TILT_ANGLE_CONSTRAINT);
    this.tiltAngleY = constrainToRange(this.tiltAngleY, -TILT_ANGLE_CONSTRAINT, TILT_ANGLE_CONSTRAINT);
 
    const isOnlyOneAxisEnabledForTilting = tiltAxis;
    if (isOnlyOneAxisEnabledForTilting) {
      this.tiltAngleX = tiltAxis === 'x' ? this.tiltAngleX : 0;
      this.tiltAngleY = tiltAxis === 'y' ? this.tiltAngleY : 0;
    }
  };
 
  public updateTiltAnglesPercentage = (props: TiltProps): void => {
    const { tiltMaxAngleX, tiltMaxAngleY } = props;
 
    this.tiltAngleXPercentage = (this.tiltAngleX / tiltMaxAngleX!) * 100;
    this.tiltAngleYPercentage = (this.tiltAngleY / tiltMaxAngleY!) * 100;
  };
 
  public render = (element: HTMLDivElement): void => {
    element.style.transform += `rotateX(${this.tiltAngleX}deg) rotateY(${this.tiltAngleY}deg) `;
  };
}