Skip to content

Commit 7ac18fd

Browse files
authored
gradient color range skips first color (#33)
1 parent a23aac3 commit 7ac18fd

File tree

4 files changed

+232
-196
lines changed

4 files changed

+232
-196
lines changed

README.md

+24-6
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,18 @@ Using 2 colors and default (10) midpoints to generate an array of hex color valu
4646
import Gradient from "javascript-color-gradient";
4747

4848
const gradientArray = new Gradient()
49-
.setColorGradient("#3F2CAF", "e9446a")
49+
.setColorGradient("#3F2CAF", "#e9446a")
5050
.getColors();
5151

5252
console.log(gradientArray);
53-
// ["#502ea8", "#6131a1", "#72339a", "#833693", "#94388d", "#a53a86", "#b63d7f", "#c73f78", "#d84271", "#e9446a"]
53+
54+
[
55+
'#3f2caf', '#522fa7',
56+
'#6531a0', '#783498',
57+
'#8b3790', '#9d3989',
58+
'#b03c81', '#c33f79',
59+
'#d64172', '#e9446a'
60+
]
5461
```
5562

5663
Using 4 colors and 20 midpoints to generate an array of hex color values :
@@ -64,7 +71,18 @@ const gradientArray = new Gradient()
6471
.getColors();
6572

6673
console.log(gradientArray);
67-
// ["#5930a5", "#72339a", "#8c3790", "#a53a86", "#bf3e7b", "#d84271", "#e94b6c", "#ea5f70", "#ea7375", "#eb8779", …]
74+
75+
[
76+
'#3f2caf', '#5a30a4',
77+
'#753499', '#90378e',
78+
'#aa3b83', '#c53f79',
79+
'#e9526d', '#ea6772',
80+
'#eb7c77', '#eb917b',
81+
'#eca680', '#e6c588',
82+
'#cfb989', '#b9ad89',
83+
'#a3a18a', '#8d958a',
84+
'#76898b', '#607D8B'
85+
]
6886
```
6987

7088
Using two colors and default (10) midpoints to return single hex color value corresponding to the provided index:
@@ -73,12 +91,12 @@ Using two colors and default (10) midpoints to return single hex color value cor
7391
import Gradient from "javascript-color-gradient";
7492

7593
const colorAtIndexTwo = new Gradient()
76-
.setColorGradient("#3F2CAF", "e9446a")
77-
.setMidpoint(20)
94+
.setColorGradient("#3F2CAF", "#e9446a")
7895
.getColor(2);
7996

8097
console.log(colorAtIndexTwo);
81-
// #5930a5
98+
99+
#6531a0
82100
```
83101

84102
## Contributing

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "javascript-color-gradient",
3-
"version": "2.4.4",
3+
"version": "2.5.0",
44
"description": "javascript-color-gradient is a lightweight JavaScript library, used to generate an array of color gradients by providing start and finish colors, as well as the required number of midpoints. ",
55
"main": "src/index.js",
66
"scripts": {

src/index.js

+134-148
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,145 @@
11
class GradientColor {
2-
constructor(startColor = "", endColor = "", minNum = 0, maxNum = 10) {
3-
this.setColorGradient = (colorStart, colorEnd) => {
4-
startColor = getHexColor(colorStart);
5-
endColor = getHexColor(colorEnd);
6-
};
7-
8-
this.setMidpoint = (minNumber, maxNumber) => {
9-
minNum = minNumber;
10-
maxNum = maxNumber;
11-
};
12-
13-
this.getColor = (numberValue) => {
14-
if (numberValue) {
15-
return (
16-
"#" +
17-
generateHex(
18-
numberValue,
19-
startColor.substring(0, 2),
20-
endColor.substring(0, 2)
21-
) +
22-
generateHex(
23-
numberValue,
24-
startColor.substring(2, 4),
25-
endColor.substring(2, 4)
26-
) +
27-
generateHex(
28-
numberValue,
29-
startColor.substring(4, 6),
30-
endColor.substring(4, 6)
31-
)
32-
);
33-
}
34-
};
2+
constructor() {
3+
this.minNum = 0;
4+
this.maxNum = 10;
5+
this.startHex = "";
6+
this.endHex = "";
7+
}
358

36-
const generateHex = (number, start, end) => {
37-
if (number < minNum) {
38-
number = minNum;
39-
} else if (number > maxNum) {
40-
number = maxNum;
41-
}
9+
setColorGradient(colorStart, colorEnd) {
10+
if (!colorStart.startsWith("#") || !colorEnd.startsWith("#")) {
11+
throw new Error('Colors must be in hexadecimal format starting with "#"');
12+
}
13+
14+
this.startHex = this.validateAndExpandHex(colorStart);
15+
this.endHex = this.validateAndExpandHex(colorEnd);
16+
}
17+
18+
validateAndExpandHex(hex) {
19+
if (hex.length === 4) {
20+
return "#" + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
21+
} else if (hex.length === 7) {
22+
return hex;
23+
} else {
24+
throw new Error(
25+
"Invalid color format. Please use full hex color values (e.g., #3f2caf) instead of abbreviated formats",
26+
);
27+
}
28+
}
29+
30+
setMidpoint(minNumber = 0, maxNumber = 10) {
31+
this.minNum = minNumber;
32+
this.maxNum = maxNumber;
33+
}
34+
35+
getColor(numberValue) {
36+
if (numberValue === undefined) return;
37+
38+
return (
39+
"#" +
40+
this.generateHex(
41+
numberValue,
42+
this.startHex.substring(1, 3),
43+
this.endHex.substring(1, 3),
44+
) +
45+
this.generateHex(
46+
numberValue,
47+
this.startHex.substring(3, 5),
48+
this.endHex.substring(3, 5),
49+
) +
50+
this.generateHex(
51+
numberValue,
52+
this.startHex.substring(5, 7),
53+
this.endHex.substring(5, 7),
54+
)
55+
);
56+
}
4257

43-
const midPoint = maxNum - minNum;
44-
const startBase = parseInt(start, 16);
45-
const endBase = parseInt(end, 16);
46-
const average = (endBase - startBase) / midPoint;
47-
const finalBase = Math.round(average * (number - minNum) + startBase);
48-
const balancedFinalBase =
49-
finalBase < 16 ? "0" + finalBase.toString(16) : finalBase.toString(16);
50-
return balancedFinalBase;
51-
};
52-
53-
const getHexColor = (color) => {
54-
return color.substring(color.length - 6, color.length);
55-
};
58+
generateHex(number, start, end) {
59+
if (number < this.minNum) number = this.minNum;
60+
else if (number > this.maxNum) number = this.maxNum;
61+
62+
const midPoint = this.maxNum - this.minNum;
63+
const startBase = parseInt(start, 16);
64+
const endBase = parseInt(end, 16);
65+
const average = (endBase - startBase) / midPoint;
66+
const finalBase = Math.round(average * (number - this.minNum) + startBase);
67+
return finalBase.toString(16).padStart(2, "0");
5668
}
5769
}
5870

5971
class Gradient {
60-
constructor(
61-
colorGradients = "",
62-
maxNum = 10,
63-
colors = ["", ""],
64-
intervals = []
65-
) {
66-
const setColorGradient = (gradientColors) => {
67-
if (gradientColors.length < 2) {
68-
throw new Error(
69-
`setColorGradient should have more than ${gradientColors.length} color`
70-
);
71-
} else {
72-
const increment = maxNum / (gradientColors.length - 1);
73-
const firstColorGradient = new GradientColor();
74-
const lower = 0;
75-
const upper = 0 + increment;
76-
firstColorGradient.setColorGradient(
77-
gradientColors[0],
78-
gradientColors[1]
79-
);
80-
firstColorGradient.setMidpoint(lower, upper);
81-
colorGradients = [firstColorGradient];
82-
intervals = [
83-
{
84-
lower,
85-
upper,
86-
},
87-
];
88-
89-
for (let i = 1; i < gradientColors.length - 1; i++) {
90-
const gradientColor = new GradientColor();
91-
const lower = 0 + increment * i;
92-
const upper = 0 + increment * (i + 1);
93-
gradientColor.setColorGradient(
94-
gradientColors[i],
95-
gradientColors[i + 1]
96-
);
97-
gradientColor.setMidpoint(lower, upper);
98-
colorGradients[i] = gradientColor;
99-
intervals[i] = {
100-
lower,
101-
upper,
102-
};
103-
}
104-
colors = gradientColors;
105-
}
106-
};
107-
108-
this.setColorGradient = (...gradientColors) => {
109-
setColorGradient(gradientColors);
110-
return this;
111-
};
112-
113-
this.getColors = () => {
114-
const gradientColorsArray = [];
115-
for (let j = 0; j < intervals.length; j++) {
116-
const interval = intervals[j];
117-
const start = interval.lower === 0 ? 1 : Math.ceil(interval.lower);
118-
const end =
119-
interval.upper === maxNum
120-
? interval.upper + 1
121-
: Math.ceil(interval.upper);
122-
for (let i = start; i < end; i++) {
123-
gradientColorsArray.push(colorGradients[j].getColor(i));
124-
}
125-
}
126-
return gradientColorsArray;
127-
};
128-
129-
this.getColor = (numberValue) => {
130-
if (isNaN(numberValue)) {
131-
throw new TypeError(`getColor should be a number`);
132-
} else if (numberValue <= 0) {
133-
throw new TypeError(`getColor should be greater than ${numberValue}`);
134-
} else {
135-
const toInsert = numberValue + 1;
136-
const segment = (maxNum - 0) / colorGradients.length;
137-
const index = Math.min(
138-
Math.floor((Math.max(numberValue, 0) - 0) / segment),
139-
colorGradients.length - 1
140-
);
141-
return colorGradients[index].getColor(toInsert);
142-
}
143-
};
144-
145-
this.setMidpoint = (maxNumber) => {
146-
if (!isNaN(maxNumber) && maxNumber >= 0) {
147-
maxNum = maxNumber;
148-
setColorGradient(colors);
149-
} else if (maxNumber <= 0) {
150-
throw new RangeError(`midPoint should be greater than ${maxNumber}`);
151-
} else {
152-
throw new RangeError("midPoint should be a number");
72+
constructor() {
73+
this.maxNum = 10;
74+
this.colors = [];
75+
this.colorGradients = [];
76+
this.intervals = [];
77+
}
78+
79+
setColorGradient(...gradientColors) {
80+
if (gradientColors.length < 2) {
81+
throw new RangeError(`setColorGradient requires at least 2 colors`);
82+
}
83+
84+
const increment = (this.maxNum - 1) / (gradientColors.length - 1);
85+
this.colorGradients = [];
86+
this.intervals = [];
87+
88+
for (let i = 0; i < gradientColors.length - 1; i++) {
89+
const gradientColor = new GradientColor();
90+
const lower = increment * i;
91+
const upper = increment * (i + 1);
92+
gradientColor.setColorGradient(gradientColors[i], gradientColors[i + 1]);
93+
gradientColor.setMidpoint(lower, upper);
94+
this.colorGradients.push(gradientColor);
95+
this.intervals.push({ lower, upper });
96+
}
97+
this.colors = gradientColors;
98+
return this;
99+
}
100+
101+
getColors() {
102+
const gradientColorsArray = [];
103+
const numColors = this.maxNum + 1;
104+
105+
for (let j = 0; j < this.intervals.length; j++) {
106+
const { lower, upper } = this.intervals[j];
107+
const start = j === 0 ? 0 : Math.ceil(lower);
108+
const end = j === this.intervals.length - 1 ? Math.ceil(upper) : Math.floor(upper);
109+
110+
for (let i = start; i < end; i++) {
111+
gradientColorsArray.push(this.colorGradients[j].getColor(i));
153112
}
154-
return this;
155-
};
113+
}
114+
115+
gradientColorsArray.push(this.colors[this.colors.length - 1]);
116+
return gradientColorsArray.slice(0, numColors);
117+
}
118+
119+
getColor(numberValue) {
120+
if (isNaN(numberValue)) {
121+
throw new TypeError(`getColor requires a numeric value`);
122+
}
123+
if (numberValue <= 0) {
124+
throw new RangeError(`getColor value should be greater than 0`);
125+
}
126+
127+
const segment = (this.maxNum + 1) / this.colorGradients.length;
128+
const index = Math.min(Math.floor(numberValue / segment), this.colorGradients.length - 1);
129+
return this.colorGradients[index].getColor(numberValue);
130+
}
131+
132+
setMidpoint(maxNumber = 10) {
133+
if (isNaN(maxNumber) || maxNumber < this.colors.length) {
134+
throw new RangeError(
135+
`setMidpoint should be a number greater than or equal to the number of colors`,
136+
);
137+
}
138+
139+
this.maxNum = maxNumber ;
140+
this.setColorGradient(...this.colors);
141+
return this;
156142
}
157143
}
158144

159-
module.exports = Gradient;
145+
module.exports = Gradient;

0 commit comments

Comments
 (0)