Función de potencia | Programar Plus

Si bien es muy útil con la aritmética, Sass se queda un poco corto con las funciones de ayuda matemática. Ha habido un problema abierto en el repositorio oficial para solicitar más funciones relacionadas con las matemáticas durante casi 3 años.

Algunos proveedores externos como Compass o SassyMath brindan soporte avanzado para funciones matemáticas, pero son dependencias externas que podrían (¿deberían?) Evitarse.

Una de las solicitudes más populares sobre este tema es una función de potencia o incluso un operador exponente. Desafortunadamente, todavía no hay apoyo para esto en Sass y, aunque todavía se está debatiendo activamente, es poco probable que suceda muy pronto.

Mientras tanto, ser capaz de elevar un número a una determinada potencia resulta muy útil en CSS. Aquí hay algunos ejemplos en los que sería útil:

  • para determinar la luminancia de un color;
  • para fijar un número a una cierta cantidad de dígitos;
  • hacer algo de trigonometría (inversa) …

Implementación de Sass

Afortunadamente para nosotros, es posible (y bastante simple) crear una función de potencia con nada más que Sass. Todo lo que necesitamos es un bucle y algunos operadores matemáticos básicos (como * y /).

Exponentes enteros positivos

Nuestra función (llamada pow) en su forma más pequeña se vería así:

@function pow($number, $exponent) {
  $value: 1;

  @if $exponent > 0 {
    @for $i from 1 through $exponent {
      $value: $value * $number;
    }
  }

  @return $value;
}

Aquí hay un ejemplo:

.foo {
  width: pow(20, 2) * 1px; // 400px
}

Exponentes enteros positivos o negativos

Sin embargo, solo funciona con un argumento positivo “$ power”. Permitir exponentes negativos no sería tan difícil, solo necesitamos una pequeña condición adicional:

@function pow($number, $exponent) {
  $value: 1;

  @if $exponent > 0 {
    @for $i from 1 through $exponent {
      $value: $value * $number;
    }
  } @else if $exponent < 0 {
    @for $i from 1 through -$exponent {
      $value: $value / $number;
    }
  }

  @return $value;
}

Aquí hay un ejemplo:

.foo {
  width: pow(10, -2) * 1px; // 0.0001px
}

Exponentes positivos o negativos

Ahora, ¿qué pasa si queremos exponentes no enteros? Tal como 4.2 ¿por ejemplo? La verdad es que la verdad es que no es nada fácil. Todavía es factible, pero requiere algo más que un bucle y algunas operaciones.

Esto se ha hecho en el repositorio de Bourbon con el fin de completar el modular-scale(..) función del marco (aunque se ha rechazado). Aquí está el código:

@function pow($number, $exponent) {
  @if (round($exponent) != $exponent) {
    @return exp($exponent * ln($number));
  }
    
  $value: 1;
  
  @if $exponent > 0 {
    @for $i from 1 through $exponent {
     $value: $value * $number;
    }
  } @else if $exponent < 0 {
    @for $i from 1 through -$exponent {
      $value: $value / $number;
    }
  }

  @return $value;
}

@function factorial($value) {
  $result: 1;

  @if $value == 0 {
    @return $result;
  }
  
  @for $index from 1 through $value {
    $result: $result * $index;
  }
  
  @return $result;
}

@function summation($iteratee, $input, $initial: 0, $limit: 100) {
  $sum: 0;
  
  @for $index from $initial to $limit {
    $sum: $sum + call($iteratee, $input, $index);
  }
  
  @return $sum;
}

@function exp-maclaurin($x, $n) {
  @return (pow($x, $n) / factorial($n));
}

@function exp($value) {
  @return summation('exp-maclaurin', $value, 0, 100);
}

@function ln-maclaurin($x, $n) {
  @return (pow(-1, $n + 1) / $n) * (pow($x - 1, $n));
}

@function ln($value) {
  $ten-exp: 1;
  $ln-ten: 2.30258509;
  
  @while ($value > pow(10, $ten-exp)) {
    $ten-exp: $ten-exp + 1;
  }
  
  @return summation(ln-maclaurin, $value / pow(10, $ten-exp), 1, 100) + $ten-exp * $ln-ten;
}

Consideraciones adicionales

Bueno, eso fue intenso. Si necesita soporte para exponentes no enteros (como 4.2), Te recomiendo que uses una dependencia externa que la proporcione (como sass-math-pow) en lugar de incluir todo este código en tu proyecto. No es que sea algo malo en sí mismo, pero no es realmente el papel de su proyecto albergar una cantidad tan grande de código de relleno múltiple sin autor (por eso tenemos administradores de paquetes).

También tenga en cuenta que todas estas operaciones son bastante intensivas para una capa tan delgada como Sass. En este punto, y si su diseño se basa en funciones matemáticas avanzadas, probablemente sea mejor pasar la implementación de estos ayudantes desde la capa superior (Node.js, Ruby, etc.) a Sass a través de un sistema de complementos (Eyeglass, Ruby gema, etc.).

Pero para lo básico pow(..) uso, no puedo recomendar las versiones simples lo suficiente!

(Visited 3 times, 1 visits today)