Skip to content

Commit 04d68ac

Browse files
committed
Updates to docs; make filter functions return original color space
1 parent 9473d10 commit 04d68ac

File tree

11 files changed

+103
-43
lines changed

11 files changed

+103
-43
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
![(culori logo)](./docs/img/culori.svg)
1+
![culori](./docs/img/culori.svg)
22

3-
culori is a color library for JavaScript that works across many color spaces to offer conversion, interpolation, color difference formulas, and blending functions.
3+
<a href="https://www.npmjs.org/package/culori"><img src="https://img.shields.io/npm/v/culori.svg?style=flat-square&labelColor=d84f4c&color=black" alt="npm version"></a> <a href="https://bundlephobia.com/result?p=culori"><img src="https://img.shields.io/bundlephobia/minzip/culori?style=flat-square&labelColor=d84f4c&color=black" alt="npm version"></a>
4+
5+
culori is a color library for JavaScript that works across many color spaces to offer conversion, interpolation, color difference formulas, blending functions, and more.
46

57
[**Read the documentation**](https://culorijs.org)

docs/_includes/layouts/default.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<html>
33
<head>
44
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width,initial-scale=1" />
56
<title>
67
{% if title %} {{ title }} &middot; culori {% else %} culori {%
78
endif %}

docs/_includes/partials/header.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<header>
22
<div class="container">
33
<div class="logo">
4-
<a href='{{"/" | url }}'>culori</a>
4+
<a href='{{"/" | url }}'>
5+
<img src='{{ "/img/culori.svg" | url }}' alt="culori" />
6+
</a>
57
<span
68
>v{{ pkg.version }} alpha (<a
79
href="https://github.com/evercoder/culori/releases"

docs/api.md

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -684,26 +684,12 @@ nearestNamedColors('lch(50% 70 60)', 3);
684684

685685
## Blending
686686

687-
Color blending works as defined in the W3C [Compositing and Blending Level 2](https://drafts.fxtf.org/compositing-2/) specification.
687+
Culori makes available the separable blend modes defined in the W3C [Compositing and Blending Level 2](https://drafts.fxtf.org/compositing-2/) specification.
688688

689689
<a name="blend" href="#blend">#</a> culori.**blend**(_colors_, _type = 'normal'_, _mode = 'rgb'_) → _color_ &middot; [Source](https://github.com/evercoder/culori/blob/master/src/blend.js)
690690

691-
Available blending modes:
692-
693-
- `normal`
694-
- `multiply`
695-
- `screen`
696-
- `hard-light`
697-
- `overlay`
698-
- `darken`
699-
- `lighten`
700-
- `color-dodge`
701-
- `color-burn`
702-
- `soft-light`
703-
- `difference`
704-
- `exclusion`
705-
706-
> **Note:** culori currently implements the _separable_ blend modes, that is the blend modes that work on each channel in the color space independently. _color_, _hue_, _saturation_, and _lightness_ modes are not yet available.
691+
A separable blend mode is a simple formula that gets applied to each channel in the color space independently. The available blend modes are `color-burn`, `color-dodge`, `darken`, `difference`, `exclusion`, `hard-light`, `lighten`, `multiply`, `normal`, `overlay`, `screen`
692+
, and `soft-light`. They are designed to work on RGB colors, so _mode_ is expected to be `rgb` or `lrgb`.
707693

708694
An example of blending three colors:
709695

@@ -723,6 +709,8 @@ culori.blend(['red', 'green'], function average(b, s) {
723709
});
724710
```
725711

712+
The non-separable blend modes — `color`, `hue`, `saturation`, and `lightness` — are not available. The effect which they mean to produce is better obtained with simple formulas on a cylindrical color space (e.g. HSL).
713+
726714
## Random colors
727715

728716
<a name="random" href="#random">#</a> culori.**random**(_mode = 'rgb'_, _constraints = {}_) &middot; [Source](https://github.com/evercoder/culori/blob/master/src/random.js)
@@ -790,14 +778,26 @@ culori.wcagContrast('red', 'black');
790778

791779
## Filters
792780

793-
### CSS filter effects
781+
Filters apply certain graphical effects to a color. Culori currently implements two sets of filter functions:
782+
783+
### CSS Filter Effects
784+
785+
These correspond to the filter effects defined in the W3C [Filter Effects Module Level 1](https://drafts.fxtf.org/filter-effects-1/) specification.
794786

795-
Culori implements some of the filter effects defined by the W3C [Filter Effects Module Level 1](https://drafts.fxtf.org/filter-effects-1/). The _amount_ parameter is usually in the `[0, 1]` interval, but may go above `1` for some filters. The filters were designed for RGB colors, so the _mode_ parameter is expected to be `rgb` or `lrgb`.
787+
The _amount_ parameter is usually in the `[0, 1]` interval, but may go above `1` for some filters. The filters were designed for RGB colors, so the _mode_ parameter is expected to be `rgb` or `lrgb`.
788+
789+
The resulting color is returned in the color space of the original color.
796790

797791
<a name="filterBrightness" href="#filterBrightness">#</a> culori.**filterBrightness**(_amount = 1_, _mode = 'rgb'_) &middot; [Source](https://github.com/evercoder/culori/blob/master/src/filter.js)
798792

799793
The [`brightness()`](https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/brightness) CSS filter. An _amount_ of `1` leaves the color unchanged. Smaller values darken the color (with `0` being fully black), while larger values brighten it.
800794

795+
```js
796+
let brighten = culori.filterBrightness(2, 'lrgb');
797+
brighten('salmon');
798+
// ⇒ { mode: 'rgb', r: 1.32…, g: 0.68…, b: 0.61… }
799+
```
800+
801801
<a name="filterContrast" href="#filterContrast">#</a> culori.**filterContrast**(_amount = 1_, _mode = 'rgb'_) &middot; [Source](https://github.com/evercoder/culori/blob/master/src/filter.js)
802802

803803
The [`contrast()`](https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/contrast) filter. An _amount_ of `1` leaves the color unchanged. Smaller values decrease the contrast (with `0` being fully gray), while larger values increase it.
@@ -832,6 +832,8 @@ culori
832832
// ⇒ ["#751800", "#664200", "#576c00", "#1a3e82", "#0010ff"];
833833
```
834834

835+
Some of the effects may be obtained more straightforwardly with simple calculations in other color spaces. For example, [hue rotation](#filterHueRotate) can just as well be implemented as `color.h += angle` in a cylindrical color space such as HSL.
836+
835837
### Color vision deficiency (CVD) simulation
836838

837839
Simulate how a color may be perceived by people with color vision deficiencies (CVD).

docs/css/main.css

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ body {
147147
line-height: 1.6;
148148
margin: 0;
149149

150-
--aside-bg: var(--lavender);
150+
--aside-bg: var(--mintcream);
151151
--listing-bg: var(--whitesmoke);
152-
--link-color: var(--indigo);
152+
--link-color: #d84f4c;
153153

154154
--ff-main: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
155155
sans-serif, Apple Color Emoji, Segoe UI Emoji;
@@ -205,7 +205,7 @@ article img {
205205

206206
header {
207207
padding: 0.25em 0 0;
208-
background: linear-gradient(to bottom, var(--aside-bg), white);
208+
/*background: linear-gradient(to bottom, var(--aside-bg), white);*/
209209
}
210210

211211
footer .container {
@@ -272,6 +272,12 @@ a {
272272
color: var(--link-color);
273273
}
274274

275+
a:hover,
276+
a:focus {
277+
outline: 2px dotted black;
278+
outline-offset: 2px;
279+
}
280+
275281
pre,
276282
code,
277283
kbd,
@@ -280,6 +286,14 @@ samp {
280286
font-family: var(--ff-code);
281287
}
282288

289+
.btn-link {
290+
background: var(--link-color);
291+
color: white;
292+
padding: 1ch 2ch;
293+
text-decoration: none;
294+
display: inline-block;
295+
}
296+
283297
/* syntax highlighting */
284298

285299
code[class*='language-'],

docs/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ culori = require('culori@{{pkg.version}}');
1818
1919
## Install it as an npm package
2020

21-
<a href="https://www.npmjs.org/package/culori"><img src="https://img.shields.io/npm/v/culori.svg?style=flat" alt="npm version"></a> <a href="https://bundlephobia.com/result?p=culori"><img src="https://badgen.net/bundlephobia/minzip/culori" alt="bundlephobia"></a>
21+
<a href="https://www.npmjs.org/package/culori"><img src="https://img.shields.io/npm/v/culori.svg?style=flat-square&labelColor=d84f4c&color=black" alt="npm version"></a> <a href="https://bundlephobia.com/result?p=culori"><img src="https://img.shields.io/bundlephobia/minzip/culori?style=flat-square&labelColor=d84f4c&color=black" alt="npm version"></a>
2222

2323
culori is bundled as both UMD and ES [on npm](https://npmjs.com/package/culori). Install it using `npm` or `yarn`:
2424

docs/img/culori.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/index.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ layout: layouts/default
44
menu-order: 0
55
---
66

7-
Culori is a color library for JavaScript that supports most color spaces and formats defined in the [CSS Colors Level 4][css4-colors] spec ([named colors][css4-named-colors], [Hex colors](hex-colors) (3 to 8 digits), [RGB](rgb-colors), [HSL](hsl-colors), [HWB](hwb-colors), [Lab and LCh](lab-colors)), plus [additional color spaces](./color-spaces).
7+
Culori is a color library for JavaScript that supports most color spaces and formats defined in the [CSS Colors Level 4][css4-colors] spec ([named colors][css4-named-colors], [Hex colors](hex-colors) with 3 to 8 digits, [RGB](rgb-colors), [HSL](hsl-colors), [HWB](hwb-colors), [Lab and LCh](lab-colors)), plus [additional color spaces](./color-spaces).
88

99
It handles [color differences](https://en.wikipedia.org/wiki/Color_difference), interpolation, gradients, blend modes [and more](./api).
1010

11+
<a class='btn-link' href='./getting-started'>Get started</a>
12+
1113
## Another JS color library?
1214

1315
Mike Bostock's [d3-color](https://github.com/d3/d3-color), and Gregor Aisch's [chroma.js](https://github.com/gka/chroma.js) are two excellent, robust libraries that provide most of what you need for working with colors on the web. The [Resources](./resources) section for even more libraries you can try.

src/filter.js

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { mapper, mapTransferLinear } from './map';
22
import converter from './converter';
3+
import prepare from './_prepare';
34
import lerp from './util/lerp';
45
import { getModeDefinition } from './modes';
56

@@ -96,14 +97,17 @@ const matrixHueRotate = degrees => {
9697
];
9798
};
9899

99-
const matrix = (values, mode) => {
100+
const matrix = (values, mode, preserve_mode = false) => {
100101
let conv = converter(mode);
101102
let channels = getModeDefinition(mode).channels;
102103
return color => {
103104
let c = conv(color);
105+
if (!c) {
106+
return undefined;
107+
}
104108
let res = { mode };
105-
let ch,
106-
count = channels.length;
109+
let ch;
110+
let count = channels.length;
107111
for (let i = 0; i < values.length; i++) {
108112
ch = channels[Math.floor(i / count)];
109113
if (c[ch] === undefined) {
@@ -112,29 +116,39 @@ const matrix = (values, mode) => {
112116
res[ch] =
113117
(res[ch] || 0) + values[i] * (c[channels[i % count]] || 0);
114118
}
115-
return res;
119+
if (!preserve_mode) {
120+
return res;
121+
}
122+
let prep = prepare(color);
123+
return prep && res.mode !== prep.mode ? converter(prep.mode)(res) : res;
116124
};
117125
};
118126

119127
const filterBrightness = (amt = 1, mode = 'rgb') => {
120128
let a = minzero(amt);
121-
return mapper(mapTransferLinear(a), mode);
129+
return mapper(mapTransferLinear(a), mode, true);
122130
};
131+
123132
const filterContrast = (amt = 1, mode = 'rgb') => {
124133
let a = minzero(amt);
125-
return mapper(mapTransferLinear(a, (1 - a) / 2), mode);
134+
return mapper(mapTransferLinear(a, (1 - a) / 2), mode, true);
126135
};
127-
const filterSepia = (amt = 1, mode = 'rgb') => matrix(matrixSepia(amt), mode);
136+
const filterSepia = (amt = 1, mode = 'rgb') =>
137+
matrix(matrixSepia(amt), mode, true);
128138
const filterSaturate = (amt = 1, mode = 'rgb') =>
129-
matrix(matrixSaturate(amt), mode);
139+
matrix(matrixSaturate(amt), mode, true);
130140
const filterGrayscale = (amt = 1, mode = 'rgb') =>
131-
matrix(matrixGrayscale(amt), mode);
141+
matrix(matrixGrayscale(amt), mode, true);
132142
const filterInvert = (amt = 1, mode = 'rgb') => {
133143
let a = clamp(amt);
134-
return mapper((v, ch) => (ch === 'alpha' ? v : lerp(a, 1 - a, v)), mode);
144+
return mapper(
145+
(v, ch) => (ch === 'alpha' ? v : lerp(a, 1 - a, v)),
146+
mode,
147+
true
148+
);
135149
};
136150
const filterHueRotate = (deg = 0, mode = 'rgb') =>
137-
matrix(matrixHueRotate(deg), mode);
151+
matrix(matrixHueRotate(deg), mode, true);
138152

139153
export {
140154
filterBrightness,

src/map.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import converter from './converter';
22
import identity from './util/identity';
3-
import _prepare from './_prepare';
3+
import prepare from './_prepare';
44
import { getModeDefinition } from './modes';
55

6-
const mapper = (fn, mode = 'rgb') => {
6+
const mapper = (fn, mode = 'rgb', preserve_mode = false) => {
77
let channels = mode ? getModeDefinition(mode).channels : null;
8-
let conv = mode ? converter(mode) : _prepare;
8+
let conv = mode ? converter(mode) : prepare;
99
return color => {
1010
let conv_color = conv(color);
11-
return (channels || getModeDefinition(color.mode).channels).reduce(
11+
let res = (channels || getModeDefinition(color.mode).channels).reduce(
1212
(res, ch) => {
1313
let v = fn(conv_color[ch], ch, conv_color, mode);
1414
if (v !== undefined && !isNaN(v)) {
@@ -18,6 +18,14 @@ const mapper = (fn, mode = 'rgb') => {
1818
},
1919
{ mode }
2020
);
21+
if (!preserve_mode) {
22+
return res;
23+
}
24+
let prep = prepare(color);
25+
if (prep && prep.mode !== res.mode) {
26+
return converter(prep.mode)(res);
27+
}
28+
return res;
2129
};
2230
};
2331

0 commit comments

Comments
 (0)