绘制saturation/brightness渐变
Draw saturation/brightness gradient
我正在尝试在canvas中绘制以下渐变图像,但是右下角有问题。
想要的效果:
当前输出:
我可能遗漏了一些非常简单的东西。
function color(r, g, b) {
var args = Array.prototype.slice.call(arguments);
if (args.length == 1) {
args.push(args[0]);
args.push(args[0]);
} else if (args.length != 3 && args.length != 4) {
return;
}
return "rgb(" + args.join() + ")";
}
function drawPixel(x, y, fill) {
var fill = fill || "black";
context.beginPath();
context.rect(x, y, 1, 1);
context.fillStyle = fill;
context.fill();
context.closePath();
}
var canvas = document.getElementById("primary");
var context = canvas.getContext("2d");
canvas.width = 256;
canvas.height = 256;
for (var x = 0; x < canvas.width; x++) {
for (var y = 0; y < canvas.height; y++) {
var r = 255 - y;
var g = 255 - x - y;
var b = 255 - x - y;
drawPixel(x, y, color(r, g, b));
}
}
#primary {
display: block;
border: 1px solid gray;
}
<canvas id="primary"></canvas>
更新: 在前面的示例中,我只为红色创建了渐变。我也可以使用相同的方法在稍作修改后创建绿色和蓝色渐变,但我不能使用它为随机色调创建渐变。红色、绿色和蓝色很容易,因为当一个通道为 255
时,其他两个具有相同的值。对于随机色调,例如140°,事实并非如此。 H=140
转换为 rgb(0,255,85)
。红色和蓝色不能具有相同的值。这需要不同且更复杂的计算。
Blindman67的回答解决了这个问题。使用内置渐变,您可以轻松地为任何随机色调创建渐变:
jsfiddle。但作为一个很好奇的人,我还是想硬着头皮做,就是这样:
(比起Blindman67的,很慢。。。)
function drawPixel(x, y, fillArray) {
fill = "rgb(" + fillArray.join() + ")" || "black";
context.beginPath();
context.rect(x, y, 1, 1);
context.fillStyle = fill;
context.fill();
}
var canvas = document.getElementById("primary");
var context = canvas.getContext("2d");
var grad1 = [ [255, 255, 255], [0, 0, 0] ]; // brightness
fillPrimary([255, 0, 0]); // initial hue = 0 (red)
$("#secondary").on("input", function() {
var hue = parseInt(this.value, 10);
var clr = hsl2rgb(hue, 100, 50);
fillPrimary(clr);
});
function fillPrimary(rgb) {
var grad2 = [ [255, 255, 255], rgb ]; // saturation
for (var x = 0; x < canvas.width; x++) {
for (var y = 0; y < canvas.height; y++) {
var grad1Change = [
grad1[0][0] - grad1[1][0],
grad1[0][1] - grad1[1][1],
grad1[0][2] - grad1[1][2],
];
var currentGrad1Color = [
grad1[0][0] - (grad1Change[0] * y / 255),
grad1[0][1] - (grad1Change[1] * y / 255),
grad1[0][2] - (grad1Change[2] * y / 255)
];
var grad2Change = [
grad2[0][0] - grad2[1][0],
grad2[0][1] - grad2[1][1],
grad2[0][2] - grad2[1][2],
];
var currentGrad2Color = [
grad2[0][0] - (grad2Change[0] * x / 255),
grad2[0][1] - (grad2Change[1] * x / 255),
grad2[0][2] - (grad2Change[2] * x / 255)
];
var multiplied = [
Math.floor(currentGrad1Color[0] * currentGrad2Color[0] / 255),
Math.floor(currentGrad1Color[1] * currentGrad2Color[1] / 255),
Math.floor(currentGrad1Color[2] * currentGrad2Color[2] / 255),
];
drawPixel(x, y, multiplied);
}
}
}
function hsl2rgb(h, s, l) {
h /= 360;
s /= 100;
l /= 100;
var r, g, b;
if (s == 0) {
r = g = b = l;
} else {
var hue2rgb = function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return [
Math.round(r * 255),
Math.round(g * 255),
Math.round(b * 255),
];
}
#primary {
display: block;
border: 1px solid gray;
}
#secondary {
width: 256px;
height: 15px;
margin-top: 15px;
outline: 0;
display: block;
border: 1px solid gray;
box-sizing: border-box;
-webkit-appearance: none;
background-image: linear-gradient(to right, red 0%, yellow 16.66%, lime 33.33%, cyan 50%, blue 66.66%, violet 83.33%, red 100%);
}
#secondary::-webkit-slider-thumb {
-webkit-appearance: none;
height: 25px;
width: 10px;
border-radius: 10px;
background-color: rgb(230, 230, 230);
border: 1px solid gray;
box-shadow: inset 0 0 2px rgba(255, 255, 255, 1), 0 0 2px rgba(255, 255, 255, 1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="primary" width="256" height="256"></canvas>
<input type="range" min="0" max="360" step="1" value="0" id="secondary" />
好的,我知道问题出在哪里了。虽然垂直范围始终介于 [0,255]
之间,但水平范围始终介于 [0,r]
之间。所以 g
和 b
不能大于 r
(呃!)。
function color(r, g, b) {
var args = Array.prototype.slice.call(arguments);
if (args.length == 1) {
args.push(args[0]);
args.push(args[0]);
} else if (args.length != 3 && args.length != 4) {
return;
}
return "rgb(" + args.join() + ")";
}
function drawPixel(x, y, fill) {
var fill = fill || "black";
context.beginPath();
context.rect(x, y, 1, 1);
context.fillStyle = fill;
context.fill();
context.closePath();
}
var canvas = document.getElementById("primary");
var context = canvas.getContext("2d");
canvas.width = 256;
canvas.height = 256;
for (var x = 0; x < canvas.width; x++) {
for (var y = 0; y < canvas.height; y++) {
var r = 255 - y;
var g = b = r - Math.floor((x / 255) * r); // tada!
drawPixel(x, y, color(r, g, b));
}
}
#primary {
display: block;
border: 1px solid gray;
}
<canvas id="primary"></canvas>
使用渐变。
您可以让 GPU 完成 you.The 二维合成操作的大部分处理 multiply
有效地将每个像素的两种颜色相乘。因此,对于每个通道和每个像素 colChanDest = Math.floor(colChanDest * (colChanSrc / 255))
是通过 GPU 的大规模并行处理能力完成的,而不是单核(JavaScript 执行上下文)上的低共享线程 运行。
两个梯度
一个是背景从上到下白到黑
var gradB = ctx.createLinearGradient(0,0,0,255);
gradB.addColorStop(0,"white");
gradB.addColorStop(1,"black");
另一个是从左到右由透明渐变到不透明的Hue
var swatchHue
var col = "rgba(0,0,0,0)"
var gradC = ctx.createLinearGradient(0,0,255,0);
gradC.addColorStop(0,``hsla(${hueValue},100%,50%,0)``);
gradC.addColorStop(1,``hsla(${hueValue},100%,50%,1)``);
注意 上面的字符串引号在 SO 上没有正确呈现所以我只是将它们加倍以显示,使用单引号作为演示片段中的做法。
渲染
然后将两者叠加,首先是背景(灰度),然后进行合成操作"multiply"
ctx.fillStyle = gradB;
ctx.fillRect(0,0,255,255);
ctx.fillStyle = gradC;
ctx.globalCompositeOperation = "multiply";
ctx.fillRect(0,0,255,255);
ctx.globalCompositeOperation = "source-over";
仅适用于 Hue
重要的是颜色(色调)是纯色值,不能使用随机的rgb值。如果您选择了 rgb 值,则需要从 rgb 中提取色调值。
以下函数会将 RGB 值转换为 HSL 颜色
function rgbToLSH(red, green, blue, result = {}){
value hue, sat, lum, min, max, dif, r, g, b;
r = red/255;
g = green/255;
b = blue/255;
min = Math.min(r,g,b);
max = Math.max(r,g,b);
lum = (min+max)/2;
if(min === max){
hue = 0;
sat = 0;
}else{
dif = max - min;
sat = lum > 0.5 ? dif / (2 - max - min) : dif / (max + min);
switch (max) {
case r:
hue = (g - b) / dif;
break;
case g:
hue = 2 + ((b - r) / dif);
break;
case b:
hue = 4 + ((r - g) / dif);
break;
}
hue *= 60;
if (hue < 0) {
hue += 360;
}
}
result.lum = lum * 255;
result.sat = sat * 255;
result.hue = hue;
return result;
}
把它们放在一起
该示例每 3 秒渲染一个随机红、绿、蓝值的样本。
请注意,此示例使用 Balel,因此它可以在 IE 上运行
var canvas = document.createElement("canvas");
canvas.width = canvas.height = 255;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
function drawSwatch(r, g, b) {
var col = rgbToLSH(r, g, b);
var gradB = ctx.createLinearGradient(0, 0, 0, 255);
gradB.addColorStop(0, "white");
gradB.addColorStop(1, "black");
var gradC = ctx.createLinearGradient(0, 0, 255, 0);
gradC.addColorStop(0, `hsla(${Math.floor(col.hue)},100%,50%,0)`);
gradC.addColorStop(1, `hsla(${Math.floor(col.hue)},100%,50%,1)`);
ctx.fillStyle = gradB;
ctx.fillRect(0, 0, 255, 255);
ctx.fillStyle = gradC;
ctx.globalCompositeOperation = "multiply";
ctx.fillRect(0, 0, 255, 255);
ctx.globalCompositeOperation = "source-over";
}
function rgbToLSH(red, green, blue, result = {}) {
var hue, sat, lum, min, max, dif, r, g, b;
r = red / 255;
g = green / 255;
b = blue / 255;
min = Math.min(r, g, b);
max = Math.max(r, g, b);
lum = (min + max) / 2;
if (min === max) {
hue = 0;
sat = 0;
} else {
dif = max - min;
sat = lum > 0.5 ? dif / (2 - max - min) : dif / (max + min);
switch (max) {
case r:
hue = (g - b) / dif;
break;
case g:
hue = 2 + ((b - r) / dif);
break;
case b:
hue = 4 + ((r - g) / dif);
break;
}
hue *= 60;
if (hue < 0) {
hue += 360;
}
}
result.lum = lum * 255;
result.sat = sat * 255;
result.hue = hue;
return result;
}
function drawRandomSwatch() {
drawSwatch(Math.random() * 255, Math.random() * 255, Math.random() * 255);
setTimeout(drawRandomSwatch, 3000);
}
drawRandomSwatch();
要从 x 和 y 坐标计算颜色,您需要计算色相,然后是饱和度和值以获得 hsv 颜色(注意 hsl 和 hsv 是不同的颜色模型)
// saturation and value are clamped to prevent rounding errors creating wrong colour
var rgbArray = hsv_to_rgb(
hue, // as used to create the swatch
Math.max(0, Math.min(1, x / 255)),
Math.max(0, Math.min(1, 1 - y / 255))
);
获取 h、s、v 颜色的 r、g、b 值的函数。
/* Function taken from datGUI.js
Web site https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage
// h 0-360, s 0-1, and v 0-1
*/
function hsv_to_rgb(h, s, v) {
var hi = Math.floor(h / 60) % 6;
var f = h / 60 - Math.floor(h / 60);
var p = v * (1.0 - s);
var q = v * (1.0 - f * s);
var t = v * (1.0 - (1.0 - f) * s);
var c = [
[v, t, p],
[q, v, p],
[p, v, t],
[p, q, v],
[t, p, v],
[v, p, q]
][hi];
return {
r: c[0] * 255,
g: c[1] * 255,
b: c[2] * 255
};
}
我必须使用 OpenGL 来完成此操作,而 Blindman67 的答案是我找到的唯一资源。
最后,我通过在彼此之上绘制 3 个矩形来做到这一点。
- 全白
- 透明红色到不透明红色,横向
- 透明黑色到不透明黑色,垂直
我正在尝试在canvas中绘制以下渐变图像,但是右下角有问题。
想要的效果:
当前输出:
我可能遗漏了一些非常简单的东西。
function color(r, g, b) {
var args = Array.prototype.slice.call(arguments);
if (args.length == 1) {
args.push(args[0]);
args.push(args[0]);
} else if (args.length != 3 && args.length != 4) {
return;
}
return "rgb(" + args.join() + ")";
}
function drawPixel(x, y, fill) {
var fill = fill || "black";
context.beginPath();
context.rect(x, y, 1, 1);
context.fillStyle = fill;
context.fill();
context.closePath();
}
var canvas = document.getElementById("primary");
var context = canvas.getContext("2d");
canvas.width = 256;
canvas.height = 256;
for (var x = 0; x < canvas.width; x++) {
for (var y = 0; y < canvas.height; y++) {
var r = 255 - y;
var g = 255 - x - y;
var b = 255 - x - y;
drawPixel(x, y, color(r, g, b));
}
}
#primary {
display: block;
border: 1px solid gray;
}
<canvas id="primary"></canvas>
更新: 在前面的示例中,我只为红色创建了渐变。我也可以使用相同的方法在稍作修改后创建绿色和蓝色渐变,但我不能使用它为随机色调创建渐变。红色、绿色和蓝色很容易,因为当一个通道为 255
时,其他两个具有相同的值。对于随机色调,例如140°,事实并非如此。 H=140
转换为 rgb(0,255,85)
。红色和蓝色不能具有相同的值。这需要不同且更复杂的计算。
Blindman67的回答解决了这个问题。使用内置渐变,您可以轻松地为任何随机色调创建渐变: jsfiddle。但作为一个很好奇的人,我还是想硬着头皮做,就是这样:
(比起Blindman67的,很慢。。。)
function drawPixel(x, y, fillArray) {
fill = "rgb(" + fillArray.join() + ")" || "black";
context.beginPath();
context.rect(x, y, 1, 1);
context.fillStyle = fill;
context.fill();
}
var canvas = document.getElementById("primary");
var context = canvas.getContext("2d");
var grad1 = [ [255, 255, 255], [0, 0, 0] ]; // brightness
fillPrimary([255, 0, 0]); // initial hue = 0 (red)
$("#secondary").on("input", function() {
var hue = parseInt(this.value, 10);
var clr = hsl2rgb(hue, 100, 50);
fillPrimary(clr);
});
function fillPrimary(rgb) {
var grad2 = [ [255, 255, 255], rgb ]; // saturation
for (var x = 0; x < canvas.width; x++) {
for (var y = 0; y < canvas.height; y++) {
var grad1Change = [
grad1[0][0] - grad1[1][0],
grad1[0][1] - grad1[1][1],
grad1[0][2] - grad1[1][2],
];
var currentGrad1Color = [
grad1[0][0] - (grad1Change[0] * y / 255),
grad1[0][1] - (grad1Change[1] * y / 255),
grad1[0][2] - (grad1Change[2] * y / 255)
];
var grad2Change = [
grad2[0][0] - grad2[1][0],
grad2[0][1] - grad2[1][1],
grad2[0][2] - grad2[1][2],
];
var currentGrad2Color = [
grad2[0][0] - (grad2Change[0] * x / 255),
grad2[0][1] - (grad2Change[1] * x / 255),
grad2[0][2] - (grad2Change[2] * x / 255)
];
var multiplied = [
Math.floor(currentGrad1Color[0] * currentGrad2Color[0] / 255),
Math.floor(currentGrad1Color[1] * currentGrad2Color[1] / 255),
Math.floor(currentGrad1Color[2] * currentGrad2Color[2] / 255),
];
drawPixel(x, y, multiplied);
}
}
}
function hsl2rgb(h, s, l) {
h /= 360;
s /= 100;
l /= 100;
var r, g, b;
if (s == 0) {
r = g = b = l;
} else {
var hue2rgb = function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return [
Math.round(r * 255),
Math.round(g * 255),
Math.round(b * 255),
];
}
#primary {
display: block;
border: 1px solid gray;
}
#secondary {
width: 256px;
height: 15px;
margin-top: 15px;
outline: 0;
display: block;
border: 1px solid gray;
box-sizing: border-box;
-webkit-appearance: none;
background-image: linear-gradient(to right, red 0%, yellow 16.66%, lime 33.33%, cyan 50%, blue 66.66%, violet 83.33%, red 100%);
}
#secondary::-webkit-slider-thumb {
-webkit-appearance: none;
height: 25px;
width: 10px;
border-radius: 10px;
background-color: rgb(230, 230, 230);
border: 1px solid gray;
box-shadow: inset 0 0 2px rgba(255, 255, 255, 1), 0 0 2px rgba(255, 255, 255, 1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="primary" width="256" height="256"></canvas>
<input type="range" min="0" max="360" step="1" value="0" id="secondary" />
好的,我知道问题出在哪里了。虽然垂直范围始终介于 [0,255]
之间,但水平范围始终介于 [0,r]
之间。所以 g
和 b
不能大于 r
(呃!)。
function color(r, g, b) {
var args = Array.prototype.slice.call(arguments);
if (args.length == 1) {
args.push(args[0]);
args.push(args[0]);
} else if (args.length != 3 && args.length != 4) {
return;
}
return "rgb(" + args.join() + ")";
}
function drawPixel(x, y, fill) {
var fill = fill || "black";
context.beginPath();
context.rect(x, y, 1, 1);
context.fillStyle = fill;
context.fill();
context.closePath();
}
var canvas = document.getElementById("primary");
var context = canvas.getContext("2d");
canvas.width = 256;
canvas.height = 256;
for (var x = 0; x < canvas.width; x++) {
for (var y = 0; y < canvas.height; y++) {
var r = 255 - y;
var g = b = r - Math.floor((x / 255) * r); // tada!
drawPixel(x, y, color(r, g, b));
}
}
#primary {
display: block;
border: 1px solid gray;
}
<canvas id="primary"></canvas>
使用渐变。
您可以让 GPU 完成 you.The 二维合成操作的大部分处理 multiply
有效地将每个像素的两种颜色相乘。因此,对于每个通道和每个像素 colChanDest = Math.floor(colChanDest * (colChanSrc / 255))
是通过 GPU 的大规模并行处理能力完成的,而不是单核(JavaScript 执行上下文)上的低共享线程 运行。
两个梯度
一个是背景从上到下白到黑
var gradB = ctx.createLinearGradient(0,0,0,255); gradB.addColorStop(0,"white"); gradB.addColorStop(1,"black");
另一个是从左到右由透明渐变到不透明的Hue
var swatchHue var col = "rgba(0,0,0,0)" var gradC = ctx.createLinearGradient(0,0,255,0); gradC.addColorStop(0,``hsla(${hueValue},100%,50%,0)``); gradC.addColorStop(1,``hsla(${hueValue},100%,50%,1)``);
注意 上面的字符串引号在 SO 上没有正确呈现所以我只是将它们加倍以显示,使用单引号作为演示片段中的做法。
渲染
然后将两者叠加,首先是背景(灰度),然后进行合成操作"multiply"
ctx.fillStyle = gradB;
ctx.fillRect(0,0,255,255);
ctx.fillStyle = gradC;
ctx.globalCompositeOperation = "multiply";
ctx.fillRect(0,0,255,255);
ctx.globalCompositeOperation = "source-over";
仅适用于 Hue
重要的是颜色(色调)是纯色值,不能使用随机的rgb值。如果您选择了 rgb 值,则需要从 rgb 中提取色调值。
以下函数会将 RGB 值转换为 HSL 颜色
function rgbToLSH(red, green, blue, result = {}){
value hue, sat, lum, min, max, dif, r, g, b;
r = red/255;
g = green/255;
b = blue/255;
min = Math.min(r,g,b);
max = Math.max(r,g,b);
lum = (min+max)/2;
if(min === max){
hue = 0;
sat = 0;
}else{
dif = max - min;
sat = lum > 0.5 ? dif / (2 - max - min) : dif / (max + min);
switch (max) {
case r:
hue = (g - b) / dif;
break;
case g:
hue = 2 + ((b - r) / dif);
break;
case b:
hue = 4 + ((r - g) / dif);
break;
}
hue *= 60;
if (hue < 0) {
hue += 360;
}
}
result.lum = lum * 255;
result.sat = sat * 255;
result.hue = hue;
return result;
}
把它们放在一起
该示例每 3 秒渲染一个随机红、绿、蓝值的样本。
请注意,此示例使用 Balel,因此它可以在 IE 上运行
var canvas = document.createElement("canvas");
canvas.width = canvas.height = 255;
var ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
function drawSwatch(r, g, b) {
var col = rgbToLSH(r, g, b);
var gradB = ctx.createLinearGradient(0, 0, 0, 255);
gradB.addColorStop(0, "white");
gradB.addColorStop(1, "black");
var gradC = ctx.createLinearGradient(0, 0, 255, 0);
gradC.addColorStop(0, `hsla(${Math.floor(col.hue)},100%,50%,0)`);
gradC.addColorStop(1, `hsla(${Math.floor(col.hue)},100%,50%,1)`);
ctx.fillStyle = gradB;
ctx.fillRect(0, 0, 255, 255);
ctx.fillStyle = gradC;
ctx.globalCompositeOperation = "multiply";
ctx.fillRect(0, 0, 255, 255);
ctx.globalCompositeOperation = "source-over";
}
function rgbToLSH(red, green, blue, result = {}) {
var hue, sat, lum, min, max, dif, r, g, b;
r = red / 255;
g = green / 255;
b = blue / 255;
min = Math.min(r, g, b);
max = Math.max(r, g, b);
lum = (min + max) / 2;
if (min === max) {
hue = 0;
sat = 0;
} else {
dif = max - min;
sat = lum > 0.5 ? dif / (2 - max - min) : dif / (max + min);
switch (max) {
case r:
hue = (g - b) / dif;
break;
case g:
hue = 2 + ((b - r) / dif);
break;
case b:
hue = 4 + ((r - g) / dif);
break;
}
hue *= 60;
if (hue < 0) {
hue += 360;
}
}
result.lum = lum * 255;
result.sat = sat * 255;
result.hue = hue;
return result;
}
function drawRandomSwatch() {
drawSwatch(Math.random() * 255, Math.random() * 255, Math.random() * 255);
setTimeout(drawRandomSwatch, 3000);
}
drawRandomSwatch();
要从 x 和 y 坐标计算颜色,您需要计算色相,然后是饱和度和值以获得 hsv 颜色(注意 hsl 和 hsv 是不同的颜色模型)
// saturation and value are clamped to prevent rounding errors creating wrong colour
var rgbArray = hsv_to_rgb(
hue, // as used to create the swatch
Math.max(0, Math.min(1, x / 255)),
Math.max(0, Math.min(1, 1 - y / 255))
);
获取 h、s、v 颜色的 r、g、b 值的函数。
/* Function taken from datGUI.js
Web site https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage
// h 0-360, s 0-1, and v 0-1
*/
function hsv_to_rgb(h, s, v) {
var hi = Math.floor(h / 60) % 6;
var f = h / 60 - Math.floor(h / 60);
var p = v * (1.0 - s);
var q = v * (1.0 - f * s);
var t = v * (1.0 - (1.0 - f) * s);
var c = [
[v, t, p],
[q, v, p],
[p, v, t],
[p, q, v],
[t, p, v],
[v, p, q]
][hi];
return {
r: c[0] * 255,
g: c[1] * 255,
b: c[2] * 255
};
}
我必须使用 OpenGL 来完成此操作,而 Blindman67 的答案是我找到的唯一资源。 最后,我通过在彼此之上绘制 3 个矩形来做到这一点。
- 全白
- 透明红色到不透明红色,横向
- 透明黑色到不透明黑色,垂直