├── .eslintrc.json ├── .gitignore ├── index.d.ts ├── index.js ├── package-lock.json ├── package.json ├── readme.md └── test.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "commonjs": true, 6 | "es6": true 7 | }, 8 | "extends": "eslint:recommended", 9 | "rules": { 10 | "strict": 2, 11 | "indent": 0, 12 | "linebreak-style": 0, 13 | "quotes": 0, 14 | "semi": 0, 15 | "no-cond-assign": 1, 16 | "no-constant-condition": 1, 17 | "no-duplicate-case": 1, 18 | "no-empty": 1, 19 | "no-ex-assign": 1, 20 | "no-extra-boolean-cast": 1, 21 | "no-extra-semi": 1, 22 | "no-fallthrough": 1, 23 | "no-func-assign": 1, 24 | "no-global-assign": 1, 25 | "no-implicit-globals": 2, 26 | "no-inner-declarations": ["error", "functions"], 27 | "no-irregular-whitespace": 2, 28 | "no-loop-func": 1, 29 | "no-multi-str": 1, 30 | "no-mixed-spaces-and-tabs": 1, 31 | "no-proto": 1, 32 | "no-sequences": 1, 33 | "no-throw-literal": 1, 34 | "no-unmodified-loop-condition": 1, 35 | "no-useless-call": 1, 36 | "no-void": 1, 37 | "no-with": 2, 38 | "wrap-iife": 1, 39 | "no-redeclare": 1, 40 | "no-unused-vars": ["error", { "vars": "all", "args": "none" }], 41 | "no-sparse-arrays": 1 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | node_modules/* 11 | .c9revisions/* 12 | bundle.js 13 | 14 | pids 15 | logs 16 | results 17 | 18 | npm-debug.log 19 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "color-interpolate" { 2 | function interpolate(palette: string[]): (index: number) => string 3 | 4 | export = interpolate 5 | } 6 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * @module color-interpolate 5 | * Pick color from palette by index 6 | */ 7 | 8 | import parse from 'color-parse'; 9 | import hsl from 'color-space/hsl.js'; 10 | 11 | const lerp = (start, stop, step) => start*(1-step)+stop*step; 12 | 13 | export default function interpolate (palette) { 14 | palette = palette.map((c) => { 15 | c = parse(c); 16 | if (c.space != 'rgb') { 17 | if (c.space != 'hsl') throw 'c.space' + 'space is not supported.'; 18 | c.values = hsl.rgb(c.values); 19 | } 20 | c.values.push(c.alpha); 21 | return c.values; 22 | }); 23 | 24 | return (t, mix) => { 25 | mix = mix || lerp; 26 | t = Math.min(Math.max(t, 0), 1); 27 | 28 | var idx = ( palette.length - 1 ) * t, 29 | lIdx = Math.floor( idx ), 30 | rIdx = Math.ceil( idx ); 31 | 32 | t = idx - lIdx; 33 | 34 | var lColor = palette[lIdx], rColor = palette[rIdx]; 35 | 36 | var result = lColor.map(function(v, i) { 37 | v = mix(v, rColor[i], t); 38 | if (i < 3) v = Math.round(v); 39 | return v; 40 | }); 41 | 42 | if (result[3] === 1) { 43 | return 'rgb('+result.slice(0,3)+')'; 44 | } 45 | return 'rgba('+result+')'; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "color-interpolate", 3 | "version": "2.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "color-interpolate", 9 | "version": "2.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "color-parse": "^2.0.2", 13 | "color-space": "^2.3.2" 14 | } 15 | }, 16 | "node_modules/color-name": { 17 | "version": "2.0.0", 18 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.0.tgz", 19 | "integrity": "sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow==", 20 | "license": "MIT", 21 | "engines": { 22 | "node": ">=12.20" 23 | } 24 | }, 25 | "node_modules/color-parse": { 26 | "version": "2.0.2", 27 | "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-2.0.2.tgz", 28 | "integrity": "sha512-eCtOz5w5ttWIUcaKLiktF+DxZO1R9KLNY/xhbV6CkhM7sR3GhVghmt6X6yOnzeaM24po+Z9/S1apbXMwA3Iepw==", 29 | "license": "MIT", 30 | "dependencies": { 31 | "color-name": "^2.0.0" 32 | } 33 | }, 34 | "node_modules/color-space": { 35 | "version": "2.3.2", 36 | "resolved": "https://registry.npmjs.org/color-space/-/color-space-2.3.2.tgz", 37 | "integrity": "sha512-BcKnbOEsOarCwyoLstcoEztwT0IJxqqQkNwDuA3a65sICvvHL2yoeV13psoDFh5IuiOMnIOKdQDwB4Mk3BypiA==", 38 | "license": "Unlicense" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "color-interpolate", 3 | "version": "2.0.0", 4 | "description": "Pick color from a given color palette by index", 5 | "main": "index.js", 6 | "types": "index.d.ts", 7 | "type": "module", 8 | "scripts": { 9 | "test": "node test" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/colorjs/color-interpolate.git" 14 | }, 15 | "keywords": [ 16 | "color", 17 | "interpolate", 18 | "lerp", 19 | "interpolate-arrays", 20 | "interpolation", 21 | "smootstep", 22 | "palette", 23 | "colormap", 24 | "gradient" 25 | ], 26 | "author": "Dmitry Iv ", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/colorjs/color-interpolate/issues" 30 | }, 31 | "homepage": "https://github.com/colorjs/color-interpolate#readme", 32 | "dependencies": { 33 | "color-parse": "^2.0.2", 34 | "color-space": "^2.3.2" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # color-interpolate [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) 2 | 3 | For a given palette, return color by any float index. Useful for interpolating colormaps, color palettes or gradients. 4 | 5 | ## Usage 6 | 7 | [![npm install color-interpolate](https://nodei.co/npm/color-interpolate.png?mini=true)](https://npmjs.org/package/color-interpolate/) 8 | 9 | ```js 10 | import interpolate from 'color-interpolate'; 11 | 12 | let colormap = interpolate(['black', 'gray', 'white']); 13 | let black = colormap(0); // 'rgb(0, 0, 0)' 14 | let white = colormap(1); // 'rgb(255, 255, 255)' 15 | let gray = colormap(.5); // 'rgb(128, 128, 128)' 16 | ``` 17 | 18 | ## API 19 | 20 | ### `let palette = interpolate(colors)` 21 | 22 | Create interpolator from a list of `colors`. Colors can be in any format: CSS color string, array with RGB channel values, object with `r`, `g`, `b` or `h`, `s`, `l` channel values or even a number, see [color-parse](https://github.com/dy/color-parse) for reference. 23 | 24 | ### `let color = palette(index, fn?)` 25 | 26 | Get interpolated color from palette by `index` value within `0..1` range. Pass optional `fn` interpolation function, by default [lerp](https://npmjs.org/package/lerp) is used, but [smoothstep](https://npmjs.org/package/smoothstep) can be used as an alternative. 27 | 28 | Example: 29 | 30 | ```js 31 | import palettes from 'nice-color-palettes' 32 | import interpolate from 'color-interpolate' 33 | 34 | const palette = interpolate(palettes[32]) 35 | 36 | let activeColor = palette(.2) // 'rgb(51, 23 47)' 37 | let background = palette(1) // 'rgb(255, 255, 255)' 38 | let foreground = palette(0) // 'rgb(0, 0, 0)' 39 | ``` 40 | 41 | ## Credits 42 | 43 | Thanks to **[@mattdesl](https://github.com/mattdesl/)** for [interpolation](https://github.com/mattdesl/interpolation) functions and **[@mikkoh](https://github.com/mikkoh/)** for API insight in [interpolation-arrays](https://github.com/jam3/interpolation-arrays). 44 | 45 | ## Related 46 | 47 | > [colormap](https://github.com/bpostlethwaite/colormap) — collection of beautiful colormaps, a good source for palettes.
48 | > [nice-color-palettes](https://github.com/jam3/nice-color-palettes) — collection of beautiful color palettes from colourlovers.
49 | > [color-alpha](https://github.com/dy/color-alpha) — change alpha of a color string.
50 | > [color-spectrum](https://github.com/dy/color-spectrum) — convert spectrum, like FFT result, to color.
51 | > [color-space](https://github.com/scijs/color-space) — collection of color space transforms, useful for custom interpolation modes.
52 | 53 | © Dmitry Iv. MIT License 54 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | 2 | import assert from 'assert'; 3 | import interpolate from './index.js'; 4 | 5 | let bw = interpolate(['black', 'white']); 6 | 7 | assert.equal(bw(0), 'rgb(0,0,0)'); 8 | assert.equal(bw(1), 'rgb(255,255,255)'); 9 | assert.equal(bw(.5), 'rgb(128,128,128)'); 10 | assert.equal(bw(.25), 'rgb(64,64,64)'); 11 | 12 | 13 | let palette = interpolate(['red', 'gray', 'green']); 14 | 15 | assert.equal(palette(0), 'rgb(255,0,0)'); 16 | assert.equal(palette(1), 'rgb(0,128,0)'); 17 | assert.equal(palette(.5), 'rgb(128,128,128)'); 18 | --------------------------------------------------------------------------------