将一天中的时间绘制成固定的颜色渐变?
Plotting times of day to a fixed color gradient?
我正在做一个约会应用。
我有这个渐变结构(在 Pixelmator 中创建),我想用它来标记一天中的时间:
在预期的方案中,上午 8 点为纯绿色,中午 12 点为纯黄色,晚上 8 点为纯蓝色。
我需要一个算法来获取一天中的时间并将它们变成那些颜色,但我无法弄清楚,尤其是从中午到晚上。
这些颜色是使用 HSB 值系统组成的:所有颜色的 S 和 B 均为 100%,色调值从左到右分别为 121(绿色)、60(黄色)和 229(蓝色)。
从绿色到黄色(从早上到中午)的进展很简单,因为它只是从 121 到 60 的线性缩放,但从黄色到蓝色(中午到晚上)则不然;如果您考虑以线性方式从 60 到 229 将首先复制从绿色到黄色的渐变,只是以相反的顺序,然后从绿色到蓝色,那么这就很清楚了。换句话说,严格的线性渐变会使渐变看起来更像这样:
任何人都可以指出正确的方向来理解如何制作我在这里需要的算法吗?我是否必须使用不同的颜色值系统,例如 RGB?
在此先感谢您的帮助!
这是一个算法:
- 将小时转换为 24 小时并将分钟和秒转换为分数或小数(即 8:30 -> 8.5,8:20 -> 25/3)
- 小时减去 8(现在我们有一个从 0 到 12 的数字)
- 如果小时 h 在 0 到 4 之间,我们将执行
((-h+4)*(61/4))+60
否则我们会 ((-h+12)*(191/8))-131
- 如果值为负数,我们将加上 360
我们得到的值就是颜色的色调值
Pablo-No 给出了一个合理的答案,如果黄色-> 蓝色过渡通过红色是可以的。但是 OP 的原始图片并没有经过红色,而是经过了某种灰色。或许应该用饱和度S来尝试实现:
// Assume time is a real value between 8 (8am) and 20 (8pm)
// H is between 0 and 360
// S and B are between 0 and 100
B = 255;
if (time < 12)
{
// Before noon, linearly go from H=121 (green) to H=60 (yellow)
H = (time - 8) * (60-121)/4.0 + 121;
S = 100;
}
else
{
// After noon, linearly go from H=60 (green) to H=229 (blue)
// But in the middle, where the color goes green, linearly scale
// Saturation down to zero and back to 100.
H = (time - 12) * (229-60)/8.0 + 60;
auto secondGreenTime = (121-60)*8.0/(229-60) + 12;
if (time < secondGreenTime)
S = (time - 12) * (-100.0)/(secondGreenTime-12) + 100;
else
S = (time - secondGreenTime) * 100.0/(20-secondGreenTime);
}
Pixelmator 看起来像是在使用 RGB 渐变。演示:
const canvas = document.getElementById("gradient");
const ctx = canvas.getContext("2d");
for (let i = 0; i < canvas.width; i++) {
const alpha = (i + 0.5) / canvas.width;
const r = 2 * Math.min(alpha, 1 - alpha);
const g = Math.min(1, 2 * (1 - alpha));
const b = Math.max(0, 2 * alpha - 1);
ctx.fillStyle = `rgba(${255*r},${255*g},${255*b})`
ctx.fillRect(i, 0, 1, canvas.height);
}
<canvas id="gradient" width="240" height="40">
我正在做一个约会应用。
我有这个渐变结构(在 Pixelmator 中创建),我想用它来标记一天中的时间:
在预期的方案中,上午 8 点为纯绿色,中午 12 点为纯黄色,晚上 8 点为纯蓝色。
我需要一个算法来获取一天中的时间并将它们变成那些颜色,但我无法弄清楚,尤其是从中午到晚上。
这些颜色是使用 HSB 值系统组成的:所有颜色的 S 和 B 均为 100%,色调值从左到右分别为 121(绿色)、60(黄色)和 229(蓝色)。
从绿色到黄色(从早上到中午)的进展很简单,因为它只是从 121 到 60 的线性缩放,但从黄色到蓝色(中午到晚上)则不然;如果您考虑以线性方式从 60 到 229 将首先复制从绿色到黄色的渐变,只是以相反的顺序,然后从绿色到蓝色,那么这就很清楚了。换句话说,严格的线性渐变会使渐变看起来更像这样:
任何人都可以指出正确的方向来理解如何制作我在这里需要的算法吗?我是否必须使用不同的颜色值系统,例如 RGB?
在此先感谢您的帮助!
这是一个算法:
- 将小时转换为 24 小时并将分钟和秒转换为分数或小数(即 8:30 -> 8.5,8:20 -> 25/3)
- 小时减去 8(现在我们有一个从 0 到 12 的数字)
- 如果小时 h 在 0 到 4 之间,我们将执行
((-h+4)*(61/4))+60
否则我们会((-h+12)*(191/8))-131
- 如果值为负数,我们将加上 360
我们得到的值就是颜色的色调值
Pablo-No 给出了一个合理的答案,如果黄色-> 蓝色过渡通过红色是可以的。但是 OP 的原始图片并没有经过红色,而是经过了某种灰色。或许应该用饱和度S来尝试实现:
// Assume time is a real value between 8 (8am) and 20 (8pm)
// H is between 0 and 360
// S and B are between 0 and 100
B = 255;
if (time < 12)
{
// Before noon, linearly go from H=121 (green) to H=60 (yellow)
H = (time - 8) * (60-121)/4.0 + 121;
S = 100;
}
else
{
// After noon, linearly go from H=60 (green) to H=229 (blue)
// But in the middle, where the color goes green, linearly scale
// Saturation down to zero and back to 100.
H = (time - 12) * (229-60)/8.0 + 60;
auto secondGreenTime = (121-60)*8.0/(229-60) + 12;
if (time < secondGreenTime)
S = (time - 12) * (-100.0)/(secondGreenTime-12) + 100;
else
S = (time - secondGreenTime) * 100.0/(20-secondGreenTime);
}
Pixelmator 看起来像是在使用 RGB 渐变。演示:
const canvas = document.getElementById("gradient");
const ctx = canvas.getContext("2d");
for (let i = 0; i < canvas.width; i++) {
const alpha = (i + 0.5) / canvas.width;
const r = 2 * Math.min(alpha, 1 - alpha);
const g = Math.min(1, 2 * (1 - alpha));
const b = Math.max(0, 2 * alpha - 1);
ctx.fillStyle = `rgba(${255*r},${255*g},${255*b})`
ctx.fillRect(i, 0, 1, canvas.height);
}
<canvas id="gradient" width="240" height="40">