@fbltd/math 1.0.40 → 1.0.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ import { Color } from "./color.js";
2
+ /**
3
+ * Смешение цветов
4
+ */
5
+ export function blend(background, ...foregrounds) {
6
+ let temp;
7
+ let red, green, blue;
8
+ for (let foreground of foregrounds) {
9
+ const fgAlpha = foreground.alpha;
10
+ const bgAlpha = background.alpha;
11
+ let alpha = 1 - (1 - fgAlpha) * (1 - bgAlpha);
12
+ if (alpha <= 0) {
13
+ background = new Color(0, 0, 0, 0);
14
+ continue;
15
+ }
16
+ temp = bgAlpha * (1 - fgAlpha) / alpha;
17
+ red = Math.floor(foreground.red * fgAlpha / alpha + background.red * temp);
18
+ green = Math.floor(foreground.green * fgAlpha / alpha + background.green * temp);
19
+ blue = Math.floor(foreground.blue * fgAlpha / alpha + background.blue * temp);
20
+ background = new Color(red, green, blue, alpha);
21
+ }
22
+ return background;
23
+ }
@@ -5,7 +5,7 @@ export class Color {
5
5
  _green;
6
6
  _blue;
7
7
  _alpha;
8
- constructor(_red, _green, _blue, _alpha = 255) {
8
+ constructor(_red, _green, _blue, _alpha = 1) {
9
9
  this._red = _red;
10
10
  this._green = _green;
11
11
  this._blue = _blue;
@@ -0,0 +1,6 @@
1
+ import { Color } from "./color.js";
2
+ export const COLORS = {
3
+ WHITE: new Color(255, 255, 255, 1),
4
+ BLACK: new Color(0, 0, 0, 1),
5
+ TRANSPARENT: new Color(0, 0, 0, 0),
6
+ };
@@ -1,87 +1,69 @@
1
- import { Color } from "./color.js";
2
- export class ConicGradient {
1
+ import { Color } from "../color.js";
2
+ import { denormalizeShade } from "../utils.js";
3
+ export class BaseGradient {
3
4
  colors;
4
5
  constructor(...colors) {
5
- this.colors = [...colors].sort((a, b) => a.angle - b.angle);
6
+ this.colors = [...colors].sort((a, b) => a.percentage - b.percentage);
6
7
  this.colors.push({
7
- angle: 1,
8
+ percentage: 1,
8
9
  color: this.colors[0].color
9
10
  });
10
11
  }
11
12
  /**
12
13
  * Получить цвет по углу от оси X по часовой стрелке
13
- * @param angle единица измерения угла должна быть той же самой, что и углы всех передаваемых в констурктор цветов
14
+ * @param percentage единица измерения угла должна быть той же самой, что и углы всех передаваемых в констурктор цветов
14
15
  */
15
- getColorAtAngle(angle) {
16
+ getColorAtPercentage(percentage) {
16
17
  let prev = undefined;
17
18
  let next = undefined;
18
19
  for (let entry of this.colors) {
19
- if (entry.angle === angle)
20
+ if (entry.percentage === percentage)
20
21
  return entry.color;
21
- if (entry.angle < angle)
22
+ if (entry.percentage < percentage)
22
23
  prev = entry;
23
- if (entry.angle > angle) {
24
+ if (entry.percentage > percentage) {
24
25
  next = entry;
25
26
  break;
26
27
  }
27
28
  }
28
29
  if (!prev || !next)
29
30
  return undefined;
30
- const coef = (angle - prev.angle) / (next.angle - prev.angle);
31
- return new Color(Math.floor((next.color.red - prev.color.red) * coef + prev.color.red), Math.floor((next.color.green - prev.color.green) * coef + prev.color.green), Math.floor((next.color.blue - prev.color.blue) * coef + prev.color.blue));
31
+ const coef = (percentage - prev.percentage) / (next.percentage - prev.percentage);
32
+ return new Color(Math.floor((next.color.red - prev.color.red) * coef + prev.color.red), Math.floor((next.color.green - prev.color.green) * coef + prev.color.green), Math.floor((next.color.blue - prev.color.blue) * coef + prev.color.blue), (next.color.alpha - prev.color.alpha) * coef + prev.color.alpha);
32
33
  }
33
- getAngleByColor(color) {
34
+ getPercentageByColor(color) {
34
35
  let prev;
35
36
  let next = this.colors[0];
36
37
  if (color.isEqual(next.color))
37
- return next.angle;
38
+ return next.percentage;
38
39
  for (let i = 1; i < this.colors.length; i++) {
39
40
  next = this.colors[i];
40
41
  prev = this.colors[i - 1];
41
42
  if (color.isEqual(next.color))
42
- return next.angle;
43
+ return next.percentage;
43
44
  let redDif = next.color.red - prev.color.red;
44
45
  let greenDif = next.color.green - prev.color.green;
45
46
  let blueDif = next.color.blue - prev.color.blue;
47
+ let alphaDif = denormalizeShade(next.color.alpha) - denormalizeShade(prev.color.alpha);
46
48
  let redDifColor = color.red - prev.color.red;
47
49
  let greenDifColor = color.green - prev.color.green;
48
50
  let blueDifColor = color.blue - prev.color.blue;
51
+ let alphaDifColor = denormalizeShade(color.alpha) - denormalizeShade(prev.color.alpha);
49
52
  if (((redDifColor >= 0 && redDifColor <= redDif) || (redDifColor <= 0 && redDifColor >= redDif)) &&
50
53
  ((greenDifColor >= 0 && greenDifColor <= greenDif) || (greenDifColor <= 0 && greenDifColor >= greenDif)) &&
51
- ((blueDifColor >= 0 && blueDifColor <= blueDif) || (blueDifColor <= 0 && blueDifColor >= blueDif))) {
54
+ ((blueDifColor >= 0 && blueDifColor <= blueDif) || (blueDifColor <= 0 && blueDifColor >= blueDif)) &&
55
+ ((alphaDifColor >= 0 && alphaDifColor <= alphaDif) || (alphaDifColor <= 0 && alphaDifColor >= alphaDif))) {
52
56
  const redCoef = ((color.red - prev.color.red) / (next.color.red - prev.color.red));
53
57
  const greenCoef = ((color.green - prev.color.green) / (next.color.green - prev.color.green));
54
58
  const blueCoef = ((color.blue - prev.color.blue) / (next.color.blue - prev.color.blue));
55
- const coefs = [redCoef, greenCoef, blueCoef].filter(Boolean);
56
- return (next.angle - prev.angle) * Math.min(...coefs) + prev.angle;
59
+ const alphaCoef = ((color.alpha - prev.color.alpha) / (next.color.alpha - prev.color.alpha));
60
+ const coefs = [redCoef, greenCoef, blueCoef, alphaCoef].filter(Boolean);
61
+ return (next.percentage - prev.percentage) * Math.min(...coefs) + prev.percentage;
57
62
  }
58
63
  }
59
64
  return undefined;
60
65
  }
61
66
  isColorInRange(color) {
62
- return Boolean(this.getAngleByColor(color));
63
- }
64
- /**
65
- * Для использования метода, углы должны быть в Turn единицах измерения
66
- */
67
- toCanvas(ctx, center) {
68
- const gradient = ctx.createConicGradient(0, ...center);
69
- for (let color of this.colors) {
70
- gradient.addColorStop(color.angle, color.color.toString());
71
- }
72
- return gradient;
73
- }
74
- /**
75
- * Для использования метода, углы должны быть в Turn единицах измерения
76
- */
77
- toCSS() {
78
- let s = '';
79
- for (let color of this.colors) {
80
- if (s)
81
- s += ',';
82
- s += `rgb(${color.color.red},${color.color.green},${color.color.blue})`;
83
- }
84
- s = `conic-gradient(in srgb from 0.25turn at 50% 50%, ${s})`;
85
- return s;
67
+ return Boolean(this.getPercentageByColor(color));
86
68
  }
87
69
  }
@@ -0,0 +1,26 @@
1
+ import { BaseGradient } from "./base.gradient.js";
2
+ export class ConicGradient extends BaseGradient {
3
+ /**
4
+ * Для использования метода, углы должны быть в Turn единицах измерения
5
+ */
6
+ toCanvas(ctx, center) {
7
+ const gradient = ctx.createConicGradient(0, ...center);
8
+ for (let color of this.colors) {
9
+ gradient.addColorStop(color.percentage, color.color.toString());
10
+ }
11
+ return gradient;
12
+ }
13
+ /**
14
+ * Для использования метода, углы должны быть в Turn единицах измерения
15
+ */
16
+ toCSS() {
17
+ let s = '';
18
+ for (let color of this.colors) {
19
+ if (s)
20
+ s += ',';
21
+ s += `rgb(${color.color.red},${color.color.green},${color.color.blue})`;
22
+ }
23
+ s = `conic-gradient(in srgb from 0.25turn at 50% 50%, ${s})`;
24
+ return s;
25
+ }
26
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./conic.gradient.js";
2
+ export * from "./linear.gradient.js";
@@ -0,0 +1,19 @@
1
+ import { BaseGradient } from "./base.gradient.js";
2
+ export class LinearGradient extends BaseGradient {
3
+ toCanvas(ctx, p1, p2) {
4
+ const gradient = ctx.createLinearGradient(...p1, ...p2);
5
+ for (let color of this.colors) {
6
+ gradient.addColorStop(color.percentage, color.color.toString());
7
+ }
8
+ return gradient;
9
+ }
10
+ toCSS(direction = 'to bottom') {
11
+ let s = '';
12
+ for (let color of this.colors) {
13
+ if (s)
14
+ s += ',';
15
+ s += `rgb(${color.color.red},${color.color.green},${color.color.blue})`;
16
+ }
17
+ return `conic-gradient(${direction}, ${s})`;
18
+ }
19
+ }
@@ -1,2 +1,5 @@
1
1
  export * from "./color.js";
2
- export * from "./conic.gradient.js";
2
+ export * from "./gradient/conic.gradient.js";
3
+ export * from "./blend.js";
4
+ export * from "./utils.js";
5
+ export * from "./constants.js";
@@ -0,0 +1,5 @@
1
+ import { Color } from "./color.ts";
2
+ /**
3
+ * Смешение цветов
4
+ */
5
+ export declare function blend(background: Color, ...foregrounds: Color[]): Color;
@@ -0,0 +1,6 @@
1
+ import { Color } from "./color.ts";
2
+ export declare const COLORS: {
3
+ WHITE: Color;
4
+ BLACK: Color;
5
+ TRANSPARENT: Color;
6
+ };
@@ -0,0 +1,17 @@
1
+ import { Color } from "../color.ts";
2
+ export declare abstract class BaseGradient {
3
+ protected colors: {
4
+ percentage: number;
5
+ color: Color;
6
+ }[];
7
+ constructor(...colors: typeof this.colors);
8
+ /**
9
+ * Получить цвет по углу от оси X по часовой стрелке
10
+ * @param percentage единица измерения угла должна быть той же самой, что и углы всех передаваемых в констурктор цветов
11
+ */
12
+ getColorAtPercentage(percentage: number): Color | undefined;
13
+ getPercentageByColor(color: Color): number | undefined;
14
+ isColorInRange(color: Color): boolean;
15
+ abstract toCanvas(ctx: CanvasRenderingContext2D, ...args: any): CanvasGradient;
16
+ abstract toCSS(...args: any): string;
17
+ }
@@ -0,0 +1,12 @@
1
+ import type { IPoint2 } from "../../figures/index.ts";
2
+ import { BaseGradient } from "./base.gradient.ts";
3
+ export declare class ConicGradient extends BaseGradient {
4
+ /**
5
+ * Для использования метода, углы должны быть в Turn единицах измерения
6
+ */
7
+ toCanvas(ctx: CanvasRenderingContext2D, center: IPoint2): CanvasGradient;
8
+ /**
9
+ * Для использования метода, углы должны быть в Turn единицах измерения
10
+ */
11
+ toCSS(): string;
12
+ }
@@ -0,0 +1,2 @@
1
+ export * from './conic.gradient.ts';
2
+ export * from './linear.gradient.ts';
@@ -0,0 +1,6 @@
1
+ import { BaseGradient } from "./base.gradient.ts";
2
+ import type { IPoint2 } from "../../figures/index.ts";
3
+ export declare class LinearGradient extends BaseGradient {
4
+ toCanvas(ctx: CanvasRenderingContext2D, p1: IPoint2, p2: IPoint2): CanvasGradient;
5
+ toCSS(direction?: string): string;
6
+ }
@@ -1,2 +1,5 @@
1
1
  export * from './color.ts';
2
- export * from './conic.gradient.ts';
2
+ export * from './gradient/conic.gradient.ts';
3
+ export * from "./blend.ts";
4
+ export * from './utils.ts';
5
+ export * from './constants.ts';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fbltd/math",
3
- "version": "1.0.40",
3
+ "version": "1.0.41",
4
4
  "description": "Math and geometry utilities",
5
5
  "sideEffects": false,
6
6
  "main": "dist/bin/index.js",
@@ -1,27 +0,0 @@
1
- import { Color } from "./color.ts";
2
- import type { IPoint2 } from "../figures/index.ts";
3
- export declare class ConicGradient {
4
- colors: {
5
- angle: number;
6
- color: Color;
7
- }[];
8
- constructor(...colors: {
9
- angle: number;
10
- color: Color;
11
- }[]);
12
- /**
13
- * Получить цвет по углу от оси X по часовой стрелке
14
- * @param angle единица измерения угла должна быть той же самой, что и углы всех передаваемых в констурктор цветов
15
- */
16
- getColorAtAngle(angle: number): Color | undefined;
17
- getAngleByColor(color: Color): number | undefined;
18
- isColorInRange(color: Color): boolean;
19
- /**
20
- * Для использования метода, углы должны быть в Turn единицах измерения
21
- */
22
- toCanvas(ctx: CanvasRenderingContext2D, center: IPoint2): CanvasGradient;
23
- /**
24
- * Для использования метода, углы должны быть в Turn единицах измерения
25
- */
26
- toCSS(): string;
27
- }