UNPKG

gradient-color

Version:

Gradient color generator that lives in 21st

226 lines (185 loc) 5.52 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _color = require('color'); var _color2 = _interopRequireDefault(_color); var _errors = require('./errors'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Generate n colors with given color stops * * @param {Array} colorArray * @param {Number} n number of colors that need to generate * @returns {Array} array of generated colors in rgb mode */ function gradient(colorArray, n) { var isFullOption = checkParam(colorArray, n); // init 2 arrays for algorithm var colorList = []; var fracList = []; // result array for storing data var resultArray = []; // simple array of color string if (!isFullOption) { var frac = 1 / (colorArray.length - 1); colorArray.forEach(function (colorString, index) { if (index !== colorArray.length - 1) { colorList.push((0, _color2.default)(colorString)); fracList.push(frac); } else { colorList.push((0, _color2.default)(colorString)); } }); } else { colorArray.forEach(function (obj, index) { if (index !== colorArray.length - 1) { colorList.push((0, _color2.default)(obj.color)); fracList.push(obj.frac); } else { if (obj.color) { // the last item could be like { color: #ffffff } colorList.push((0, _color2.default)(obj.color)); } else { // and it could also be like '#ffffff' colorList.push((0, _color2.default)(obj)); } } }); } var assignList = assignNumbers(fracList, n); resultArray = createGradient(colorList, assignList); // convert colors to string version resultArray = resultArray.map(function (c) { return c.rgb().toString(); }); return resultArray; } /** * Explainations: * o -> stop color for gradient * * -> generated color * * o * * * | o * * * * | o * * o -> generated color list in char version * 4 5 4 -> assigned number of colors need to be generated * * The last section, the end color should be considered in the generated colors * * @returns {Array} array of colors in Color(pkg) format, need toString() call */ function createGradient(colorList, assignList) { var result = []; assignList.forEach(function (num, index) { var isLastElement = index === assignList.length - 1; var list = []; // get end point color var start = colorList[index]; var end = colorList[index + 1]; // if last element, end color should be in the list, // so the num = num - 1 if (isLastElement) { num = num - 1; } var deltaR = (end.red() - start.red()) / num; var deltaG = (end.green() - start.green()) / num; var deltaB = (end.blue() - start.blue()) / num; // generate num colors for (var i = 0; i < num; i++) { var R = start.red() + i * deltaR; var G = start.green() + i * deltaG; var B = start.blue() + i * deltaB; list.push(_color2.default.rgb(R, G, B)); } // if last element, end this list with the last color if (isLastElement) { list.push(end); } result = result.concat(list); }); return result; } /** * Calculate and optimize the number of each color period * * Sometimes frac * N might be a fraction * So we use this algorithm: * * 1. Split the number into 2 parts, each part fits in an array: * [2, 4, 1, 5] -> int array * [0.2, 0.5, 0.9, 0.3] -> decimal array * * The left number should be: * left = N - sum(intArray) * * 2. Sort the decimal array from large to small, assign left to * the corresponding element in intArray one by one * until left === 0 * * 3. There goes your final array! * * @returns {Array} array of optimized color numbers */ function assignNumbers(fracList, n) { var intArray = []; var decimalArray = []; // assign int part fracList.forEach(function (frac, index) { var real = frac * n; var intPart = Math.floor(real); var decimalPart = real - intPart; intArray.push(intPart); decimalArray.push({ value: decimalPart, index: index }); }); // how many left ? var left = n - intArray.reduce(function (a, b) { return a + b; }, 0); // sort O -> o decimalArray.sort(function (a, b) { return b.value - a.value; }); // assign the left number regard to the decimal part's value // until nothing left for (var i = 0; i < left; i++) { var targetIndex = decimalArray[i].index; intArray[targetIndex] = intArray[targetIndex] + 1; } return intArray; } /** * Check param format and throw some errors */ function checkParam(array, n) { // Seriously? Anyone this dumb? if (array.length < 2) { throw _errors.MIN_ARRAY_LENGTH; } // Read the documentation OMG! Of course no frac at the end! if (array[array.length - 1].frac) { throw _errors.NO_EDN_FRAC; } // You need to see a doctor, like, right now if (n <= array.length) { throw _errors.COLOR_NUMBER_ERROR; } // if full option mode, sum should be 1 if (typeof array[0] !== 'string') { var fracSum = array.slice(0, array.length - 1).reduce(function (a, b) { return a + b.frac; }, 0); if (fracSum < 0.99) { throw _errors.FRAC_SUM_ERROR; } } var result = void 0; if (typeof array[0] === 'string') { result = false; } else { result = true; } return result; } exports.default = gradient;