javascript实现彩虹颜色梯度渐变

标签: Javascript 分类: Javascript 创建时间:2019-11-12 01:28:58 更新时间:2024-11-23 02:04:26

实现彩虹色渐变的方式,其实网上有两种主要的实现方式,第一种就是单纯的用颜色值的规律从紫色一直过度到红色,比如参考文章1;另一种是两种颜色之间的渐变色,比如参考文章的2和3。由于能力有限,第一种实现彩虹表算法的方法,不能实现指定的颜色开始与结束颜色区间,但是第二种,又不能指定从哪个颜色过渡到哪个颜色,比如从红到橙再到黄,只能从红直接到黄,或者是直接到橙,不太方便。最后,其实我是使用了第二种方式,我设置了一个数组,从红到紫的数组,指定了开始颜色值,比如红色,结束颜色值比如紫色,分段数位10,那么我就将从红到橙,通过第二种方法,渐变2段,然后从橙到黄渐变两段,一直到紫色,最后,组成一个最终的渐变数组。

1.颜色数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
/** 颜色表算法
* colorSize 颜色分段,默认为6
* colorType 上限下限的数值类型,是整数,还是小数,整数为0,小数为1,默认为0
* maxValue 上限值,整数情况下默认为300,小数情况下默认为1.0
* minValue 下限值,整数情况下默认为100,小数情况下默认为0.2
*/
//function RGBCal(colorSize,colorType,maxValue,minValue){
function RGBCal(section,option){
//执行单色卡初始化
this.initSingleColor();
//执行双色卡初始化
this.initDoubleColor();
}
RGBCal.prototype={
constructor:RGBCal,
initSingleColor:function(colorSize,colorType,maxValue,minValue){
this.colorSize=colorSize||7;
this.colorType=colorType||0;
if(this.colorType==0){
this.maxValue=maxValue||300;
this.minValue=minValue||100;
}else {
this.maxValue=maxValue||1.0;
this.minValue=minValue||0.2;
}
//执行初始化
this.rgbColors=this.getRGBColorsNew(this.colorSize);
},
initDoubleColor:function(colorBlock){
if(!colorBlock){
colorBlock= [{
"colorSection": 5,
"colorType":0,
"upperValue": 300, //最大值
"lowerValue": 0, //最小值
"rgbColors":[] //色卡数组
},{
"colorSection": 6, //颜色分段
"colorType":0, //使用小数还是整数计算
"upperValue": 0, ///最大值
"lowerValue": -100, //最小值
"rgbColors":[] //色卡数组
}];
}
this.colorBlock= colorBlock;
//计算基准值
var upper=this.colorBlock[0].lowerValue;
var lower=this.colorBlock[1].upperValue;
if(lower>=upper){
this.reference=upper;
}else {
this.reference=(parseFloat(upper)+parseFloat(lower))/2;
}

//分段计算色卡
this.colorBlock[0].rgbColors=this.getRainbowColor2_own(this.colorBlock[0].colorSection);
this.colorBlock[1].rgbColors=this.getRainbowColor2_two(this.colorBlock[1].colorSection);
},
//获取一段颜色时当前数据对应RGB
getCurrentColor:function (currentVal) {
var maxValue=this.maxValue;
var minValue=this.minValue;
var colorLineType=this.colorType
if (currentVal - minValue <= 0) {
return this.rgbColors[0];
}
var colorSize=this.colorSize;
if (currentVal - maxValue >= 0) {
return this.rgbColors[colorSize - 1];
}
if (colorLineType === 0) { //温度
var itemVal = (maxValue - minValue) / (colorSize - 2);
var indexVal = Math.floor((currentVal - minValue) / itemVal) + 1;
} else { //压力colorLineType === 1
var itemVal = this.accDiv(this.accSub(maxValue, minValue), colorSize - 2);
var indexVal = Math.floor(this.accDiv(this.accSub(currentVal, minValue), itemVal)) + 1;
}
return this.rgbColors[indexVal];
},
//RGB彩虹算法---标准
getRGBColors:function (colorSize) {
var colors = [];
for (var i = 0; i < colorSize; i++) {
var r = 0;
var g = 0;
var b = 0;
if (i < colorSize / 3) {
r = 255;
g = Math.ceil(255 * 3 * i / colorSize);
b = 0;
} else if (i < colorSize / 2) {
r = Math.ceil(750 - i * (250 * 6 / colorSize));
g = 255;
b = 0;
} else if (i < colorSize * 2 / 3) {
r = 0;
g = 255;
b = Math.ceil(i * (250 * 6 / colorSize) - 750);
} else if (i < colorSize * 5 / 6) {
r = 0;
g = Math.ceil(1250 - i * (250 * 6 / colorSize));
b = 255;
} else {
r = Math.ceil(150 * i * (6 / colorSize) - 750);
g = 0;
b = 255;
}
colors.push('rgb(' + r + ',' + g + ',' + b + ')');
}
colors.reverse(); //倒序
return colors;
},
//RGB彩虹算法--去掉紫色
getRGBColorsNew:function (colorSize) {
var colors = [];
for (var i = 0; i < colorSize; i++) {
var r = 0;
var g = 0;
var b = 0;
if (i < colorSize / 3) {
r = 255;
g = Math.ceil(255 * 3 * i / colorSize);
b = 0;
} else if (i < colorSize / 2) {
r = Math.ceil(750 - i * (250 * 6 / colorSize));
g = 255;
b = 0;
} else if (i < colorSize * 2 / 3) {
r = 0;
g = 255;
b = Math.ceil(i * (250 * 6 / colorSize) - 750);
} else {
r = 0;
g = Math.ceil(750 - i * (250 * 3 / colorSize));
b = 255;
}
colors.push('rgb(' + r + ',' + g + ',' + b + ')');
}
colors.reverse();
return colors;
},
// 修改颜色分段、颜色类型、最大最小值
setColorConfig:function(colorSize,colorType,maxValue,minValue){
this.colorSize=colorSize||this.colorSize;
this.colorType=colorType||this.colorType;
this.maxValue=maxValue||this.maxValue;
this.minValue=minValue||this.minValue;
//重新计算色卡
//this.rgbColors=this.getRGBColors(this.colorSize);
//去掉紫色
this.rgbColors=this.getRGBColorsNew(this.colorSize);
},
//修改双色卡时的分段、颜色类型、最大最小值
setColorConfig2:function(colorblock){
colorblock=colorblock||this.colorBlock;
//判断是否为空值
colorblock[0].colorSection=colorblock[0].colorSection||this.colorBlock[0].colorSection;
//如果第二段为空
if(colorblock.length>1){
colorblock[1].colorSection=colorblock[1].colorSection==""?this.colorBlock[1].colorSection:colorblock[1].colorSection;
}
this.colorBlock=colorblock;
//重新计算基准值
var upper=this.colorBlock[0].lowerValue;
var lower=this.colorBlock[1].upperValue;
if(lower>=upper){
this.reference=upper;
}else {
this.reference=(parseFloat(upper)+parseFloat(lower))/2;
}
//分段计算色卡
this.colorBlock[0].rgbColors=this.getRainbowColor2_own(this.colorBlock[0].colorSection);
this.colorBlock[1].rgbColors=this.getRainbowColor2_two(this.colorBlock[1].colorSection);
},
//获取双色卡时当前数据对应的RGB值
getCurrentColor2:function (currentVal) {
//首先和基准值比较,确定落在哪个色卡内
var colorblock=null;
var colorLineType=0;
if(currentVal>=this.reference){ //落在第一个色卡内
colorblock=this.colorBlock[0];
}else { //否则落在第二个色卡内
colorblock=this.colorBlock[1];
}
// 设置计算方式
var colorLineType=colorblock.colorType;

var maxValue=colorblock.upperValue;
var minValue=colorblock.lowerValue;
if (currentVal - minValue <= 0) {
return colorblock.rgbColors[0];
}
var colorSize=colorblock.colorSection;
if (currentVal - maxValue >= 0) {
return colorblock.rgbColors[colorSize - 1];
}

if (colorLineType === 0) { //温度
var itemVal = (maxValue - minValue) / (colorSize - 2);
var indexVal = Math.floor((currentVal - minValue) / itemVal) + 1;
} else { //压力colorLineType === 1
var itemVal = this.accDiv(this.accSub(maxValue, minValue), colorSize - 2);
var indexVal = Math.floor(this.accDiv(this.accSub(currentVal, minValue), itemVal)) + 1;
}
return colorblock.rgbColors[indexVal];
},
//除法
accDiv:function (arg1, arg2) {
var t1 = 0,
t2 = 0,
r1, r2;
try {
t1 = arg1.toString().split(".")[1].length
} catch (e) {}
try {
t2 = arg2.toString().split(".")[1].length
} catch (e) {}
with(Math) {
r1 = Number(arg1.toString().replace(".", ""))
r2 = Number(arg2.toString().replace(".", ""))
return (r1 / r2) * pow(10, t2 - t1);
}
},
//乘法
accMul:function (arg1, arg2) {
var m = 0,
s1 = arg1.toString(),
s2 = arg2.toString();
try {
m += s1.split(".")[1].length
} catch (e) {}
try {
m += s2.split(".")[1].length
} catch (e) {}
return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
},
//加法
accAdd:function (arg1, arg2) {
var r1, r2, m;
try {
r1 = arg1.toString().split(".")[1].length
} catch (e) {
r1 = 0
}
try {
r2 = arg2.toString().split(".")[1].length
} catch (e) {
r2 = 0
}
m = Math.pow(10, Math.max(r1, r2))
return (arg1 * m + arg2 * m) / m
},
//减法
accSub:function (arg1, arg2) {
var r1, r2, m, n;
try {
r1 = arg1.toString().split(".")[1].length
} catch (e) {
r1 = 0
}
try {
r2 = arg2.toString().split(".")[1].length
} catch (e) {
r2 = 0
}
m = Math.pow(10, Math.max(r1, r2));
n = (r1 >= r2) ? r1 : r2;
return ((arg1 * m - arg2 * m) / m).toFixed(n);
},
//新的渐变算法,主要是分别定义红、橙、黄、绿、青、蓝、紫颜色值,渐变时,分从紫到蓝,蓝到青,青到绿,依此分段渐变,最后组成一个渐变色数组
//形成整个渐变色,比如从绿色渐变到红色,应先从绿色渐变到黄色,然后从黄色渐变到橙色,然后从橙色渐变到红色
// 红: #FF0000 255,0,0
// 橙: #FF7D00 255, 125, 0
// 黄: #FFFF00 255,255,0
// 绿: #00FF00 0,255,0
// 青: #00FFFF 0, 255, 255
// 蓝: #0000FF 0,0,255
// 紫: #FF00FF 255, 0, 255

// 渐变色第一段,从紫色到红色
getRainbowColor_one(colorSize){
var color_list=[];
if(colorSize<6){
switch (colorSize) {
case 1:
color_list=["rgb(255,0,0)"];
break;
case 2:
color_list=["rgb(255,0,0)","rgb(255, 0, 255)"];
break;
case 3:
color_list=["rgb(255,0,0)","rgb(0,255,0)","rgb(255, 0, 255)"];
break;
case 4:
color_list=["rgb(255,0,0)","rgb(255,255,0)","rgb(0,255,0)","rgb(0,255, 255)","rgb(255, 0, 255)"];
break;
case 5:
color_list=["rgb(255,0,0)","rgb(255,255,0)","rgb(0,255,0)","rgb(0,255, 255)","rgb(255, 0, 255)"];
break;
case 6:
color_list=["rgb(255,0,0)","rgb(255,255,0)","rgb(0,255,0)","rgb(0,255, 255)","rgb(0,0,255)","rgb(255, 0, 255)"];
break;
case 7:
color_list=["rgb(255,0,0)","rgb(255, 125, 0)","rgb(255,255,0)","rgb(0,255,0)","rgb(0,255, 255)","rgb(0,0,255)","rgb(255, 0, 255)"];
break;
}
}else {
var subColorSieze=parseInt(colorSize/7);
var subRemainder=colorSize%7;
var color=["#FF0000","#FF7D00","#FFFF00","#00FF00","#00FFFF","#0000FF","#FF00FF","#FF0000"];
color_list=this.getSubColor(color,subColorSieze,subRemainder);
}
return color_list.reverse();
},

// 渐变色分两段的情况下
// 渐变色第一段,从绿色到红色
getRainbowColor2_own:function(colorSize){
var color_list=[];
if(colorSize<5){
switch (colorSize) {
case 1:
color_list=["rgb(255,0,0)"];
break;
case 2:
color_list=["rgb(255,0,0)","rgb(255, 125, 0)"];
break;
case 3:
color_list=["rgb(255,0,0)","rgb(255, 125, 0)","rgb(255,255,0)"];
break;
case 4:
color_list=["rgb(255,0,0)","rgb(255, 125, 0)","rgb(255,255,0)","rgb(0,255,0)"];
break;
}
}else {
var subColorSieze=parseInt(colorSize/4);
var subRemainder=colorSize%4;
var color=["#FF0000","#FF7D00","#FFFF00","#00FF00","#00FFFF"];
color_list=this.getSubColor(color,subColorSieze,subRemainder);
}
return color_list.reverse();
},
// 渐变色第二段,从青色到紫色
getRainbowColor2_two:function(colorSize){
var color_list=[];
if(colorSize<4){
switch (colorSize) {
case 1:
color_list=["rgb(0, 255, 255)"];
break;
case 2:
color_list=["rgb(0, 255, 255)","rgb(0,0,255)"];
break;
case 3:
color_list=["rgb(0, 255, 255)","rgb(0,0,255)","rgb(255, 0, 255)"];
break;
}
}else {
var subColorSieze=parseInt(colorSize/2);
var subRemainder=colorSize%2;
var color=["#00FFFF","#0000FF","#FF00FF"];
color_list=this.getSubColor(color,subColorSieze,subRemainder);
}
return color_list.reverse();
},
getSubColor:function(colorArray,step,remainder){
var colorCount=colorArray.length;
var color_list=[];
for(var i=0;i<colorCount-1;i++){
var temp=0;
if(remainder>0){
temp=1;
}
var tempArray=new gradientColor(colorArray[i],colorArray[i+1],step+temp);
color_list.push.apply(color_list,tempArray);
remainder--;
}
return color_list;
}
}
/**
*
* @param startColor 指定起始颜色
* @param endColor 指定结束颜色
* @param step 划分渐变色区域数量
* @returns {Array} 返回渐变色数组
*/
var gradientColor = function (startColor, endColor, step) {
let startRGB = this.colorRgb(startColor);//转换为rgb数组模式
let startR = startRGB[0];
let startG = startRGB[1];
let startB = startRGB[2];

let endRGB = this.colorRgb(endColor);
let endR = endRGB[0];
let endG = endRGB[1];
let endB = endRGB[2];

let sR = (endR - startR) / step;//总差值
let sG = (endG - startG) / step;
let sB = (endB - startB) / step;

let colorArr = [];
for (let i = 0; i < step; i++) {
//计算每一步的hex值
// let hex = this.colorHex('rgb('+ parseInt((sR * i + startR))+ ',' + parseInt((sG * i + startG))+ ',' +
// parseInt((sB * i + startB)) + ')');
// colorArr.push(hex);
let rgb = 'rgb('+ parseInt((sR * i + startR))+ ',' + parseInt((sG * i + startG))+ ',' +
parseInt((sB * i + startB)) + ')';
colorArr.push(rgb);
}
return colorArr;
};

// 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式)
gradientColor.prototype.colorRgb = function (sColor) {
let reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
sColor = sColor.toLowerCase();
if (sColor && reg.test(sColor)) {
if (sColor.length === 4) {
let sColorNew = "#";
for (let i = 1; i < 4; i += 1) {
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
}
sColor = sColorNew;
}
//处理六位的颜色值
let sColorChange = [];
for (let i = 1; i < 7; i += 2) {
sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
}
return sColorChange;
} else {
return sColor;
}
};
// 将rgb表示方式转换为hex表示方式
gradientColor.prototype.colorHex = function (rgb) {
let _this = rgb;
let reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
if (/^(rgb|RGB)/.test(_this)) {
let aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
let strHex = "#";
for (let i = 0; i < aColor.length; i++) {
let hex = Number(aColor[i]).toString(16);
hex = hex < 10 ? 0 + '' + hex : hex;// 保证每个rgb的值为2位
if (hex === "0") {
hex += hex;
}
strHex += hex;
}
if (strHex.length !== 7) {
strHex = _this;
}
return strHex;
} else if (reg.test(_this)) {
let aNum = _this.replace(/#/, "").split("");
if (aNum.length === 6) {
return _this;
} else if (aNum.length === 3) {
let numHex = "#";
for (let i = 0; i < aNum.length; i += 1) {
numHex += (aNum[i] + aNum[i]);
}
return numHex;
}
} else {
return _this;
}
};

这是实现的效果:

2.HSL颜色模式

如果使用的是hsl的话,好像更加的方便,代码量也更少。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!DOCTYPE html>
<html>
<head>
<title>hsl渐变</title>
<meta charset="utf-8"/>
<style>
body,html{
width:100%;
margin:0;
padding:0;
height: 100%;
position:absolute;
text-align: center;
}
.map{
width:100%;
height:100%;
position:absolute;
}
.save{
position: absolute;
left: 200px;
z-index: 10;
}
</style>
</head>
<body>
<div class="map" id="map"></div>
<script>
function hsl(start,end,colorSize){
var startColor=start;
var endColor=end;

var colors=[];
var step=(end-start)/colorSize;
for(var i=0;i<colorSize;i++){
var hsl="hsl("+(start+step*i)+",100%,50%)";
colors.push(hsl);
}
console.log(colors);
return colors;
}
function createDiv(colors){
var count=colors.length;
var colorItemHtml="";
for(var i=0;i<count;i++){
colorItemHtml+= `<div style="height:40px" class="colorbar-item">
<div style='background:${colors[i]};height:100%;width:15px;display:inline-block;' class="colorbar-colrr"></div>
</div>`;
}
var cot=document.getElementById("map");
cot.innerHTML=colorItemHtml;

}
var h=hsl(0,300,10);
createDiv(h);
</script>
</body>
</html>

这段代码,只需要定义开始的颜色值(一般都是从0开始),和结束的颜色值,比如300,也就是去掉了紫色值,然后设定步长,就可以将颜色按相应的步长进行梯度变色了,比第一种方法好用多了。

参考文章:
1.CSS3中使用HSL颜色指南 (这里其实写的对于HSL颜色的代码还是挺好的)
2.根据值生成彩虹色 (这里其实提到了使用”hsl(“ + ((curPercent * (maxHue-minHue) ) + minHue) + “,100%,50%)” 方法生成颜色色卡的方式)
3.JS 处理十六进制颜色渐变算法-输入颜色,输出渐变rgb数组
4.HSL转换为RGB色彩 (如何将HSL颜色转为RGB颜色)
5.canvas渲染网络图片(旋转,灰阶,饱和度操作)并保存到本地
6.js如何实现rgb与hsl的转换?rgb与hsl互相转换的方法(代码实例)
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。