chromaticity-color-utilities
Advanced tools
Comparing version 0.5.0-alpha to 0.7.0-alpha
"use strict"; | ||
// chromaticity-color-utilities | ||
// Copyright (C) 2021 Emma Litwa-Vulcu | ||
// Copyright (C) 2022 Emma Litwa-Vulcu | ||
// | ||
@@ -5,0 +5,0 @@ // This program is free software: you can redistribute it and/or modify |
"use strict"; | ||
// chromaticity-color-utilities | ||
// Copyright (C) 2021 Emma Litwa-Vulcu | ||
// Copyright (C) 2022 Emma Litwa-Vulcu | ||
// | ||
@@ -5,0 +5,0 @@ // This program is free software: you can redistribute it and/or modify |
"use strict"; | ||
// chromaticity-color-utilities | ||
// Copyright (C) 2021 Emma Litwa-Vulcu | ||
// Copyright (C) 2022 Emma Litwa-Vulcu | ||
// | ||
@@ -179,2 +179,6 @@ // This program is free software: you can redistribute it and/or modify | ||
switch (args.method) { | ||
case 'rgb': | ||
case 'rgba': | ||
modified = Modify_1.default.rgbDarken(this.torgb({ round: false }), args.amount, args.round); | ||
break; | ||
case 'hsl': | ||
@@ -203,2 +207,6 @@ case 'hsla': | ||
switch (args.method) { | ||
case 'rgb': | ||
case 'rgba': | ||
modified = Modify_1.default.rgbLighten(this.torgb({ round: false }), args.amount, args.round); | ||
break; | ||
case 'hsl': | ||
@@ -270,2 +278,3 @@ case 'hsla': | ||
colorType.prototype.scheme = function (type, args) { | ||
var _a, _b, _c; | ||
if (typeof args === 'undefined') | ||
@@ -331,3 +340,3 @@ args = {}; | ||
: args.distanceToBlack; | ||
intScheme = Harmony_1.default.shade(this.to('hsl', { round: false }), args.colors, distance); | ||
intScheme = Harmony_1.default.shade(this, args.method ? args.method.toLowerCase() : 'hsl', args.colors, distance !== null && distance !== void 0 ? distance : 1, (_a = args.round) !== null && _a !== void 0 ? _a : true); | ||
break; | ||
@@ -344,3 +353,3 @@ case 'tint': | ||
: args.distanceToWhite; | ||
intScheme = Harmony_1.default.tint(this.to('hsl', { round: false }), args.colors, distance); | ||
intScheme = Harmony_1.default.tint(this, args.method ? args.method.toLowerCase() : 'hsl', args.colors, distance !== null && distance !== void 0 ? distance : 1, (_b = args.round) !== null && _b !== void 0 ? _b : true); | ||
break; | ||
@@ -360,3 +369,3 @@ case 'tintshade': | ||
: args.distanceToWhite; | ||
intScheme = Harmony_1.default.shadetint(this.to('hsl', { round: false }), args.colors, distance, args.distanceToBlack); | ||
intScheme = Harmony_1.default.shadetint(this, args.method ? args.method.toLowerCase() : 'hsl', args.colors, (_c = args.round) !== null && _c !== void 0 ? _c : true, distance !== null && distance !== void 0 ? distance : 1, args.distanceToBlack); | ||
break; | ||
@@ -371,17 +380,3 @@ case 'gradient': | ||
} | ||
if (typeof args.method === 'undefined') { | ||
args.method = 'rgb'; | ||
} | ||
switch (args.method) { | ||
case 'rgb': | ||
case 'rgba': | ||
intScheme = Harmony_1.default.rgbGradient(this.torgb({ round: false }), args.with.torgb({ round: false }), args.colors); | ||
break; | ||
case 'hsv': | ||
case 'hsva': | ||
intScheme = Harmony_1.default.hsvGradient(this.tohsv({ round: false }), args.with.tohsv({ round: false }), args.colors); | ||
break; | ||
default: | ||
throw new Error('Unrecognized saturate method'); | ||
} | ||
intScheme = Harmony_1.default.gradient(args.method ? args.method.toLowerCase() : 'rgb', this, args.with, args.colors, args.round); | ||
break; | ||
@@ -388,0 +383,0 @@ default: |
import * as Colors from './Colors'; | ||
import { colorType } from './ColorType'; | ||
declare class Harmony { | ||
@@ -55,46 +56,43 @@ /** | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distanceToBlack=1] 0-1, where 1 is all the way to black | ||
* @returns | ||
* @param {T extends colorType} color | ||
* @param {string} [method='hsl'] | ||
* @param {number} colors | ||
* @param {number} [distanceToBlack=1] 0-1, where 1 is all the way to black | ||
* @param {boolesn} [round=true] | ||
* @returns {T[]} | ||
*/ | ||
static shade(hsl: Colors.hsl, colors: number, distanceToBlack?: number): Colors.hsl[]; | ||
static shade<T extends colorType>(color: T, method: string | undefined, colors: number, distanceToBlack?: number, round?: boolean): T[]; | ||
/** | ||
* Returns an array of colors of a lighter tint | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distanceToWhite=1] 0-1, where 1 is all the way to white | ||
* @returns | ||
* @param {T extends colorType} color | ||
* @param {string} [method='hsl'] | ||
* @param {number} colors | ||
* @param {number} [distanceToWhite=1] 0-1, where 1 is all the way to white | ||
* @param {boolesn} [round=true] | ||
* @returns {T[]} | ||
*/ | ||
static tint(hsl: Colors.hsl, colors: number, distanceToWhite?: number): Colors.hsl[]; | ||
static tint<T extends colorType>(color: T, method: string | undefined, colors: number, distanceToWhite?: number, round?: boolean): T[]; | ||
/** | ||
* Returns an array of colors of darker shades and lighter tints | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distance=1] 0-1, where 1 is all the way to closest bound OR white, if distanceShade given | ||
* @param {number} [distanceShade=1] 0-1, where 1 is all the way to black | ||
* @param {T extends colorType} color | ||
* @param {string} method | ||
* @param {number} colors | ||
* @param {boolean} [round=true] | ||
* @param {number} [distance=1] 0-1, where 1 is all the way to closest bound OR white, if distanceShade given | ||
* @param {number} [distanceShade=1] 0-1, where 1 is all the way to black | ||
* @returns | ||
*/ | ||
static shadetint(hsl: Colors.hsl, colors: number, distance?: number, distanceShade?: number): Colors.hsl[]; | ||
static shadetint<T extends colorType>(color: T, method: string, colors: number, round?: boolean, distance?: number, distanceShade?: number): T[]; | ||
/** | ||
* Return an array of colors blended from color1 to color2, via rgb | ||
* Return an array of colors blended from color1 to color2 | ||
* | ||
* @param {Colors.rgb} color1 | ||
* @param {Colors.rgb} color2 | ||
* @param {number} colors number of colors in scheme (including color1 and color2) | ||
* @returns | ||
* @param {T extends colorType} color1 | ||
* @param {T extends colorType} color2 | ||
* @param {number} colors number of colors in scheme (including color1 and color2) | ||
* @returns {T[]} | ||
*/ | ||
static rgbGradient(color1: Colors.rgb, color2: Colors.rgb, colors: number): Colors.rgb[]; | ||
/** | ||
* Return an array of colors blended from color1 to color2, via hsv | ||
* | ||
* @param {Colors.hsv} color1 | ||
* @param {Colors.hsv} color2 | ||
* @param {number} colors number of colors in scheme (including color1 and color2) | ||
* @returns | ||
*/ | ||
static hsvGradient(color1: Colors.hsv, color2: Colors.hsv, colors: number): Colors.hsv[]; | ||
static gradient<T extends colorType>(type: string, color1: T, color2: T, colors: number, round?: boolean): T[]; | ||
} | ||
export = Harmony; |
"use strict"; | ||
// chromaticity-color-utilities | ||
// Copyright (C) 2021 Emma Litwa-Vulcu | ||
// Copyright (C) 2022 Emma Litwa-Vulcu | ||
// | ||
@@ -131,18 +131,122 @@ // This program is free software: you can redistribute it and/or modify | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distanceToBlack=1] 0-1, where 1 is all the way to black | ||
* @returns | ||
* @param {T extends colorType} color | ||
* @param {string} [method='hsl'] | ||
* @param {number} colors | ||
* @param {number} [distanceToBlack=1] 0-1, where 1 is all the way to black | ||
* @param {boolesn} [round=true] | ||
* @returns {T[]} | ||
*/ | ||
Harmony.shade = function (hsl, colors, distanceToBlack) { | ||
Harmony.shade = function (color, method, colors, distanceToBlack, round) { | ||
if (method === void 0) { method = 'hsl'; } | ||
if (distanceToBlack === void 0) { distanceToBlack = 1; } | ||
var hsls = []; | ||
var start = hsl.l; | ||
var end = hsl.l * (1 - Math.min(Math.max(distanceToBlack, 0), 1)); | ||
var separation = (start - end) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextL = Math.max(hsl.l - separation * i, 0); | ||
hsls.push(new Colors.hsl(hsl.h, hsl.s, nextL)); | ||
if (round === void 0) { round = true; } | ||
var scheme = []; | ||
var start, end, separation; | ||
switch (method) { | ||
case 'hsv': | ||
case 'hsva': | ||
var hsv = color.to('hsv', { round: false }); | ||
start = hsv.v; | ||
end = start * (1 - Math.min(Math.max(distanceToBlack, 0), 1)); | ||
separation = (start - end) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextV = Math.max(start - separation * i, 0); | ||
scheme.push(new Colors.hsv(hsv.h, hsv.s, nextV, hsv.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'hsi': | ||
case 'hsia': | ||
var hsi = color.to('hsi', { round: false }); | ||
start = hsi.i; | ||
end = start * (1 - Math.min(Math.max(distanceToBlack, 0), 1)); | ||
separation = (start - end) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextI = Math.max(start - separation * i, 0); | ||
scheme.push(new Colors.hsi(hsi.h, hsi.s, nextI, hsi.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'hsp': | ||
case 'hspa': | ||
var hsp = color.to('hsp', { round: false }); | ||
start = hsp.p; | ||
end = start * (1 - Math.min(Math.max(distanceToBlack, 0), 1)); | ||
separation = (start - end) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextP = Math.max(start - separation * i, 0); | ||
scheme.push(new Colors.hsp(hsp.h, hsp.s, nextP, hsp.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'hsl': | ||
case 'hsla': | ||
var hsl = color.to('hsl', { round: false }); | ||
start = hsl.l; | ||
end = start * (1 - Math.min(Math.max(distanceToBlack, 0), 1)); | ||
separation = (start - end) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextL = Math.max(start - separation * i, 0); | ||
scheme.push(new Colors.hsl(hsl.h, hsl.s, nextL, hsl.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'rgb': | ||
case 'rgba': | ||
var rgb = color.to('rgb', { round: false }); | ||
start = Math.max(rgb.r, rgb.g, rgb.b); | ||
end = start * (1 - Math.min(Math.max(distanceToBlack, 0), 1)); | ||
separation = (start - end) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var rNext = Math.max(rgb.r - separation * i, 0); | ||
var gNext = Math.max(rgb.g - separation * i, 0); | ||
var bNext = Math.max(rgb.b - separation * i, 0); | ||
scheme.push(new Colors.rgb(rNext, gNext, bNext, rgb.a).to(color.constructor.name, { round: round, bitDepth: rgb.bitDepth })); | ||
} | ||
break; | ||
case 'rgb2': | ||
case 'rgba2': | ||
var rgb2 = color.to('rgb', { round: false }); | ||
var rEnd = rgb2.r * (1 - Math.min(Math.max(distanceToBlack, 0), 1)); | ||
var gEnd = rgb2.g * (1 - Math.min(Math.max(distanceToBlack, 0), 1)); | ||
var bEnd = rgb2.b * (1 - Math.min(Math.max(distanceToBlack, 0), 1)); | ||
var rSep = (rgb2.r - rEnd) / (colors - 1); | ||
var gSep = (rgb2.g - gEnd) / (colors - 1); | ||
var bSep = (rgb2.b - bEnd) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var rNext = Math.max(rgb2.r - rSep * i, 0); | ||
var gNext = Math.max(rgb2.g - gSep * i, 0); | ||
var bNext = Math.max(rgb2.b - bSep * i, 0); | ||
scheme.push(new Colors.rgb(rNext, gNext, bNext, rgb2.a).to(color.constructor.name, { round: round, bitDepth: rgb2.bitDepth })); | ||
} | ||
break; | ||
case 'cmyk': | ||
var cmyk = color.to('cmyk', { round: false }); | ||
// reverse algorithm, max k is all values = 100 | ||
var cEnd = cmyk.c + (100 - cmyk.c) * Math.min(Math.max(distanceToBlack, 0), 1); | ||
var mEnd = cmyk.m + (100 - cmyk.m) * Math.min(Math.max(distanceToBlack, 0), 1); | ||
var yEnd = cmyk.y + (100 - cmyk.y) * Math.min(Math.max(distanceToBlack, 0), 1); | ||
var kEnd = cmyk.k + (100 - cmyk.k) * Math.min(Math.max(distanceToBlack, 0), 1); | ||
var cSep = (cmyk.c - cEnd) / (colors - 1); | ||
var mSep = (cmyk.m - mEnd) / (colors - 1); | ||
var ySep = (cmyk.y - yEnd) / (colors - 1); | ||
var kSep = (cmyk.k - kEnd) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextC = Math.min(cmyk.c - cSep * i, 100); | ||
var nextM = Math.min(cmyk.m - mSep * i, 100); | ||
var nextY = Math.min(cmyk.y - ySep * i, 100); | ||
var nextK = Math.min(cmyk.k - kSep * i, 100); | ||
scheme.push(new Colors.cmyk(nextC, nextM, nextY, nextK).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
default: | ||
throw new Error('Invalid method for generating color scheme'); | ||
} | ||
return hsls; | ||
return scheme; | ||
}; | ||
@@ -152,18 +256,136 @@ /** | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distanceToWhite=1] 0-1, where 1 is all the way to white | ||
* @returns | ||
* @param {T extends colorType} color | ||
* @param {string} [method='hsl'] | ||
* @param {number} colors | ||
* @param {number} [distanceToWhite=1] 0-1, where 1 is all the way to white | ||
* @param {boolesn} [round=true] | ||
* @returns {T[]} | ||
*/ | ||
Harmony.tint = function (hsl, colors, distanceToWhite) { | ||
Harmony.tint = function (color, method, colors, distanceToWhite, round) { | ||
if (method === void 0) { method = 'hsl'; } | ||
if (distanceToWhite === void 0) { distanceToWhite = 1; } | ||
var hsls = []; | ||
var start = hsl.l; | ||
var end = hsl.l + (100 - hsl.l) * Math.min(Math.max(distanceToWhite, 0), 1); | ||
var separation = (end - start) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextL = Math.min(hsl.l + separation * i, 100); | ||
hsls.push(new Colors.hsl(hsl.h, hsl.s, nextL)); | ||
if (round === void 0) { round = true; } | ||
var scheme = []; | ||
var start, end, separation; | ||
switch (method) { | ||
case 'hsv': | ||
case 'hsva': | ||
var hsv = color.to('hsv', { round: false }); | ||
var startV = hsv.v; | ||
var endV = startV + (100 - startV) * Math.min(Math.max(distanceToWhite, 0), 1); | ||
var separationV = (endV - startV) / (colors - 1); | ||
var startVS = hsv.s; | ||
var endVS = (1 - distanceToWhite) * 100; | ||
var separationVS = (endVS - startVS) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextV = Math.min(startV + separationV * i, 100); | ||
var nextS = Math.min(startVS + separationVS * i, 100); | ||
scheme.push(new Colors.hsv(hsv.h, nextS, nextV).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'hsi': | ||
case 'hsia': | ||
var hsi = color.to('hsi', { round: false }); | ||
start = hsi.i; | ||
end = start + (100 - start) * Math.min(Math.max(distanceToWhite, 0), 1); | ||
separation = (end - start) / (colors - 1); | ||
var endIS = (1 - distanceToWhite) * 100; | ||
var separationIS = (endIS - hsi.s) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextI = Math.min(start + separation * i, 100); | ||
var nextS = Math.min(hsi.s + separationIS * i, 100); | ||
scheme.push(new Colors.hsi(hsi.h, nextS, nextI).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'hsp': | ||
case 'hspa': | ||
var hsp = color.to('hsp', { round: false }); | ||
start = hsp.p; | ||
end = start + (100 - start) * Math.min(Math.max(distanceToWhite, 0), 1); | ||
separation = (end - start) / (colors - 1); | ||
var endPS = (1 - distanceToWhite) * 100; | ||
var separationPS = (endPS - hsp.s) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextP = Math.min(start + separation * i, 100); | ||
var nextS = Math.min(hsp.s + separationPS * i, 100); | ||
scheme.push(new Colors.hsp(hsp.h, nextS, nextP).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'hsl': | ||
case 'hsla': | ||
var hsl = color.to('hsl', { round: false }); | ||
start = hsl.l; | ||
end = start + (100 - start) * Math.min(Math.max(distanceToWhite, 0), 1); | ||
separation = (end - start) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextL = Math.min(start + separation * i, 100); | ||
scheme.push(new Colors.hsl(hsl.h, hsl.s, nextL).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'rgb': | ||
case 'rgba': | ||
var rgb = color.to('rgb', { round: false }); | ||
start = Math.min(rgb.r, rgb.g, rgb.b); | ||
end = | ||
start + (rgb.max - start) * Math.min(Math.max(distanceToWhite, 0), 1); | ||
separation = (end - start) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var rNext = Math.min(rgb.r + separation * i, rgb.max); | ||
var gNext = Math.min(rgb.g + separation * i, rgb.max); | ||
var bNext = Math.min(rgb.b + separation * i, rgb.max); | ||
scheme.push(new Colors.rgb(rNext, gNext, bNext, rgb.a).to(color.constructor.name, { round: round, bitDepth: rgb.bitDepth })); | ||
} | ||
break; | ||
case 'rgb2': | ||
case 'rgba2': | ||
var rgb2 = color.to('rgb', { round: false }); | ||
var rEnd = rgb2.r + | ||
(rgb2.max - rgb2.r) * Math.min(Math.max(distanceToWhite, 0), 1); | ||
var gEnd = rgb2.g + | ||
(rgb2.max - rgb2.g) * Math.min(Math.max(distanceToWhite, 0), 1); | ||
var bEnd = rgb2.b + | ||
(rgb2.max - rgb2.b) * Math.min(Math.max(distanceToWhite, 0), 1); | ||
var rSep = (rEnd - rgb2.r) / (colors - 1); | ||
var gSep = (gEnd - rgb2.g) / (colors - 1); | ||
var bSep = (bEnd - rgb2.b) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var rNext = Math.min(rgb2.r + rSep * i, rgb2.max); | ||
var gNext = Math.min(rgb2.g + gSep * i, rgb2.max); | ||
var bNext = Math.min(rgb2.b + bSep * i, rgb2.max); | ||
scheme.push(new Colors.rgb(rNext, gNext, bNext, rgb2.a).to(color.constructor.name, { round: round, bitDepth: rgb2.bitDepth })); | ||
} | ||
break; | ||
case 'cmyk': | ||
var cmyk = color.to('cmyk', { round: false }); | ||
// reverse algorithm, max "white" is all values = 0 | ||
var cEnd = cmyk.c * (1 - Math.min(Math.max(distanceToWhite, 0), 1)); | ||
var mEnd = cmyk.m * (1 - Math.min(Math.max(distanceToWhite, 0), 1)); | ||
var yEnd = cmyk.y * (1 - Math.min(Math.max(distanceToWhite, 0), 1)); | ||
var kEnd = cmyk.k * (1 - Math.min(Math.max(distanceToWhite, 0), 1)); | ||
var cSep = (cmyk.c - cEnd) / (colors - 1); | ||
var mSep = (cmyk.m - mEnd) / (colors - 1); | ||
var ySep = (cmyk.y - yEnd) / (colors - 1); | ||
var kSep = (cmyk.k - kEnd) / (colors - 1); | ||
for (var i = 0; i < colors; i++) { | ||
var nextC = Math.max(cmyk.c - cSep * i, 0); | ||
var nextM = Math.max(cmyk.m - mSep * i, 0); | ||
var nextY = Math.max(cmyk.y - ySep * i, 0); | ||
var nextK = Math.max(cmyk.k - kSep * i, 0); | ||
scheme.push(new Colors.cmyk(nextC, nextM, nextY, nextK).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
default: | ||
throw new Error('Invalid method for generating color scheme'); | ||
} | ||
return hsls; | ||
return scheme; | ||
}; | ||
@@ -173,52 +395,395 @@ /** | ||
* | ||
* @param {Colors.hsl} hsl | ||
* @param {number} colors | ||
* @param {number} [distance=1] 0-1, where 1 is all the way to closest bound OR white, if distanceShade given | ||
* @param {number} [distanceShade=1] 0-1, where 1 is all the way to black | ||
* @param {T extends colorType} color | ||
* @param {string} method | ||
* @param {number} colors | ||
* @param {boolean} [round=true] | ||
* @param {number} [distance=1] 0-1, where 1 is all the way to closest bound OR white, if distanceShade given | ||
* @param {number} [distanceShade=1] 0-1, where 1 is all the way to black | ||
* @returns | ||
*/ | ||
Harmony.shadetint = function (hsl, colors, distance, distanceShade) { | ||
Harmony.shadetint = function (color, method, colors, round, distance, distanceShade) { | ||
if (round === void 0) { round = true; } | ||
if (distance === void 0) { distance = 1; } | ||
var hsls = []; | ||
var scheme = []; | ||
var tEnd, sEnd, tSeparation, sSeparation; | ||
if (typeof distanceShade === 'undefined') { | ||
if (100 - hsl.l < hsl.l) { | ||
tEnd = hsl.l + (100 - hsl.l) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - hsl.l) / colors; | ||
sSeparation = tSeparation; | ||
sEnd = hsl.l - sSeparation * colors; | ||
} | ||
else { | ||
sEnd = hsl.l * (1 - Math.min(Math.max(distance, 0), 1)); | ||
sSeparation = (hsl.l - sEnd) / colors; | ||
tSeparation = sSeparation; | ||
tEnd = hsl.l + tSeparation * colors; | ||
} | ||
switch (method) { | ||
case 'hsl': | ||
case 'hsla': | ||
var hsl = color.to('hsl', { round: false }); | ||
if (typeof distanceShade === 'undefined') { | ||
if (100 - hsl.l < hsl.l) { | ||
tEnd = hsl.l + (100 - hsl.l) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - hsl.l) / colors; | ||
sSeparation = tSeparation; | ||
sEnd = hsl.l - sSeparation * colors; | ||
} | ||
else { | ||
sEnd = hsl.l * (1 - Math.min(Math.max(distance, 0), 1)); | ||
sSeparation = (hsl.l - sEnd) / colors; | ||
tSeparation = sSeparation; | ||
tEnd = hsl.l + tSeparation * colors; | ||
} | ||
} | ||
else { | ||
tEnd = hsl.l + (100 - hsl.l) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - hsl.l) / colors; | ||
sEnd = hsl.l * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
sSeparation = (hsl.l - sEnd) / colors; | ||
} | ||
for (var i = 0; i < colors; i++) { | ||
var nextL = Math.max(sEnd + sSeparation * i, 0); | ||
scheme.push(new Colors.hsl(hsl.h, hsl.s, nextL, hsl.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
scheme.push(hsl.to(color.constructor.name, { round: round })); | ||
for (var i = 1; i <= colors; i++) { | ||
var nextL = Math.min(hsl.l + tSeparation * i, 100); | ||
scheme.push(new Colors.hsl(hsl.h, hsl.s, nextL, hsl.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'hsv': | ||
case 'hsva': | ||
var hsv = color.to('hsv', { round: false }); | ||
var separationTVS = void 0; | ||
var endTVS = (1 - distance) * 100; | ||
if (typeof distanceShade === 'undefined') { | ||
var distanceFromWhite = 100 - hsv.v + hsv.s; | ||
if (distanceFromWhite < 100) { | ||
// closer to white | ||
tEnd = hsv.v + (100 - hsv.v) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - hsv.v) / colors; | ||
separationTVS = (endTVS - hsv.s) / colors; | ||
sSeparation = tSeparation - separationTVS; | ||
sEnd = hsv.v - sSeparation * colors; | ||
} | ||
else { | ||
// closer to black | ||
sEnd = hsv.v * (1 - Math.min(Math.max(distance, 0), 1)); | ||
sSeparation = (hsv.v - sEnd) / colors; | ||
tEnd = hsv.v + sSeparation * (colors - 1); | ||
separationTVS = (-1 * Math.abs(hsv.s - tEnd)) / colors; | ||
// tint spacing should take saturation into account? | ||
tSeparation = sSeparation + separationTVS; | ||
} | ||
} | ||
else { | ||
tEnd = hsv.v + (100 - hsv.v) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - hsv.v) / colors; | ||
sEnd = hsv.v * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
sSeparation = (hsv.v - sEnd) / colors; | ||
separationTVS = (endTVS - hsv.s) / colors; | ||
} | ||
for (var i = 0; i < colors; i++) { | ||
var nextV = Math.min(Math.max(sEnd + sSeparation * i, 0), 100); | ||
scheme.push(new Colors.hsv(hsv.h, hsv.s, nextV, hsv.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
for (var i = 0; i <= colors; i++) { | ||
var nextV = Math.max(Math.min(hsv.v + tSeparation * i, 100), 0); | ||
var nextTVS = Math.min(Math.max(hsv.s + separationTVS * i, 0), 100); | ||
scheme.push(new Colors.hsv(hsv.h, nextTVS, nextV, hsv.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'hsi': | ||
case 'hsia': | ||
var hsi = color.to('hsi', { round: false }); | ||
var separationTIS = void 0; | ||
var endTIS = (1 - distance) * 100; | ||
if (typeof distanceShade === 'undefined') { | ||
var distanceFromWhite = 100 - hsi.i + hsi.s; | ||
if (distanceFromWhite < 100) { | ||
// closer to white | ||
tEnd = hsi.i + (100 - hsi.i) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - hsi.i) / colors; | ||
sSeparation = tSeparation; | ||
sEnd = hsi.i - sSeparation * colors; | ||
separationTIS = (endTIS - hsi.s) / colors; | ||
} | ||
else { | ||
// closer to black | ||
sEnd = hsi.i * (1 - Math.min(Math.max(distance, 0), 1)); | ||
sSeparation = (hsi.i - sEnd) / colors; | ||
tSeparation = sSeparation; | ||
tEnd = hsi.i + tSeparation * (colors - 1); | ||
separationTIS = (-1 * Math.abs(hsi.s - tEnd)) / colors; | ||
} | ||
} | ||
else { | ||
tEnd = hsi.i + (100 - hsi.i) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - hsi.i) / colors; | ||
sEnd = hsi.i * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
sSeparation = (hsi.i - sEnd) / colors; | ||
separationTIS = (endTIS - hsi.s) / colors; | ||
} | ||
for (var i = 0; i < colors; i++) { | ||
var nextI = Math.max(sEnd + sSeparation * i, 0); | ||
scheme.push(new Colors.hsi(hsi.h, hsi.s, nextI, hsi.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
scheme.push(hsi.to(color.constructor.name, { round: round })); | ||
for (var i = 1; i <= colors; i++) { | ||
var nextI = Math.min(hsi.i + tSeparation * i, 100); | ||
var nextTIS = Math.max(hsi.s + separationTIS * i, 0); | ||
scheme.push(new Colors.hsi(hsi.h, nextTIS, nextI, hsi.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'hsp': | ||
case 'hspa': | ||
var hsp = color.to('hsp', { round: false }); | ||
var separationTPS = void 0; | ||
var endTPS = (1 - distance) * 100; | ||
if (typeof distanceShade === 'undefined') { | ||
if (100 - hsp.p < hsp.p) { | ||
// closer to white | ||
tEnd = hsp.p + (100 - hsp.p) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - hsp.p) / colors; | ||
sSeparation = tSeparation; | ||
sEnd = hsp.p - sSeparation * colors; | ||
separationTPS = (endTPS - hsp.s) / colors; | ||
} | ||
else { | ||
// closer to black | ||
sEnd = hsp.p * (1 - Math.min(Math.max(distance, 0), 1)); | ||
sSeparation = (hsp.p - sEnd) / colors; | ||
tSeparation = sSeparation; | ||
tEnd = hsp.p + tSeparation * colors; | ||
separationTPS = (-1 * Math.abs(hsp.s - tEnd)) / colors; | ||
} | ||
} | ||
else { | ||
tEnd = hsp.p + (100 - hsp.p) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - hsp.p) / colors; | ||
sEnd = hsp.p * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
sSeparation = (hsp.p - sEnd) / colors; | ||
separationTPS = (endTPS - hsp.s) / colors; | ||
} | ||
for (var i = 0; i < colors; i++) { | ||
var nextP = Math.max(sEnd + sSeparation * i, 0); | ||
scheme.push(new Colors.hsp(hsp.h, hsp.s, nextP, hsp.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
for (var i = 0; i <= colors; i++) { | ||
var nextP = Math.min(hsp.p + tSeparation * i, 100); | ||
var nextTPS = Math.max(hsp.s + separationTPS * i, 0); | ||
scheme.push(new Colors.hsp(hsp.h, nextTPS, nextP, hsp.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'rgb': | ||
case 'rgba': | ||
var rgb = color.to('rgb', { round: false }); | ||
var maxVal = Math.max(rgb.r, rgb.g, rgb.b); | ||
var minVal = Math.min(rgb.r, rgb.g, rgb.b); | ||
if (typeof distanceShade === 'undefined') { | ||
if (rgb.max - minVal < maxVal) { | ||
tEnd = | ||
minVal + (rgb.max - minVal) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - minVal) / colors; | ||
sSeparation = tSeparation; | ||
sEnd = minVal - sSeparation * colors; | ||
} | ||
else { | ||
sEnd = maxVal * (1 - Math.min(Math.max(distance, 0), 1)); | ||
sSeparation = (maxVal - sEnd) / colors; | ||
tSeparation = sSeparation; | ||
tEnd = maxVal + tSeparation * colors; | ||
} | ||
} | ||
else { | ||
tEnd = | ||
minVal + (rgb.max - minVal) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - minVal) / colors; | ||
sEnd = maxVal * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
sSeparation = (maxVal - sEnd) / colors; | ||
} | ||
for (var i = 1; i <= colors; i++) { | ||
var rNext = Math.max(rgb.r - sSeparation * i, 0); | ||
var gNext = Math.max(rgb.g - sSeparation * i, 0); | ||
var bNext = Math.max(rgb.b - sSeparation * i, 0); | ||
scheme.unshift(new Colors.rgb(rNext, gNext, bNext, rgb.a).to(color.constructor.name, { round: round, bitDepth: rgb.bitDepth })); | ||
} | ||
scheme.push(rgb.to(color.constructor.name, { round: round })); | ||
for (var i = 1; i <= colors; i++) { | ||
var rNext = Math.min(rgb.r + tSeparation * i, rgb.max); | ||
var gNext = Math.min(rgb.g + tSeparation * i, rgb.max); | ||
var bNext = Math.min(rgb.b + tSeparation * i, rgb.max); | ||
scheme.push(new Colors.rgb(rNext, gNext, bNext, rgb.a).to(color.constructor.name, { round: round, bitDepth: rgb.bitDepth })); | ||
} | ||
break; | ||
case 'rgb2': | ||
case 'rgba2': | ||
var rgb2 = color.to('rgb', { round: false }); | ||
var tREnd = void 0, tGEnd = void 0, tBEnd = void 0, sREnd = void 0, sGEnd = void 0, sBEnd = void 0, tRSep = void 0, tGSep = void 0, tBSep = void 0, sRSep = void 0, sGSep = void 0, sBSep = void 0; | ||
if (typeof distanceShade === 'undefined') { | ||
var percentDistanceToWhite = (rgb2.max * 3 - rgb2.r - rgb2.g - rgb2.b) / (rgb2.max * 3); | ||
if (percentDistanceToWhite < 0.5) { | ||
tREnd = rgb2.r + (rgb2.max - rgb2.r) * Math.min(Math.max(distance, 0), 1); | ||
tRSep = (tREnd - rgb2.r) / colors; | ||
sREnd = rgb2.r * percentDistanceToWhite; | ||
sRSep = (rgb2.r - sREnd) / colors; | ||
tGEnd = rgb2.g + (rgb2.max - rgb2.g) * Math.min(Math.max(distance, 0), 1); | ||
tGSep = (tGEnd - rgb2.g) / colors; | ||
sGEnd = rgb2.g * percentDistanceToWhite; | ||
sGSep = (rgb2.g - sGEnd) / colors; | ||
tBEnd = rgb2.b + (rgb2.max - rgb2.b) * Math.min(Math.max(distance, 0), 1); | ||
tBSep = (tBEnd - rgb2.b) / colors; | ||
sBEnd = rgb2.b * percentDistanceToWhite; | ||
sBSep = (rgb2.b - sBEnd) / colors; | ||
} | ||
else { | ||
sREnd = rgb2.r * (1 - Math.min(Math.max(distance, 0), 1)); | ||
sRSep = (rgb2.r - sREnd) / colors; | ||
tREnd = rgb2.r * (1 + ((rgb2.max - rgb2.r) / rgb2.max)); | ||
tRSep = (tREnd - rgb2.r) / colors; | ||
sGEnd = rgb2.g * (1 - Math.min(Math.max(distance, 0), 1)); | ||
sGSep = (rgb2.g - sGEnd) / colors; | ||
tGEnd = rgb2.g * (1 + ((rgb2.max - rgb2.g) / rgb2.max)); | ||
tGSep = (tGEnd - rgb2.g) / colors; | ||
sBEnd = rgb2.b * (1 - Math.min(Math.max(distance, 0), 1)); | ||
sBSep = (rgb2.b - sBEnd) / colors; | ||
tBEnd = rgb2.b * (1 + ((rgb2.max - rgb2.b) / rgb2.max)); | ||
tBSep = (tBEnd - rgb2.b) / colors; | ||
} | ||
} | ||
else { | ||
tREnd = rgb2.r + (rgb2.max - rgb2.r) * Math.min(Math.max(distance, 0), 1); | ||
tRSep = (tREnd - rgb2.r) / colors; | ||
sREnd = rgb2.r * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
sRSep = (rgb2.r - sREnd) / colors; | ||
tGEnd = rgb2.g + (rgb2.max - rgb2.g) * Math.min(Math.max(distance, 0), 1); | ||
tGSep = (tGEnd - rgb2.g) / colors; | ||
sGEnd = rgb2.g * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
sGSep = (rgb2.g - sGEnd) / colors; | ||
tBEnd = rgb2.b + (rgb2.max - rgb2.b) * Math.min(Math.max(distance, 0), 1); | ||
tBSep = (tBEnd - rgb2.b) / colors; | ||
sBEnd = rgb2.b * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
sBSep = (rgb2.b - sBEnd) / colors; | ||
} | ||
for (var i = 0; i < colors; i++) { | ||
var rNext = Math.min(Math.max(sREnd + sRSep * i, 0), rgb2.max); | ||
var gNext = Math.min(Math.max(sGEnd + sGSep * i, 0), rgb2.max); | ||
var bNext = Math.min(Math.max(sBEnd + sBSep * i, 0), rgb2.max); | ||
scheme.push(new Colors.rgb(rNext, gNext, bNext, rgb2.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
for (var i = 0; i <= colors; i++) { | ||
var rNext = Math.min(Math.max(rgb2.r + tRSep * i, 0), rgb2.max); | ||
var gNext = Math.min(Math.max(rgb2.g + tGSep * i, 0), rgb2.max); | ||
var bNext = Math.min(Math.max(rgb2.b + tBSep * i, 0), rgb2.max); | ||
scheme.push(new Colors.rgb(rNext, gNext, bNext, rgb2.a).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
case 'cmyk': | ||
var cmyk = color.to('cmyk', { round: false }); | ||
var tCEnd = void 0, tMEnd = void 0, tYEnd = void 0, tKEnd = void 0, sCEnd = void 0, sMEnd = void 0, sYEnd = void 0, sKEnd = void 0, tCSep = void 0, tMSep = void 0, tYSep = void 0, tKSep = void 0, sCSep = void 0, sMSep = void 0, sYSep = void 0, sKSep = void 0; | ||
if (typeof distanceShade === 'undefined') { | ||
var percentDistanceToWhite = (cmyk.c + cmyk.m + cmyk.y + cmyk.k) / 400; | ||
// not sure how to calculate when to go up or down with cmyk, so using rgb | ||
var rgb_1 = cmyk.to('rgb'); | ||
var perceivedDistanceToWhite = (rgb_1.max * 3 - rgb_1.r - rgb_1.g - rgb_1.b) / (rgb_1.max * 3); | ||
if (perceivedDistanceToWhite > 0.5) { | ||
// closer to black | ||
sCEnd = cmyk.c + (100 - cmyk.c) * Math.min(Math.max(distance, 0), 1); | ||
sCSep = (sCEnd - cmyk.c) / colors; | ||
tCEnd = cmyk.c * percentDistanceToWhite; | ||
tCSep = (cmyk.c - tCEnd) / colors; | ||
sMEnd = cmyk.m + (100 - cmyk.m) * Math.min(Math.max(distance, 0), 1); | ||
sMSep = (sMEnd - cmyk.m) / colors; | ||
tMEnd = cmyk.m * percentDistanceToWhite; | ||
tMSep = (cmyk.m - tMEnd) / colors; | ||
sYEnd = cmyk.y + (100 - cmyk.y) * Math.min(Math.max(distance, 0), 1); | ||
sYSep = (sYEnd - cmyk.y) / colors; | ||
tYEnd = cmyk.y * percentDistanceToWhite; | ||
tYSep = (cmyk.y - tYEnd) / colors; | ||
sKEnd = cmyk.k + (100 - cmyk.k) * Math.min(Math.max(distance, 0), 1); | ||
sKSep = (sKEnd - cmyk.k) / colors; | ||
tKEnd = cmyk.k * percentDistanceToWhite; | ||
tKSep = (cmyk.k - tKEnd) / colors; | ||
} | ||
else { | ||
// closer to white | ||
tCEnd = cmyk.c * (1 - Math.min(Math.max(distance, 0), 1)); | ||
tCSep = (cmyk.c - tCEnd) / colors; | ||
sCEnd = cmyk.c * (1 + ((100 - cmyk.c) / 100)); | ||
sCSep = (sCEnd - cmyk.c) / colors; | ||
tMEnd = cmyk.m * (1 - Math.min(Math.max(distance, 0), 1)); | ||
tMSep = (cmyk.m - tMEnd) / colors; | ||
sMEnd = cmyk.m * (1 + ((100 - cmyk.m) / 100)); | ||
sMSep = (sMEnd - cmyk.m) / colors; | ||
tYEnd = cmyk.y * (1 - Math.min(Math.max(distance, 0), 1)); | ||
tYSep = (cmyk.y - tYEnd) / colors; | ||
sYEnd = cmyk.y * (1 + ((100 - cmyk.y) / 100)); | ||
sYSep = (sYEnd - cmyk.y) / colors; | ||
tKEnd = cmyk.k * (1 - Math.min(Math.max(distance, 0), 1)); | ||
tKSep = (cmyk.k - tKEnd) / colors; | ||
sKEnd = cmyk.k * (1 + ((100 - cmyk.k) / 100)); | ||
sKSep = (sKEnd - cmyk.k) / colors; | ||
} | ||
} | ||
else { | ||
sCEnd = cmyk.c + (100 - cmyk.c) * Math.min(Math.max(distance, 0), 1); | ||
sCSep = (sCEnd - cmyk.c) / colors; | ||
tCEnd = cmyk.c * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
tCSep = (cmyk.c - tCEnd) / colors; | ||
sMEnd = cmyk.m + (100 - cmyk.m) * Math.min(Math.max(distance, 0), 1); | ||
sMSep = (sMEnd - cmyk.m) / colors; | ||
tMEnd = cmyk.m * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
tMSep = (cmyk.m - tMEnd) / colors; | ||
sYEnd = cmyk.y + (100 - cmyk.y) * Math.min(Math.max(distance, 0), 1); | ||
sYSep = (sYEnd - cmyk.y) / colors; | ||
tYEnd = cmyk.y * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
tYSep = (cmyk.y - tYEnd) / colors; | ||
sKEnd = cmyk.k + (100 - cmyk.k) * Math.min(Math.max(distance, 0), 1); | ||
sKSep = (sKEnd - cmyk.k) / colors; | ||
tKEnd = cmyk.k * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
tKSep = (cmyk.k - tKEnd) / colors; | ||
} | ||
for (var i = 0; i < colors; i++) { | ||
var cNext = Math.min(Math.max(sCEnd - sCSep * i, 0), 100); | ||
var mNext = Math.min(Math.max(sMEnd - sMSep * i, 0), 100); | ||
var yNext = Math.min(Math.max(sYEnd - sYSep * i, 0), 100); | ||
var kNext = Math.min(Math.max(sKEnd - sKSep * i, 0), 100); | ||
scheme.push(new Colors.cmyk(cNext, mNext, yNext, kNext).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
for (var i = 0; i <= colors; i++) { | ||
var cNext = Math.min(Math.max(cmyk.c - tCSep * i, 0), 100); | ||
var mNext = Math.min(Math.max(cmyk.m - tMSep * i, 0), 100); | ||
var yNext = Math.min(Math.max(cmyk.y - tYSep * i, 0), 100); | ||
var kNext = Math.min(Math.max(cmyk.k - tKSep * i, 0), 100); | ||
scheme.push(new Colors.cmyk(cNext, mNext, yNext, kNext).to(color.constructor.name, { | ||
round: round, | ||
})); | ||
} | ||
break; | ||
default: | ||
throw new Error('Invalid method for generating color scheme'); | ||
} | ||
else { | ||
tEnd = hsl.l + (100 - hsl.l) * Math.min(Math.max(distance, 0), 1); | ||
tSeparation = (tEnd - hsl.l) / colors; | ||
sEnd = hsl.l * (1 - Math.min(Math.max(distanceShade, 0), 1)); | ||
sSeparation = (hsl.l - sEnd) / colors; | ||
} | ||
for (var i = 0; i < colors; i++) { | ||
var nextL = Math.max(sEnd + sSeparation * i, 0); | ||
hsls.push(new Colors.hsl(hsl.h, hsl.s, nextL)); | ||
} | ||
hsls.push(hsl); | ||
for (var i = 1; i <= colors; i++) { | ||
var nextL = Math.min(hsl.l + tSeparation * i, 100); | ||
hsls.push(new Colors.hsl(hsl.h, hsl.s, nextL)); | ||
} | ||
return hsls; | ||
return scheme; | ||
}; | ||
/** | ||
* Return an array of colors blended from color1 to color2, via rgb | ||
* Return an array of colors blended from color1 to color2 | ||
* | ||
* @param {Colors.rgb} color1 | ||
* @param {Colors.rgb} color2 | ||
* @param {number} colors number of colors in scheme (including color1 and color2) | ||
* @returns | ||
* @param {T extends colorType} color1 | ||
* @param {T extends colorType} color2 | ||
* @param {number} colors number of colors in scheme (including color1 and color2) | ||
* @returns {T[]} | ||
*/ | ||
Harmony.rgbGradient = function (color1, color2, colors) { | ||
Harmony.gradient = function (type, color1, color2, colors, round) { | ||
if (round === void 0) { round = true; } | ||
if (colors < 2) { | ||
@@ -232,3 +797,30 @@ throw new Error('Unable to generate gradient with less than two colors'); | ||
var amount = (i + 1) / (inBetweenColors + 1); | ||
gradient.push(Modify_1.default.rgbBlend(color1, color2, amount, false)); | ||
switch (type) { | ||
case 'rgb': | ||
case 'rgba': | ||
gradient.push(Modify_1.default.rgbBlend(color1.to('rgb', { round: false }), color2.to('rgb', { round: false }), amount, false).to(color1.constructor.name, { round: round })); | ||
break; | ||
case 'hsv': | ||
case 'hsva': | ||
gradient.push(Modify_1.default.hsvBlend(color1.to('hsv', { round: false }), color2.to('hsv', { round: false }), amount, false).to(color1.constructor.name, { round: round })); | ||
break; | ||
case 'hsl': | ||
case 'hsla': | ||
gradient.push(Modify_1.default.hslBlend(color1.to('hsl', { round: false }), color2.to('hsl', { round: false }), amount, false).to(color1.constructor.name, { round: round })); | ||
break; | ||
case 'hsi': | ||
case 'hsia': | ||
gradient.push(Modify_1.default.hsiBlend(color1.to('hsi', { round: false }), color2.to('hsi', { round: false }), amount, false).to(color1.constructor.name, { round: round })); | ||
break; | ||
case 'hsp': | ||
case 'hspa': | ||
gradient.push(Modify_1.default.hspBlend(color1.to('hsp', { round: false }), color2.to('hsp', { round: false }), amount, false).to(color1.constructor.name, { round: round })); | ||
break; | ||
case 'cmyk': | ||
gradient.push(Modify_1.default.cmykBlend(color1.to('cmyk', { round: false }), color2.to('cmyk', { round: false }), amount, false).to(color1.constructor.name, { round: round })); | ||
break; | ||
case 'yiq': | ||
gradient.push(Modify_1.default.yiqBlend(color1.to('yiq', { round: false }), color2.to('yiq', { round: false }), amount, false).to(color1.constructor.name, { round: round })); | ||
break; | ||
} | ||
} | ||
@@ -238,26 +830,4 @@ gradient.push(color2); | ||
}; | ||
/** | ||
* Return an array of colors blended from color1 to color2, via hsv | ||
* | ||
* @param {Colors.hsv} color1 | ||
* @param {Colors.hsv} color2 | ||
* @param {number} colors number of colors in scheme (including color1 and color2) | ||
* @returns | ||
*/ | ||
Harmony.hsvGradient = function (color1, color2, colors) { | ||
if (colors < 2) { | ||
throw new Error('Unable to generate gradient with less than two colors'); | ||
} | ||
var inBetweenColors = colors - 2; | ||
var gradient = []; | ||
gradient.push(color1); | ||
for (var i = 0; i < inBetweenColors; i++) { | ||
var amount = (i + 1) / (inBetweenColors + 1); | ||
gradient.push(Modify_1.default.hsvBlend(color1, color2, amount, false)); | ||
} | ||
gradient.push(color2); | ||
return gradient; | ||
}; | ||
return Harmony; | ||
}()); | ||
module.exports = Harmony; |
"use strict"; | ||
// chromaticity-color-utilities | ||
// Copyright (C) 2021 Emma Litwa-Vulcu | ||
// Copyright (C) 2022 Emma Litwa-Vulcu | ||
// | ||
@@ -5,0 +5,0 @@ // This program is free software: you can redistribute it and/or modify |
@@ -32,2 +32,54 @@ import * as Colors from './Colors'; | ||
static hsvBlend(hsv1: Colors.hsv, hsv2: Colors.hsv, amount?: number, round?: boolean): Colors.hsv; | ||
/** | ||
* Blend one HSL color with another | ||
* | ||
* @param {Colors.hsl} hsl1 | ||
* @param {Colors.hsl} hsl2 | ||
* @param {number} amount amount to blend (0-1) | ||
* @param {boolean} [round=true] | ||
* @return {Colors.hsl} | ||
*/ | ||
static hslBlend(hsl1: Colors.hsl, hsl2: Colors.hsl, amount?: number, round?: boolean): Colors.hsl; | ||
/** | ||
* Blend one HSI color with another | ||
* | ||
* @param {Colors.hsi} hsi1 | ||
* @param {Colors.hsi} hsi2 | ||
* @param {number} amount amount to blend (0-1) | ||
* @param {boolean} [round=true] | ||
* @return {Colors.hsi} | ||
*/ | ||
static hsiBlend(hsi1: Colors.hsi, hsi2: Colors.hsi, amount?: number, round?: boolean): Colors.hsi; | ||
/** | ||
* Blend one HSP color with another | ||
* | ||
* @param {Colors.hsp} hsp1 | ||
* @param {Colors.hsp} hsp2 | ||
* @param {number} amount amount to blend (0-1) | ||
* @param {boolean} [round=true] | ||
* @return {Colors.hsp} | ||
*/ | ||
static hspBlend(hsp1: Colors.hsp, hsp2: Colors.hsp, amount?: number, round?: boolean): Colors.hsp; | ||
/** | ||
* Blend one CMYK color with another | ||
* | ||
* @param {Colors.cmyk} cmyk1 | ||
* @param {Colors.cmyk} cmyk2 | ||
* @param {number} amount amount to blend (0-1) | ||
* @param {boolean} [round=true] | ||
* @return {Colors.cmyk} | ||
*/ | ||
static cmykBlend(cmyk1: Colors.cmyk, cmyk2: Colors.cmyk, amount?: number, round?: boolean): Colors.cmyk; | ||
/** | ||
* Blend one YIQ color with another | ||
* | ||
* @param {Colors.yiq} c1 | ||
* @param {Colors.yiq} c2 | ||
* @param {number} amount amount to blend (0-1) | ||
* @param {boolean} [round=true] | ||
* @return {Colors.yiq} | ||
*/ | ||
static yiqBlend(c1: Colors.yiq, c2: Colors.yiq, amount?: number, round?: boolean): Colors.yiq; | ||
static rgbDarken(rgb: Colors.rgb, amount?: number, round?: boolean): Colors.rgb; | ||
static rgbLighten(rgb: Colors.rgb, amount?: number, round?: boolean): Colors.rgb; | ||
static hslDarken(hsl: Colors.hsl, amount?: number, round?: boolean): Colors.hsl; | ||
@@ -34,0 +86,0 @@ static hslLighten(hsl: Colors.hsl, amount?: number, round?: boolean): Colors.hsl; |
"use strict"; | ||
// chromaticity-color-utilities | ||
// Copyright (C) 2021 Emma Litwa-Vulcu | ||
// Copyright (C) 2022 Emma Litwa-Vulcu | ||
// | ||
@@ -100,5 +100,3 @@ // This program is free software: you can redistribute it and/or modify | ||
if (Math.abs(hsv2.h - hsv1.h) > 180) { | ||
hueDiff = 360 - Math.abs((hsv2.h - hsv1.h) * amount); | ||
if (hsv1.h > hsv2.h) | ||
hueDiff *= -1; | ||
hueDiff = 360 - (hsv2.h - hsv1.h) * amount * -1; | ||
} | ||
@@ -120,2 +118,174 @@ else { | ||
}; | ||
/** | ||
* Blend one HSL color with another | ||
* | ||
* @param {Colors.hsl} hsl1 | ||
* @param {Colors.hsl} hsl2 | ||
* @param {number} amount amount to blend (0-1) | ||
* @param {boolean} [round=true] | ||
* @return {Colors.hsl} | ||
*/ | ||
Modify.hslBlend = function (hsl1, hsl2, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
amount = Math.min(Math.max(amount, 0), 1); | ||
var hueDiff; | ||
if (Math.abs(hsl2.h - hsl1.h) > 180) { | ||
hueDiff = 360 - (hsl2.h - hsl1.h) * amount * -1; | ||
} | ||
else { | ||
hueDiff = (hsl2.h - hsl1.h) * amount; | ||
} | ||
var h3 = this.hueShift(hsl1.h, hueDiff); | ||
var s3 = hsl1.s + (hsl2.s - hsl1.s) * amount; | ||
var l3 = hsl1.l + (hsl2.l - hsl1.l) * amount; | ||
var a3 = hsl1.a + (hsl2.a - hsl1.a) * amount; | ||
if (round) { | ||
h3 = Math.round(h3); | ||
s3 = Math.round(s3); | ||
l3 = Math.round(l3); | ||
a3 = Math.round(a3); | ||
} | ||
return new Colors.hsl(h3, s3, l3, a3); | ||
}; | ||
/** | ||
* Blend one HSI color with another | ||
* | ||
* @param {Colors.hsi} hsi1 | ||
* @param {Colors.hsi} hsi2 | ||
* @param {number} amount amount to blend (0-1) | ||
* @param {boolean} [round=true] | ||
* @return {Colors.hsi} | ||
*/ | ||
Modify.hsiBlend = function (hsi1, hsi2, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
amount = Math.min(Math.max(amount, 0), 1); | ||
var hueDiff; | ||
if (Math.abs(hsi2.h - hsi1.h) > 180) { | ||
hueDiff = 360 - (hsi2.h - hsi1.h) * amount * -1; | ||
} | ||
else { | ||
hueDiff = (hsi2.h - hsi1.h) * amount; | ||
} | ||
var h3 = this.hueShift(hsi1.h, hueDiff); | ||
var s3 = hsi1.s + (hsi2.s - hsi1.s) * amount; | ||
var i3 = hsi1.i + (hsi2.i - hsi1.i) * amount; | ||
var a3 = hsi1.a + (hsi2.a - hsi1.a) * amount; | ||
if (round) { | ||
h3 = Math.round(h3); | ||
s3 = Math.round(s3); | ||
i3 = Math.round(i3); | ||
a3 = Math.round(a3); | ||
} | ||
return new Colors.hsi(h3, s3, i3, a3); | ||
}; | ||
/** | ||
* Blend one HSP color with another | ||
* | ||
* @param {Colors.hsp} hsp1 | ||
* @param {Colors.hsp} hsp2 | ||
* @param {number} amount amount to blend (0-1) | ||
* @param {boolean} [round=true] | ||
* @return {Colors.hsp} | ||
*/ | ||
Modify.hspBlend = function (hsp1, hsp2, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
amount = Math.min(Math.max(amount, 0), 1); | ||
var hueDiff; | ||
if (Math.abs(hsp2.h - hsp1.h) > 180) { | ||
hueDiff = 360 - (hsp2.h - hsp1.h) * amount * -1; | ||
} | ||
else { | ||
hueDiff = (hsp2.h - hsp1.h) * amount; | ||
} | ||
var h3 = this.hueShift(hsp1.h, hueDiff); | ||
var s3 = hsp1.s + (hsp2.s - hsp1.s) * amount; | ||
var p3 = hsp1.p + (hsp2.p - hsp1.p) * amount; | ||
var a3 = hsp1.a + (hsp2.a - hsp1.a) * amount; | ||
if (round) { | ||
h3 = Math.round(h3); | ||
s3 = Math.round(s3); | ||
p3 = Math.round(p3); | ||
a3 = Math.round(a3); | ||
} | ||
return new Colors.hsp(h3, s3, p3, a3); | ||
}; | ||
/** | ||
* Blend one CMYK color with another | ||
* | ||
* @param {Colors.cmyk} cmyk1 | ||
* @param {Colors.cmyk} cmyk2 | ||
* @param {number} amount amount to blend (0-1) | ||
* @param {boolean} [round=true] | ||
* @return {Colors.cmyk} | ||
*/ | ||
Modify.cmykBlend = function (cmyk1, cmyk2, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
amount = Math.min(Math.max(amount, 0), 1); | ||
var c3 = cmyk1.c + (cmyk2.c - cmyk1.c) * amount; | ||
var m3 = cmyk1.m + (cmyk2.m - cmyk1.m) * amount; | ||
var y3 = cmyk1.y + (cmyk2.y - cmyk1.y) * amount; | ||
var k3 = cmyk1.k + (cmyk2.k - cmyk1.k) * amount; | ||
if (round) { | ||
c3 = Math.round(c3); | ||
m3 = Math.round(m3); | ||
y3 = Math.round(y3); | ||
k3 = Math.round(k3); | ||
} | ||
return new Colors.cmyk(c3, m3, y3, k3); | ||
}; | ||
/** | ||
* Blend one YIQ color with another | ||
* | ||
* @param {Colors.yiq} c1 | ||
* @param {Colors.yiq} c2 | ||
* @param {number} amount amount to blend (0-1) | ||
* @param {boolean} [round=true] | ||
* @return {Colors.yiq} | ||
*/ | ||
Modify.yiqBlend = function (c1, c2, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
amount = Math.min(Math.max(amount, 0), 1); | ||
var y = c1.y + (c2.y - c1.y) * amount; | ||
var i = c1.i + (c2.i - c1.i) * amount; | ||
var q = c1.q + (c2.q - c1.q) * amount; | ||
if (round) { | ||
y = Math.round(y); | ||
i = Math.round(i); | ||
q = Math.round(q); | ||
} | ||
return new Colors.yiq(y, i, q); | ||
}; | ||
Modify.rgbDarken = function (rgb, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
var realAmount = 1 - Math.min(Math.max(amount, 0), 1); | ||
var rd = rgb.r * realAmount; | ||
var gd = rgb.g * realAmount; | ||
var bd = rgb.b * realAmount; | ||
if (round) { | ||
rd = Math.round(rd); | ||
gd = Math.round(gd); | ||
bd = Math.round(bd); | ||
} | ||
return new Colors.rgb(rd, gd, bd, rgb.a); | ||
}; | ||
Modify.rgbLighten = function (rgb, amount, round) { | ||
if (amount === void 0) { amount = 0.5; } | ||
if (round === void 0) { round = true; } | ||
var realAmount = 1 - Math.min(Math.max(amount, 0), 1); | ||
var rl = rgb.r + (100 - rgb.r) * realAmount; | ||
var gl = rgb.g + (100 - rgb.g) * realAmount; | ||
var bl = rgb.b + (100 - rgb.b) * realAmount; | ||
if (round) { | ||
rl = Math.round(rl); | ||
gl = Math.round(gl); | ||
bl = Math.round(bl); | ||
} | ||
return new Colors.rgb(rl, gl, bl, rgb.a); | ||
}; | ||
Modify.hslDarken = function (hsl, amount, round) { | ||
@@ -122,0 +292,0 @@ if (amount === void 0) { amount = 0.5; } |
"use strict"; | ||
// chromaticity-color-utilities | ||
// Copyright (C) 2021 Emma Litwa-Vulcu | ||
// Copyright (C) 2022 Emma Litwa-Vulcu | ||
// | ||
@@ -5,0 +5,0 @@ // This program is free software: you can redistribute it and/or modify |
"use strict"; | ||
// chromaticity-color-utilities | ||
// Copyright (C) 2021 Emma Litwa-Vulcu | ||
// Copyright (C) 2022 Emma Litwa-Vulcu | ||
// | ||
@@ -240,28 +240,3 @@ // This program is free software: you can redistribute it and/or modify | ||
Util.fmod = function (x, y) { | ||
var p = 0; | ||
var pY = 0; | ||
var l = 0.0; | ||
var l2 = 0.0; | ||
var tmp; | ||
tmp = x.toExponential().match(/^.\.?(.*)e(.+)$/); | ||
if (tmp == null) | ||
throw new Error('value is null'); | ||
p = parseInt(tmp[2], 10) - (tmp[1] + '').length; | ||
tmp = y.toExponential().match(/^.\.?(.*)e(.+)$/); | ||
if (tmp == null) | ||
throw new Error('value is null'); | ||
pY = parseInt(tmp[2], 10) - (tmp[1] + '').length; | ||
if (pY > p) { | ||
p = pY; | ||
} | ||
var tmp2 = x % y; | ||
if (p < -100 || p > 20) { | ||
// toFixed will give an out of bound error so we fix it like this: | ||
l = Math.round(Math.log(tmp2) / Math.log(10)); | ||
l2 = Math.pow(10, l); | ||
return parseFloat((tmp2 / l2).toFixed(l - p)) * l2; | ||
} | ||
else { | ||
return parseFloat(tmp2.toFixed(-p)); | ||
} | ||
return Number((x - (Math.floor(x / y) * y)).toPrecision(8)); | ||
}; | ||
@@ -268,0 +243,0 @@ return Util; |
{ | ||
"name": "chromaticity-color-utilities", | ||
"version": "0.5.0-alpha", | ||
"version": "0.7.0-alpha", | ||
"description": "Color utilities for Node.js", | ||
"main": "dist/main.js", | ||
"scripts": { | ||
"test": "mocha" | ||
"test": "mocha", | ||
"servetest": "nodemon serverTest/app.js" | ||
}, | ||
@@ -9,0 +10,0 @@ "dependencies": {}, |
@@ -70,3 +70,2 @@ # <img src="https://reiniiriarios.github.io/chromaticity-color-utilities/assets/images/chromaticity-icon-01.png" width="26" height="26"> chromaticity-color-utilities | ||
- L\*u\*v\* failing | ||
- HSP > RGB failing in one case | ||
@@ -171,5 +170,6 @@ ## Documentation | ||
- note to self: rec709 does gamma conversion before while rec2020 does gamma conversion after when converting to ypbpr (I think) | ||
- Need way more comments and better variable names | ||
- Write more documentation wrt mathematics. | ||
- Integrate my references better. :) | ||
- Validate YIQ | ||
- For RGBA to CMYK, mix alpha with white | ||
- Support for 8-digit hex values (RRGGBBAA) |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
314893
7202