个人开发的塔罗牌占卜小程序:【问问塔罗牌】 快来瞧瞧吧!
// @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);