RGB颜色插值渐变原理

RGB颜色插值渐变原理

本文将要讲述 RGB 颜色插值渐变原理及其实现。

其实 RGB 颜色变换的原理就是线性插值。

例如将颜色RGB(0,0,0)变换为RGB(255,255,255),其中要输出 100 次结果,则增加量就是(255-0)/100,将RGB分开计算也是一样。

同理,RGB(100,200,150)变换为RGB(255,0,255),增加量的计算如下:

1
2
3
R = (255 - 100) / 100 = 1.55;
G = (0 - 200) / 100 = -2;
B = (255 - 150) / 100 = 1.05;

这 100 个片段是有关增加量的递归结果,将片段连续播放,就形成了动画。

下面是一个用HTML5+JavaScript实现的 RGB 颜色插值渐变动画,在线DEMO

代码如下:

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
<!DOCTYPE html>
<html>
<head>
<title>RGB Color Interpolation Gradient</title>
<style>
body > * {
margin: 0 auto;
width: 300px;
}
div {
height: 300px;
background-color: rgb(0, 0, 0);
}
input {
display: block;
width: 100%;
}
</style>
</head>
<body>
<div></div>
<p>R(<span>0</span>):<input type="range" id="red" min="0" max="255" value="0" /></p>
<p>G(<span>0</span>):<input type="range" id="green" min="0" max="255" value="0" /></p>
<p>B(<span>0</span>):<input type="range" id="blue" min="0" max="255" value="0" /></p>
<p>To RGB:<input type="text" value="255,255,255" /><button>Animation</button></p>
<script>
NodeList.prototype.forEach = Array.prototype.forEach;
let rgb = [0, 0, 0];

let div = document.querySelector('div');
let inputs = document.querySelectorAll("input[type='range']");
let toRGB = document.querySelector("input[type='text']");
let button = document.querySelector('button');

let red = inputs[0];
let green = inputs[1];
let blue = inputs[2];

let lock = false;

function change(i) {
let span = inputs[i].parentElement.querySelector('span');

return function (e) {
let value;
if (e) {
value = parseInt(e.target.value);
span.innerHTML = value;
rgb[i] = value;
} else {
value = parseInt(inputs[i].value);
span.innerHTML = value;
}
div.style.backgroundColor =
'rgb(' + Math.round(rgb[0]) + ',' + Math.round(rgb[1]) + ',' + Math.round(rgb[2]) + ')';
};
}

let redChange = change(0);
let greenChange = change(1);
let blueChange = change(2);

red.addEventListener('change', redChange);
green.addEventListener('change', greenChange);
blue.addEventListener('change', blueChange);

button.addEventListener('click', function () {
if (lock) {
return;
}

let finalValue = toRGB.value;
let patternRGB =
/^(([0-9])|([1-9]\d)|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))[,](([0-9])|([1-9]\d)|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))[,](([0-9])|([1-9]\d)|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))$/;

if (!patternRGB.test(finalValue)) {
alert('Format is not correct, you should enter a value like 255,255,255');
return;
}

finalValue = finalValue.split(',');
let rf = finalValue[0];
let gf = finalValue[1];
let bf = finalValue[2];

lock = true;
red.disabled = true;
green.disabled = true;
blue.disabled = true;

rgb[0] = Math.round(rgb[0]);
rgb[1] = Math.round(rgb[1]);
rgb[2] = Math.round(rgb[2]);

let r = rgb[0];
let g = rgb[1];
let b = rgb[2];
let ri = (rf - r) / 100;
let gi = (gf - g) / 100;
let bi = (bf - b) / 100;
setTimeout(function (i) {
i = i || 1;
rgb[0] += ri;
rgb[1] += gi;
rgb[2] += bi;
red.value = rgb[0];
green.value = rgb[1];
blue.value = rgb[2];
redChange();
greenChange();
blueChange();
if (i < 100) {
let f = arguments.callee;
setTimeout(function () {
f(i + 1);
}, 50);
} else {
lock = false;
red.disabled = false;
green.disabled = false;
blue.disabled = false;
}
}, 0);
});
</script>
</body>
</html>
作者

Sea

发布于

2021-06-11

更新于

2023-01-10

许可协议

评论