You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@baremaps.apache.org by bc...@apache.org on 2023/06/18 12:04:41 UTC
[incubator-baremaps] 01/01: Refactor the basemap and introduce new themes
This is an automated email from the ASF dual-hosted git repository.
bchapuis pushed a commit to branch basemap-refactoring
in repository https://gitbox.apache.org/repos/asf/incubator-baremaps.git
commit dc6a8a527a4d800f9ed761c5a765b8f9be144d26
Author: Bertil Chapuis <bc...@gmail.com>
AuthorDate: Sun Jun 18 14:04:27 2023 +0200
Refactor the basemap and introduce new themes
---
basemap/theme.js | 2 +-
basemap/themes/achromatomaly.js | 13 ++
basemap/themes/achromatopsia.js | 13 ++
basemap/themes/contrast.js | 13 ++
basemap/themes/dark.js | 13 ++
basemap/themes/default.js | 3 -
basemap/themes/deuteranomaly.js | 13 ++
basemap/themes/deuteranopia.js | 13 ++
basemap/themes/grayscale.js | 13 ++
basemap/themes/light.js | 58 ++-----
basemap/themes/positron.js | 18 ---
basemap/themes/protanomaly.js | 13 ++
basemap/themes/protanopia.js | 13 ++
basemap/themes/road.js | 15 --
basemap/themes/tools.js | 36 -----
basemap/themes/transportation.js | 20 +++
basemap/themes/tritanomaly.js | 13 ++
basemap/themes/tritanopia.js | 13 ++
basemap/utils/color.js | 336 ++++++++++++++++++++++++++++++++++-----
19 files changed, 471 insertions(+), 160 deletions(-)
diff --git a/basemap/theme.js b/basemap/theme.js
index 00a70be1..87c99b84 100644
--- a/basemap/theme.js
+++ b/basemap/theme.js
@@ -1,3 +1,3 @@
-import theme from "./themes/default.js";
+import theme from "./themes/transportation.js";
export default theme;
\ No newline at end of file
diff --git a/basemap/themes/achromatomaly.js b/basemap/themes/achromatomaly.js
new file mode 100644
index 00000000..11430509
--- /dev/null
+++ b/basemap/themes/achromatomaly.js
@@ -0,0 +1,13 @@
+import style from './default.js';
+import {Color, ColorBlind} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.colorblind(ColorBlind.Achromatomaly).toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/themes/achromatopsia.js b/basemap/themes/achromatopsia.js
new file mode 100644
index 00000000..e593b603
--- /dev/null
+++ b/basemap/themes/achromatopsia.js
@@ -0,0 +1,13 @@
+import style from './default.js';
+import {Color, ColorBlind} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.colorblind(ColorBlind.Achromatopsia).toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/themes/contrast.js b/basemap/themes/contrast.js
new file mode 100644
index 00000000..f6cbee6a
--- /dev/null
+++ b/basemap/themes/contrast.js
@@ -0,0 +1,13 @@
+import style from './default.js';
+import {Color} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.contrast(0.1).toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/themes/dark.js b/basemap/themes/dark.js
new file mode 100644
index 00000000..e4c173ef
--- /dev/null
+++ b/basemap/themes/dark.js
@@ -0,0 +1,13 @@
+import style from './light.js';
+import {Color} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.grayscale().invert().toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/themes/default.js b/basemap/themes/default.js
index a6173d41..87ef3b61 100644
--- a/basemap/themes/default.js
+++ b/basemap/themes/default.js
@@ -1,5 +1,4 @@
export default {
-
aerialwayStyleLinePaintLineColor: 'rgb(177, 177, 175)',
aerowayLineRunwayLineColor: 'rgba(187, 187, 204, 1.0)',
aerowayLineTaxiwayLineColor: 'rgba(187, 187, 204, 1.0)',
@@ -607,6 +606,4 @@ export default {
waterwayLineWaterwayLineColor: 'rgb(170, 211, 223)',
waterwayTunnelCasingLineColor: 'rgb(170, 211, 223)',
waterwayTunnelLineLineColor: 'rgb(243, 247, 247)'
-
-
};
diff --git a/basemap/themes/deuteranomaly.js b/basemap/themes/deuteranomaly.js
new file mode 100644
index 00000000..d82134d9
--- /dev/null
+++ b/basemap/themes/deuteranomaly.js
@@ -0,0 +1,13 @@
+import style from './default.js';
+import {Color, ColorBlind} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.colorblind(ColorBlind.Deuteranomaly).toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/themes/deuteranopia.js b/basemap/themes/deuteranopia.js
new file mode 100644
index 00000000..414e201a
--- /dev/null
+++ b/basemap/themes/deuteranopia.js
@@ -0,0 +1,13 @@
+import style from './default.js';
+import {Color, ColorBlind} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.colorblind(ColorBlind.Deuteranopia).toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/themes/grayscale.js b/basemap/themes/grayscale.js
new file mode 100644
index 00000000..53e42682
--- /dev/null
+++ b/basemap/themes/grayscale.js
@@ -0,0 +1,13 @@
+import style from './default.js';
+import {Color} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.grayscale().toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/themes/light.js b/basemap/themes/light.js
index 2027d9e0..547014ed 100644
--- a/basemap/themes/light.js
+++ b/basemap/themes/light.js
@@ -1,49 +1,13 @@
-import * as importedTools from "./tools.js";
-import positronScheme from "./positron.js";
-
-const CLARITYFACTOR = 4.7;
-
-
-function lightScheme(string) {
- const table = importedTools.cutRgbString(string);
- if (table[1] != null) {
- let newColor = importedTools.max - importedTools.clamp(table[0] / CLARITYFACTOR);
- return importedTools.giveNewColorString(table, newColor, newColor, newColor);
+import style from './grayscale.js';
+import {Color} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.grayscale().lighten(0.1).toString();
+ return acc;
}
- return null;
-}
-
-export default Object.entries(positronScheme).reduce((acc, [key, value]) => {
- acc[key] = lightScheme(value);
- return {
- ...acc,
- attractionStyleWaterSlideLineColor: 'rgb(175,175,175)',
- landuseBackgroundBasinFillColor: 'rgb(175,175,175)',
- leisureBackgroundSwimmingPoolFillColor: 'rgb(175,175,175)',
- leisureOverlaySwimmingPoolFillOutlineColor: 'rgb(175,175,175)',
- naturalBackgroundWaterFillColor: 'rgb(175,175,175)',
- naturalOverlayLakeFillColor: 'rgb(175,175,175)',
- naturalWaterFillColor: 'rgb(175,175,175)',
- oceanWaterFillColor: 'rgb(175,175,175)',
- pointCountryLabelCountryTextColor: 'rgb(90, 56, 90)',
- pointCountryLabelPaintTextHaloColor: 'rgba(255, 255, 255, 0.8)',
- pointIconWaterfallIconColor: 'rgb(175,175,175)',
- pointIconWaterfallTextColor: 'rgb(175,175,175)',
- pointLabelCityFilterOneLabelColor: 'rgb(100, 100, 100)',
- pointLabelCityFilterTwoLabelColor: 'rgb(50, 50, 50)',
- pointLabelCityLabelColor: 'rgb(25, 25, 25)',
- pointLabelLocalityLabelColor: 'rgb(100, 100, 100)',
- pointLabelPaintTextHaloColor: 'rgba(255, 255, 255, 0.8)',
- pointLabelPlaceTextColor: 'rgba(100, 100, 100, 1)',
- pointLabelTownFilterOneLabelColor: 'rgb(100, 100, 100)',
- pointLabelTownFilterTwoLabelColor: 'rgb(75, 75, 75)',
- pointLabelVillageLabelColor: 'rgb(100, 100, 100)',
- waterwayLabelTextColor: 'rgb(175,175,175)',
- waterwayLabelTextHaloColor: 'rgb(175,175,175)',
- waterwayLineWaterwayLineColor: 'rgb(175,175,175)',
- waterwayTunnelCasingLineColor: 'rgb(175,175,175)',
- waterwayTunnelLineLineColor: 'rgb(175,175,175)',
- };
-
-
}, {});
diff --git a/basemap/themes/positron.js b/basemap/themes/positron.js
deleted file mode 100644
index 5eb59286..00000000
--- a/basemap/themes/positron.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import style from './default.js';
-import * as importedTools from "./tools.js";
-
-export function positronScheme(string) {
- const table = importedTools.cutRgbString(string)
- let newColor = positronColorCalculator(table);
-
- return importedTools.giveNewColorString(table, newColor, newColor, newColor);
-};
-
-function positronColorCalculator(table) {
- return Math.round((parseInt(table[0]) + parseInt(table[1]) + parseInt(table[2])) / 3);
-};
-
-export default Object.entries(style).reduce((acc, [key, value]) => {
- acc[key] = positronScheme(value);
- return acc;
-}, {});
diff --git a/basemap/themes/protanomaly.js b/basemap/themes/protanomaly.js
new file mode 100644
index 00000000..1dd25142
--- /dev/null
+++ b/basemap/themes/protanomaly.js
@@ -0,0 +1,13 @@
+import style from './default.js';
+import {Color, ColorBlind} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.colorblind(ColorBlind.Protanomaly).toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/themes/protanopia.js b/basemap/themes/protanopia.js
new file mode 100644
index 00000000..bc79a85e
--- /dev/null
+++ b/basemap/themes/protanopia.js
@@ -0,0 +1,13 @@
+import style from './default.js';
+import {Color, ColorBlind} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.colorblind(ColorBlind.Protanopia).toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/themes/road.js b/basemap/themes/road.js
deleted file mode 100644
index a7b9e20e..00000000
--- a/basemap/themes/road.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import style from './default.js';
-import * as importedTools from "./tools.js";
-
-function roadScheme(string) {
- const table = importedTools.cutRgbString(string);
- let redElement = importedTools.clamp(table[0] + 50);
- return importedTools.giveNewColorString(table, redElement, table[1], table[2]);
-}
-
-export default Object.entries(style).reduce((acc, [key, value]) => {
- acc[key] = roadScheme(value);
- return acc;
-}, {});
-
-
diff --git a/basemap/themes/tools.js b/basemap/themes/tools.js
deleted file mode 100644
index 0e5c815e..00000000
--- a/basemap/themes/tools.js
+++ /dev/null
@@ -1,36 +0,0 @@
-export const min = 0;
-export const max = 255;
-
-export function giveNewColorString(table, newRed, newGreen, newBlue) {
- let opacity = table[3];
- return `rgba(${newRed},${newGreen},${newBlue},${opacity})`;
-};
-
-export function cutRgbString(color) {
- let rgb = color.replace(/\s*/g, '').match(/rgb\((\d*)\,(\d*)\,(\d*)\)/)
- if (rgb != null) {
- return [
- parseInt(rgb[1]),
- parseInt(rgb[2]),
- parseInt(rgb[3]),
- 1,
- ]
- }
- ;
- let rgba = color.replace(/\s*/g, '').match(/rgba\((\d*)\,(\d*)\,(\d*)\,(.*)\)/)
- if (rgba != null) {
-
- return [
- parseInt(rgba[1]),
- parseInt(rgba[2]),
- parseInt(rgba[3]),
- parseFloat(rgba[4]),
- ]
- }
- ;
- return null;
-}
-
-export function clamp(value) {
- return Math.min(Math.max(value, min), max);
-}
diff --git a/basemap/themes/transportation.js b/basemap/themes/transportation.js
new file mode 100644
index 00000000..87f8cce2
--- /dev/null
+++ b/basemap/themes/transportation.js
@@ -0,0 +1,20 @@
+import style from './default.js';
+import {Color} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else if (key.toLowerCase().includes("highway")
+ || key.toLowerCase().includes("tunnel")
+ || key.toLowerCase().includes("bridge")
+ || key.toLowerCase().includes("rail")
+ || key.toLowerCase().includes("ferry")) {
+ acc[key] = color.darken(0.2).toString();
+ return acc;
+ } else {
+ acc[key] = color.grayscale().lighten(0.1).toString();
+ return acc;
+ }
+}, {});
\ No newline at end of file
diff --git a/basemap/themes/tritanomaly.js b/basemap/themes/tritanomaly.js
new file mode 100644
index 00000000..ecbb8769
--- /dev/null
+++ b/basemap/themes/tritanomaly.js
@@ -0,0 +1,13 @@
+import style from './default.js';
+import {Color, ColorBlind} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.colorblind(ColorBlind.Tritanomaly).toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/themes/tritanopia.js b/basemap/themes/tritanopia.js
new file mode 100644
index 00000000..b1429910
--- /dev/null
+++ b/basemap/themes/tritanopia.js
@@ -0,0 +1,13 @@
+import style from './default.js';
+import {Color, ColorBlind} from "../utils/color.js";
+
+export default Object.entries(style).reduce((acc, [key, value]) => {
+ let color = Color.fromString(value);
+ if (color == null) {
+ acc[key] = value;
+ return acc;
+ } else {
+ acc[key] = color.colorblind(ColorBlind.Tritanopia).toString();
+ return acc;
+ }
+}, {});
diff --git a/basemap/utils/color.js b/basemap/utils/color.js
index 298a6262..2a04ecf2 100644
--- a/basemap/utils/color.js
+++ b/basemap/utils/color.js
@@ -9,56 +9,312 @@
or implied. See the License for the specific language governing permissions and limitations under
the License.
**/
-export function lighten(color, percent) {
- let {r, g, b, a} = readColor(color);
- return writeColor({
- r: lightenValue(r, percent),
- g: lightenValue(g, percent),
- b: lightenValue(b, percent),
- a: a,
- })
-}
-export function darken(color, percent) {
- let {r, g, b, a} = readColor(color);
- return writeColor({
- r: darkenValue(r, percent),
- g: darkenValue(g, percent),
- b: darkenValue(b, percent),
- a: a,
- })
-}
+class Color {
+
+ constructor() {
+
+ }
+
+ static fromString(color) {
+ let rgb = RGB.fromString(color);
+ if (rgb != null) {
+ return rgb;
+ }
+ let hsl = HSL.fromString(color);
+ if (hsl != null) {
+ return hsl;
+ }
+ return null;
+ }
+
+ toRGB() {
+ throw new Error('Abstract method');
+ }
+
+ toHSL() {
+ throw new Error('Abstract method');
+ }
+
+ grayscale() {
+ let rgb = this.toRGB();
+ let gray = Math.round(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b);
+ return new RGB(gray, gray, gray, rgb.a);
+ }
-function lightenValue(value, percent) {
- return Math.round(value - value * percent);
+ lighten(amount) {
+ let hsl = this.toHSL();
+ hsl.l += amount;
+ hsl.l = Math.min(hsl.l, 1);
+ return hsl.toRGB();
+ }
+
+ darken(amount) {
+ let hsl = this.toHSL();
+ hsl.l -= amount;
+ hsl.l = Math.max(hsl.l, 0);
+ return hsl.toRGB();
+ }
+
+ saturate(amount) {
+ let hsl = this.toHSL();
+ hsl.s += amount;
+ hsl.s = Math.min(hsl.s, 1);
+ return hsl.toRGB();
+ }
+
+ desaturate(amount) {
+ let hsl = this.toHSL();
+ hsl.s -= amount;
+ hsl.s = Math.max(hsl.s, 0);
+ return hsl.toRGB();
+ }
+
+ fade(amount) {
+ let rgb = this.toRGB();
+ rgb.a -= amount;
+ rgb.a = Math.max(rgb.a, 0);
+ return rgb;
+ }
+
+ opacify(amount) {
+ let rgb = this.toRGB();
+ rgb.a += amount;
+ rgb.a = Math.min(rgb.a, 1);
+ return rgb;
+ }
+
+ rotate(degrees) {
+ let hsl = this.toHSL();
+ hsl.h = (hsl.h + degrees) % 360;
+ return hsl.toRGB();
+ }
+
+ invert() {
+ let rgb = this.toRGB();
+ rgb.r = 255 - rgb.r;
+ rgb.g = 255 - rgb.g;
+ rgb.b = 255 - rgb.b;
+ return rgb;
+ }
+
+ contrast(factor) {
+ factor = (1 + factor) ** 2;
+ let rgb = this.toRGB();
+ let r = ((rgb.r / 255.0 - 0.5) * factor + 0.5) * 255.0;
+ let g = ((rgb.g / 255.0 - 0.5) * factor + 0.5) * 255.0;
+ let b = ((rgb.b / 255.0 - 0.5) * factor + 0.5) * 255.0;
+ r = Math.max(0, Math.min(255, r));
+ g = Math.max(0, Math.min(255, g));
+ b = Math.max(0, Math.min(255, b));
+ return new RGB(r, g, b, rgb.a);
+ }
+
+ colorblind(type) {
+ return type(this.toRGB());
+ }
+
+ toString() {
+ throw new Error('Abstract method');
+ }
}
-function darkenValue(value, percent) {
- return Math.round(value + (255 - value) * percent);
+class RGB extends Color {
+
+ constructor(r, g, b, a = 1) {
+ super();
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.a = a;
+ }
+
+ static fromString(color) {
+ let rgb = color.replace(/\s*/g, '').match(/rgb\((\d*)\,(\d*)\,(\d*)\)/)
+ if (rgb != null) {
+ return new RGB(parseInt(rgb[1]), parseInt(rgb[2]), parseInt(rgb[3]), 1)
+ }
+ let rgba = color.replace(/\s*/g, '').match(/rgba\((\d*)\,(\d*)\,(\d*)\,(.*)\)/)
+ if (rgba != null) {
+ return new RGB(parseInt(rgba[1]), parseInt(rgba[2]), parseInt(rgba[3]), parseFloat(rgba[4]))
+ }
+ return null
+ }
+
+ toRGB() {
+ return this;
+ }
+
+ toHSL() {
+ let r = this.r / 255;
+ let g = this.g / 255;
+ let b = this.b / 255;
+ let max = Math.max(r, g, b);
+ let min = Math.min(r, g, b);
+ let h, s, l = (max + min) / 2;
+ if (max == min) {
+ h = s = 0;
+ } else {
+ let d = max - min;
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+ switch (max) {
+ case r:
+ h = (g - b) / d + (g < b ? 6 : 0)
+ break;
+ case g:
+ h = (b - r) / d + 2
+ break;
+ case b:
+ h = (r - g) / d + 4
+ break;
+ }
+ h /= 6;
+ }
+ return new HSL(h, s, l, this.a);
+ }
+
+ toString() {
+ if (this.a == 1) {
+ return `rgb(${this.r},${this.g},${this.b})`;
+ } else {
+ return `rgba(${this.r},${this.g},${this.b},${this.a})`;
+ }
+ }
}
-export function readColor(color) {
- let rgb = color.replace(/\s*/g, '').match(/rgb\((\d*)\,(\d*)\,(\d*)\)/)
- if (rgb != null) {
- return {
- r: parseInt(rgb[1]),
- g: parseInt(rgb[2]),
- b: parseInt(rgb[3]),
- a: 1,
+class HSL extends Color {
+
+ constructor(h, s, l, a = 1) {
+ super();
+ this.h = h;
+ this.s = s;
+ this.l = l;
+ this.a = a;
+ }
+
+ static fromString(color) {
+ let hsl = color.replace(/\s*/g, '').match(/hsl\((\d*)\,(\d*)\,(\d*)\)/)
+ if (hsl != null) {
+ return new HSL(parseInt(hsl[1]), parseInt(hsl[2]), parseInt(hsl[3]), 1)
+ }
+ let hsla = color.replace(/\s*/g, '').match(/hsla\((\d*)\,(\d*)\,(\d*)\,(.*)\)/)
+ if (hsla != null) {
+ return new HSL(parseInt(hsla[1]), parseInt(hsla[2]), parseInt(hsla[3]), parseFloat(hsla[4]))
}
+ return null
}
- let rgba = color.replace(/\s*/g, '').match(/rgba\((\d*)\,(\d*)\,(\d*)\,(.*)\)/)
- if (rgba != null) {
- return {
- r: parseInt(rgba[1]),
- g: parseInt(rgba[2]),
- b: parseInt(rgba[3]),
- a: parseFloat(rgba[4]),
+
+ toRGB() {
+ let r, g, b;
+ if (this.s == 0) {
+ r = g = b = this.l;
+ } else {
+ let hue2rgb = function hue2rgb(p, q, t) {
+ if (t < 0) {
+ t += 1;
+ }
+ if (t > 1) {
+ t -= 1;
+ }
+ if (t < 1 / 6) {
+ return p + (q - p) * 6 * t;
+ }
+ if (t < 1 / 2) {
+ return q;
+ }
+ if (t < 2 / 3) {
+ return p + (q - p) * (2 / 3 - t) * 6;
+ }
+ return p;
+ }
+ let q = this.l < 0.5 ? this.l * (1 + this.s) : this.l + this.s - this.l * this.s;
+ let p = 2 * this.l - q;
+ r = hue2rgb(p, q, this.h + 1 / 3);
+ g = hue2rgb(p, q, this.h);
+ b = hue2rgb(p, q, this.h - 1 / 3);
}
+ return new RGB(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), this.a);
+ }
+
+ toHSL() {
+ return this;
}
- return null
+
+ toString() {
+ if (this.a == 1) {
+ return `hsl(${this.h},${this.s},${this.l})`;
+ } else {
+ return `hsla(${this.h},${this.s},${this.l},${this.a})`;
+ }
+ }
+}
+
+function Achromatopsia(rgb) {
+ let r = rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114;
+ let g = rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114;
+ let b = rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114;
+ return new RGB(r, g, b, rgb.a);
+}
+
+function Achromatomaly(rgb) {
+ let r = rgb.r * 0.618 + rgb.g * 0.320 + rgb.b * 0.062;
+ let g = rgb.r * 0.163 + rgb.g * 0.775 + rgb.b * 0.062;
+ let b = rgb.r * 0.163 + rgb.g * 0.320 + rgb.b * 0.516;
+ return new RGB(r, g, b, rgb.a);
}
-function writeColor(color) {
- return `rgba(${color.r},${color.g},${color.b},${color.a})`;
+function Deuteranopia(rgb) {
+ let r = rgb.r * 0.625 + rgb.g * 0.375 + rgb.b * 0.0;
+ let g = rgb.r * 0.7 + rgb.g * 0.3 + rgb.b * 0.0;
+ let b = rgb.r * 0.0 + rgb.g * 0.3 + rgb.b * 0.7;
+ return new RGB(r, g, b, rgb.a);
}
+
+function Deuteranomaly(rgb) {
+ let r = rgb.r * 0.8 + rgb.g * 0.2 + rgb.b * 0.0;
+ let g = rgb.r * 0.258 + rgb.g * 0.742 + rgb.b * 0.0;
+ let b = rgb.r * 0.0 + rgb.g * 0.142 + rgb.b * 0.858;
+ return new RGB(r, g, b, rgb.a);
+}
+
+function Protanopia(rgb) {
+ let r = rgb.r * 0.567 + rgb.g * 0.433 + rgb.b * 0.0;
+ let g = rgb.r * 0.558 + rgb.g * 0.442 + rgb.b * 0.0;
+ let b = rgb.r * 0.0 + rgb.g * 0.242 + rgb.b * 0.758;
+ return new RGB(r, g, b, rgb.a);
+}
+
+function Protanomaly(rgb) {
+ let r = rgb.r * 0.817 + rgb.g * 0.183 + rgb.b * 0.0;
+ let g = rgb.r * 0.333 + rgb.g * 0.667 + rgb.b * 0.0;
+ let b = rgb.r * 0.0 + rgb.g * 0.125 + rgb.b * 0.875;
+ return new RGB(r, g, b, rgb.a);
+}
+
+
+function Tritanopia(rgb) {
+ let r = rgb.r * 0.95 + rgb.g * 0.05 + rgb.b * 0.0;
+ let g = rgb.r * 0.0 + rgb.g * 0.433 + rgb.b * 0.567;
+ let b = rgb.r * 0.0 + rgb.g * 0.475 + rgb.b * 0.525;
+ return new RGB(r, g, b, rgb.a);
+}
+
+function Tritanomaly(rgb) {
+ let r = rgb.r * 0.967 + rgb.g * 0.033 + rgb.b * 0.0;
+ let g = rgb.r * 0.0 + rgb.g * 0.733 + rgb.b * 0.267;
+ let b = rgb.r * 0.0 + rgb.g * 0.183 + rgb.b * 0.817;
+ return new RGB(r, g, b, rgb.a);
+}
+
+const ColorBlind = {
+ Achromatopsia: Achromatopsia,
+ Achromatomaly: Achromatomaly,
+ Deuteranopia: Deuteranopia,
+ Deuteranomaly: Deuteranomaly,
+ Protanopia: Protanopia,
+ Protanomaly: Protanomaly,
+ Tritanopia: Tritanopia,
+ Tritanomaly: Tritanomaly
+}
+
+export {Color, RGB, HSL, ColorBlind};