@js-basics/vector
Version:
A 3D Vector lib including arithmetic operator overloading (+ - * / % **).
182 lines (144 loc) • 3.31 kB
JavaScript
import { isArray, isNumber } from './utils/math.js';
import { cachedFunction, cachedMethod, cachedValueOf, defineVectorLength, operatorCalc } from './operator.js';
import { convertToCSSVars } from './utils/css.js';
const X = 0;
const Y = 1;
const Z = 2;
const W = 3;
const AXES = Symbol('axes');
class AColor {
constructor(x, y, z, w) {
if (typeof x === 'function') {
operatorCalc(x, (nx, ny, nz, nw) => {
this[AXES] = [nx, ny, nz, nw];
});
} else if (isArray(x)) {
this[AXES] = [...x];
} else if (x && isNumber(x.x)) {
this[AXES] = [x.x || 0, x.y || 0, x.z || 0, x.w || 0];
} else {
this[AXES] = [x || 0, y || 0, z || 0, w || 0];
}
}
dot(v) {
return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
}
valueOf() {
throw new Error('valueOf() not implemented, looks like you try to calculate outside of calc');
}
toArray() {
return [this.x, this.y, this.z, this.w];
}
// eslint-disable-next-line no-unused-vars
calc(alg) {
throw new Error('calc() not implemented');
}
clone() {
throw new Error('clone() not implemented');
}
equals(v) {
return this.x === v.x && this.y === v.y && this.z === v.z && this.w === v.w;
}
toJSON() {
return {
x: this.x,
y: this.y,
z: this.z,
w: this.w
};
}
toString() {
return JSON.stringify(this.toJSON());
}
toCSSVars(name, target) {
return convertToCSSVars(name, this.toJSON(), target);
}
get x() {
return this[AXES][X];
}
set x(_) {
throw new Error('set x() not implemented');
}
get y() {
return this[AXES][Y];
}
set y(_) {
throw new Error('set y() not implemented');
}
get z() {
return this[AXES][Z];
}
set z(_) {
throw new Error('set z() not implemented');
}
get w() {
return this[AXES][W];
}
set w(_) {
throw new Error('set w() not implemented');
}
[Symbol.iterator]() {
return this[AXES].values();
}
}
cachedValueOf(AColor);
defineVectorLength(AColor, 4);
cachedMethod(AColor, 'toArray');
export class Color extends AColor {
set x(x) {
this[AXES][X] = x;
}
set y(y) {
this[AXES][Y] = y;
}
set z(z) {
this[AXES][Z] = z;
}
set w(w) {
this[AXES][W] = w;
}
get x() {
return this[AXES][X];
}
get y() {
return this[AXES][Y];
}
get z() {
return this[AXES][Z];
}
get w() {
return this[AXES][W];
}
calc(alg) {
return operatorCalc(alg, this);
}
clone() {
return new Color(this.x, this.y);
}
}
export class IColor extends AColor {
toColor() {
return new Color(this.x, this.y, this.z, this.w);
}
}
export function calc(alg) {
return operatorCalc(alg);
}
const colorFactory = cachedFunction((x, y, z, w) => new Color(x, y, z, w));
/**
* @param {number | () => number} x
* @param {number} [y]
* @param {number} [z]
* @param {number} [w]
* @returns {Color & number}
*/
export const color = (x, y, z, w) => colorFactory(x, y, z, w);
const icolorFactory = cachedFunction((x, y, z, w) => new IColor(x, y, z, w));
/**
* @param {number | () => number} x
* @param {number} [y]
* @param {number} [z]
* @param {number} [w]
* @returns {IColor & number}
*/
export const icolor = (x, y, z, w) => icolorFactory(x, y, z, w);