用于创建颜色相关的方法,例如可以把 rgb 值转换成 十六进制颜色

 个人开发的塔罗牌占卜小程序:【问问塔罗牌】 快来瞧瞧吧!

// @ts-nocheck
import { math } from '@/utils/math';

/**
 * @class
 * @name Color
 * @classdesc Representation of an RGBA color.
 * @description 用于创建颜色相关的方法,例如可以把 rgb 值转换成 十六进制颜色
 * @param {number|number[]} [r] - The value of the red component (0-1). If r is an array of length 3 or 4, the array will be used to populate all components.
 * @param {number} [g] - The value of the green component (0-1).
 * @param {number} [b] - The value of the blue component (0-1).
 * @param {number} [a] - The value of the alpha component (0-1).
 * @property {number} r The red component of the color.
 * @property {number} g The green component of the color.
 * @property {number} b The blue component of the color.
 * @property {number} a The alpha component of the color.
 */
class Color {
  r = '';
  g = '';
  b = '';
  a = '';

  constructor(r: string, g: string, b: string, a?: string) {
    const length = r.length;
    if (length === 3 || length === 4) {
      this.r = r[0];
      this.g = r[1];
      this.b = r[2];
      this.a = r[3] !== undefined ? r[3] : '1';
    } else {
      this.r = r;
      this.g = g;
      this.b = b;
      this.a = a;
    }
  }

  /**
   * @function
   * @name Color#clone
   * @description Returns a clone of the specified color.
   * @returns {Color} A duplicate color object.
   */
  clone() {
    return new Color(this.r, this.g, this.b, this.a);
  }

  /**
   * @function
   * @name Color#copy
   * @description Copies the contents of a source color to a destination color.
   * @param {Color} rhs - A color to copy to the specified color.
   * @returns {Color} Self for chaining.
   * @example
   * var src = new pc.Color(1, 0, 0, 1);
   * var dst = new pc.Color();
   *
   * dst.copy(src);
   *
   * console.log("The two colors are " + (dst.equals(src) ? "equal" : "different"));
   */
  copy(rhs) {
    this.r = rhs.r;
    this.g = rhs.g;
    this.b = rhs.b;
    this.a = rhs.a;

    return this;
  }

  /**
   * @function
   * @name Color#equals
   * @description Reports whether two colors are equal.
   * @param {Color} rhs - The color to compare to the specified color.
   * @returns {boolean} True if the colors are equal and false otherwise.
   * @example
   * var a = new pc.Color(1, 0, 0, 1);
   * var b = new pc.Color(1, 1, 0, 1);
   * console.log("The two colors are " + (a.equals(b) ? "equal" : "different"));
   */
  equals(rhs) {
    return this.r === rhs.r && this.g === rhs.g && this.b === rhs.b && this.a === rhs.a;
  }

  /**
   * @function
   * @name Color#set
   * @description Assign values to the color components, including alpha.
   * @param {number} r - The value for red (0-1).
   * @param {number} g - The value for blue (0-1).
   * @param {number} b - The value for green (0-1).
   * @param {number} [a] - The value for the alpha (0-1), defaults to 1.
   * @returns {Color} Self for chaining.
   */
  set(r, g, b, a = 1) {
    this.r = r;
    this.g = g;
    this.b = b;
    this.a = a;

    return this;
  }

  /**
   * @function
   * @name Color#lerp
   * @description Returns the result of a linear interpolation between two specified colors.
   * @param {Color} lhs - The color to interpolate from.
   * @param {Color} rhs - The color to interpolate to.
   * @param {number} alpha - The value controlling the point of interpolation. Between 0 and 1, the linear interpolant
   * will occur on a straight line between lhs and rhs. Outside of this range, the linear interpolant will occur on
   * a ray extrapolated from this line.
   * @returns {Color} Self for chaining.
   * @example
   * var a = new pc.Color(0, 0, 0);
   * var b = new pc.Color(1, 1, 0.5);
   * var r = new pc.Color();
   *
   * r.lerp(a, b, 0);   // r is equal to a
   * r.lerp(a, b, 0.5); // r is 0.5, 0.5, 0.25
   * r.lerp(a, b, 1);   // r is equal to b
   */
  lerp(lhs, rhs, alpha) {
    this.r = lhs.r + alpha * (rhs.r - lhs.r);
    this.g = lhs.g + alpha * (rhs.g - lhs.g);
    this.b = lhs.b + alpha * (rhs.b - lhs.b);
    this.a = lhs.a + alpha * (rhs.a - lhs.a);

    return this;
  }

  /**
   * @function
   * @name Color#fromString
   * @description Set the values of the color from a string representation '#11223344' or '#112233'.
   * @param {string} hex - A string representation in the format '#RRGGBBAA' or '#RRGGBB'. Where RR, GG, BB, AA are red, green, blue and alpha values.
   * This is the same format used in HTML/CSS.
   * @returns {Color} Self for chaining.
   */
  fromString(hex) {
    const i = parseInt(hex.replace('#', '0x'), 16);
    let bytes;
    if (hex.length > 7) {
      bytes = math.intToBytes32(i);
    } else {
      bytes = math.intToBytes24(i);
      bytes[3] = 255;
    }

    this.set(bytes[0] / 255, bytes[1] / 255, bytes[2] / 255, bytes[3] / 255);

    return this;
  }

  /**
   * @function
   * @name Color#toString
   * @description Converts the color to string form. The format is '#RRGGBBAA', where
   * RR, GG, BB, AA are the red, green, blue and alpha values. When the alpha value is not
   * included (the default), this is the same format as used in HTML/CSS.
   * @param {boolean} alpha - If true, the output string will include the alpha value.
   * @returns {string} The color in string form.
   * @example
   * var c = new pc.Color(1, 1, 1);
   * // Outputs #ffffffff
   * console.log(c.toString());
   */
  toString(alpha) {
    let s =
      '#' +
      (
        (1 << 24) +
        (Math.round(this.r * 255) << 16) +
        (Math.round(this.g * 255) << 8) +
        Math.round(this.b * 255)
      )
        .toString(16)
        .slice(1);
    if (alpha === true) {
      const a = Math.round(this.a * 255).toString(16);
      if (this.a < 16 / 255) {
        s += '0' + a;
      } else {
        s += a;
      }
    }

    return s;
  }

  /**
   * @field
   * @static
   * @readonly
   * @name Color.BLACK
   * @type {Color}
   * @description A constant color set to black [0, 0, 0, 1].
   */
  static BLACK = Object.freeze(new Color(0, 0, 0, 1));

  /**
   * @field
   * @static
   * @readonly
   * @name Color.BLUE
   * @type {Color}
   * @description A constant color set to blue [0, 0, 1, 1].
   */
  static BLUE = Object.freeze(new Color(0, 0, 1, 1));

  /**
   * @field
   * @static
   * @readonly
   * @name Color.CYAN
   * @type {Color}
   * @description A constant color set to cyan [0, 1, 1, 1].
   */
  static CYAN = Object.freeze(new Color(0, 1, 1, 1));

  /**
   * @field
   * @static
   * @readonly
   * @name Color.GRAY
   * @type {Color}
   * @description A constant color set to gray [0.5, 0.5, 0.5, 1].
   */
  static GRAY = Object.freeze(new Color(0.5, 0.5, 0.5, 1));

  /**
   * @field
   * @static
   * @readonly
   * @name Color.GREEN
   * @type {Color}
   * @description A constant color set to green [0, 1, 0, 1].
   */
  static GREEN = Object.freeze(new Color(0, 1, 0, 1));

  /**
   * @field
   * @static
   * @readonly
   * @name Color.MAGENTA
   * @type {Color}
   * @description A constant color set to magenta [1, 0, 1, 1].
   */
  static MAGENTA = Object.freeze(new Color(1, 0, 1, 1));

  /**
   * @field
   * @static
   * @readonly
   * @name Color.RED
   * @type {Color}
   * @description A constant color set to red [1, 0, 0, 1].
   */
  static RED = Object.freeze(new Color(1, 0, 0, 1));

  /**
   * @field
   * @static
   * @readonly
   * @name Color.WHITE
   * @type {Color}
   * @description A constant color set to white [1, 1, 1, 1].
   */
  static WHITE = Object.freeze(new Color(1, 1, 1, 1));

  /**
   * @field
   * @static
   * @readonly
   * @name Color.YELLOW
   * @type {Color}
   * @description A constant color set to yellow [1, 1, 0, 1].
   */
  static YELLOW = Object.freeze(new Color(1, 1, 0, 1));
}

export { Color };

 

// @ts-nocheck

/**
 * @name math
 * @namespace
 * @description Math API.
 */
const math = {
  /**
   * @constant
   * @type {number}
   * @name math.DEG_TO_RAD
   * @description Conversion factor between degrees and radians.
   * @example
   * // Convert 180 degrees to pi radians
   * var rad = 180 * pc.math.DEG_TO_RAD;
   */
  DEG_TO_RAD: Math.PI / 180,

  /**
   * @constant
   * @type {number}
   * @name math.RAD_TO_DEG
   * @description Conversion factor between degrees and radians.
   * @example
   * // Convert pi radians to 180 degrees
   * var deg = Math.PI * pc.math.RAD_TO_DEG;
   */
  RAD_TO_DEG: 180 / Math.PI,

  /**
   * @function
   * @name math.clamp
   * @description Clamp a number between min and max inclusive.
   * @param {number} value - Number to clamp.
   * @param {number} min - Min value.
   * @param {number} max - Max value.
   * @returns {number} The clamped value.
   */
  clamp: function (value, min, max) {
    if (value >= max) return max;
    if (value <= min) return min;
    return value;
  },

  /**
   * @function
   * @name math.intToBytes24
   * @description Convert an 24 bit integer into an array of 3 bytes.
   * @param {number} i - Number holding an integer value.
   * @returns {number[]} An array of 3 bytes.
   * @example
   * // Set bytes to [0x11, 0x22, 0x33]
   * var bytes = pc.math.intToBytes24(0x112233);
   */
  intToBytes24: function (i) {
    const r = (i >> 16) & 0xff;
    const g = (i >> 8) & 0xff;
    const b = i & 0xff;

    return [r, g, b];
  },

  /**
   * @function
   * @name math.intToBytes32
   * @description Convert an 32 bit integer into an array of 4 bytes.
   * @returns {number[]} An array of 4 bytes.
   * @param {number} i - Number holding an integer value.
   * @example
   * // Set bytes to [0x11, 0x22, 0x33, 0x44]
   * var bytes = pc.math.intToBytes32(0x11223344);
   */
  intToBytes32: function (i) {
    const r = (i >> 24) & 0xff;
    const g = (i >> 16) & 0xff;
    const b = (i >> 8) & 0xff;
    const a = i & 0xff;

    return [r, g, b, a];
  },

  /**
   * @function
   * @name math.bytesToInt24
   * @description Convert 3 8 bit Numbers into a single unsigned 24 bit Number.
   * @example
   * // Set result1 to 0x112233 from an array of 3 values
   * var result1 = pc.math.bytesToInt24([0x11, 0x22, 0x33]);
   *
   * // Set result2 to 0x112233 from 3 discrete values
   * var result2 = pc.math.bytesToInt24(0x11, 0x22, 0x33);
   * @param {number} r - A single byte (0-255).
   * @param {number} g - A single byte (0-255).
   * @param {number} b - A single byte (0-255).
   * @returns {number} A single unsigned 24 bit Number.
   */
  bytesToInt24: function (r, g, b) {
    if (r.length) {
      b = r[2];
      g = r[1];
      r = r[0];
    }
    return (r << 16) | (g << 8) | b;
  },

  /**
   * @function
   * @name math.bytesToInt32
   * @description Convert 4 1-byte Numbers into a single unsigned 32bit Number.
   * @returns {number} A single unsigned 32bit Number.
   * @example
   * // Set result1 to 0x11223344 from an array of 4 values
   * var result1 = pc.math.bytesToInt32([0x11, 0x22, 0x33, 0x44]);
   *
   * // Set result2 to 0x11223344 from 4 discrete values
   * var result2 = pc.math.bytesToInt32(0x11, 0x22, 0x33, 0x44);
   * @param {number} r - A single byte (0-255).
   * @param {number} g - A single byte (0-255).
   * @param {number} b - A single byte (0-255).
   * @param {number} a - A single byte (0-255).
   */
  bytesToInt32: function (r, g, b, a) {
    if (r.length) {
      a = r[3];
      b = r[2];
      g = r[1];
      r = r[0];
    }
    // Why ((r << 24)>>>32)?
    // << operator uses signed 32 bit numbers, so 128<<24 is negative.
    // >>> used unsigned so >>>32 converts back to an unsigned.
    // See http://stackoverflow.com/questions/1908492/unsigned-integer-in-javascript
    return ((r << 24) | (g << 16) | (b << 8) | a) >>> 32;
  },

  /**
   * @function
   * @name math.lerp
   * @returns {number} The linear interpolation of two numbers.
   * @description Calculates the linear interpolation of two numbers.
   * @param {number} a - Number to linearly interpolate from.
   * @param {number} b - Number to linearly interpolate to.
   * @param {number} alpha - The value controlling the result of interpolation. When alpha is 0,
   * a is returned. When alpha is 1, b is returned. Between 0 and 1, a linear interpolation between
   * a and b is returned. alpha is clamped between 0 and 1.
   */
  lerp: function (a, b, alpha) {
    return a + (b - a) * math.clamp(alpha, 0, 1);
  },

  /**
   * @function
   * @name math.lerpAngle
   * @description Calculates the linear interpolation of two angles ensuring that interpolation
   * is correctly performed across the 360 to 0 degree boundary. Angles are supplied in degrees.
   * @returns {number} The linear interpolation of two angles.
   * @param {number} a - Angle (in degrees) to linearly interpolate from.
   * @param {number} b - Angle (in degrees) to linearly interpolate to.
   * @param {number} alpha - The value controlling the result of interpolation. When alpha is 0,
   * a is returned. When alpha is 1, b is returned. Between 0 and 1, a linear interpolation between
   * a and b is returned. alpha is clamped between 0 and 1.
   */
  lerpAngle: function (a, b, alpha) {
    if (b - a > 180) {
      b -= 360;
    }
    if (b - a < -180) {
      b += 360;
    }
    return math.lerp(a, b, math.clamp(alpha, 0, 1));
  },

  /**
   * @function
   * @name math.powerOfTwo
   * @description Returns true if argument is a power-of-two and false otherwise.
   * @param {number} x - Number to check for power-of-two property.
   * @returns {boolean} true if power-of-two and false otherwise.
   */
  powerOfTwo: function (x) {
    return x !== 0 && !(x & (x - 1));
  },

  /**
   * @function
   * @name math.nextPowerOfTwo
   * @description Returns the next power of 2 for the specified value.
   * @param {number} val - The value for which to calculate the next power of 2.
   * @returns {number} The next power of 2.
   */
  nextPowerOfTwo: function (val) {
    val--;
    val |= val >> 1;
    val |= val >> 2;
    val |= val >> 4;
    val |= val >> 8;
    val |= val >> 16;
    val++;
    return val;
  },

  /**
   * @function
   * @name math.random
   * @description Return a pseudo-random number between min and max.
   * The number generated is in the range [min, max), that is inclusive of the minimum but exclusive of the maximum.
   * @param {number} min - Lower bound for range.
   * @param {number} max - Upper bound for range.
   * @returns {number} Pseudo-random number between the supplied range.
   */
  random: function (min, max) {
    const diff = max - min;
    return Math.random() * diff + min;
  },

  /**
   * @function
   * @name math.smoothstep
   * @description The function interpolates smoothly between two input values based on
   * a third one that should be between the first two. The returned value is clamped
   * between 0 and 1.
   * <br/>The slope (i.e. derivative) of the smoothstep function starts at 0 and ends at 0.
   * This makes it easy to create a sequence of transitions using smoothstep to interpolate
   * each segment rather than using a more sophisticated or expensive interpolation technique.
   * <br/>See http://en.wikipedia.org/wiki/Smoothstep for more details.
   * @param {number} min - The lower bound of the interpolation range.
   * @param {number} max - The upper bound of the interpolation range.
   * @param {number} x - The value to interpolate.
   * @returns {number} The smoothly interpolated value clamped between zero and one.
   */
  smoothstep: function (min, max, x) {
    if (x <= min) return 0;
    if (x >= max) return 1;

    x = (x - min) / (max - min);

    return x * x * (3 - 2 * x);
  },

  /**
   * @function
   * @name math.smootherstep
   * @description An improved version of the {@link math.smoothstep} function which has zero
   * 1st and 2nd order derivatives at t=0 and t=1.
   * <br/>See http://en.wikipedia.org/wiki/Smoothstep for more details.
   * @param {number} min - The lower bound of the interpolation range.
   * @param {number} max - The upper bound of the interpolation range.
   * @param {number} x - The value to interpolate.
   * @returns {number} The smoothly interpolated value clamped between zero and one.
   */
  smootherstep: function (min, max, x) {
    if (x <= min) return 0;
    if (x >= max) return 1;

    x = (x - min) / (max - min);

    return x * x * x * (x * (x * 6 - 15) + 10);
  },

  /**
   * @function
   * @name math.roundUp
   * @description Rounds a number up to nearest multiple.
   * @param {number} numToRound - The number to round up.
   * @param {number} multiple - The multiple to round up to.
   * @returns {number} A number rounded up to nearest multiple.
   */
  roundUp: function (numToRound, multiple) {
    if (multiple === 0) return numToRound;
    return Math.ceil(numToRound / multiple) * multiple;
  },

  /**
   * @function
   * @name math.float2Half
   * @description Converts float number to half float representation.
   * @param {number} val - The float number.
   * @returns {number} A 16 bit number representing half float representation as used by GPU.
   */
  float2Half: (function () {
    // based on based on https://esdiscuss.org/topic/float16array
    const floatView = new Float32Array(1);
    const int32View = new Int32Array(floatView.buffer);

    // This method is faster than the OpenEXR implementation (very often
    // used, eg. in Ogre), with the additional benefit of rounding, inspired
    // by James Tursa?s half-precision code.
    return function (val) {
      floatView[0] = val;
      const x = int32View[0];

      let bits = (x >> 16) & 0x8000; // Get the sign
      let m = (x >> 12) & 0x07ff; // Keep one extra bit for rounding
      const e = (x >> 23) & 0xff; // Using int is faster here

      // If zero, or denormal, or exponent underflows too much for a denormal half, return signed zero.
      if (e < 103) {
        return bits;
      }

      // If NaN, return NaN. If Inf or exponent overflow, return Inf.
      if (e > 142) {
        bits |= 0x7c00;

        // If exponent was 0xff and one mantissa bit was set, it means NaN,
        // not Inf, so make sure we set one mantissa bit too.
        bits |= (e === 255 ? 0 : 1) && x & 0x007fffff;
        return bits;
      }

      // If exponent underflows but not too much, return a denormal
      if (e < 113) {
        m |= 0x0800;

        // Extra rounding may overflow and set mantissa to 0 and exponent to 1, which is OK.
        bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1);
        return bits;
      }

      bits |= ((e - 112) << 10) | (m >> 1);

      // Extra rounding. An overflow will set mantissa to 0 and increment the exponent, which is OK.
      bits += m & 1;
      return bits;
    };
  })(),

  /**
   * @function
   * @private
   * @name math.between
   * @description Checks whether a given number resides between two other given numbers.
   * @param {number} num - The number to check the position of.
   * @param {number} a - The first upper or lower threshold to check between.
   * @param {number} b - The second upper or lower threshold to check between.
   * @param {boolean} inclusive - If true, a num param which is equal to a or b will return true.
   * @returns {boolean} true if between or false otherwise.
   */
  between: function (num, a, b, inclusive) {
    const min = Math.min(a, b);
    const max = Math.max(a, b);
    return inclusive ? num >= min && num <= max : num > min && num < max;
  },
};

export { math };

调用

new Color(

r,g,b

).toString(false);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值