当前位置 : 主页 > 编程语言 > 其它开发 >

一个“会”用代码调色的Web前端开发,绝对是一个吃香的设计师

来源:互联网 收集:自由互联 发布时间:2022-05-30
用代码着色,一种程序化的设计绝佳方法。学习创建美丽、鼓舞人心和独特的调色板/组合,所有都会让你的网页和文本编辑变得更加舒适!废话不多说,今天带着大家认识下LCH颜色表达

用代码着色,一种程序化的设计绝佳方法。学习创建美丽、鼓舞人心和独特的调色板/组合,所有都会让你的网页和文本编辑变得更加舒适!废话不多说,今天带着大家认识下LCH颜色表达方式!

颜色是强大的——它可以从根本上改变我们的情绪,激励我们,并帮助我们以一种其他事物无法做到的方式表达自己。在设计中我们常听到的是RGB(常用的网页颜色三元素)以及打印的CMYK;为了更好的视觉效果,我们也需要了解LCH颜色!这样可以让我们的网页更加有层次感,高级感十足!当你了解了这篇文章后,绝对会提升你的审美观。老板看了你写的网页,绝对是赞不绝口。还要给你加薪!

 

什么是LCH颜色

 

LCH 代表亮度 (颜色的深/浅)色度 (颜色的鲜艳/饱和度)色调 (颜色是红色、绿色、蓝色……)

简而言之,LCH 是一种与 RGB 或 HSL 一样的颜色表示方式,但有一些显着的优势——对于本教程来说最重要的是它的感知均匀性。在本教程中,我们几乎只使用 LCH 颜色。我知道这听起来有点吓人,但我保证不会;让我告诉你这意味着什么!

首先,看看这两对 HSL 颜色: 

 

请注意,尽管顶部和底部对具有相同的 20 度色相变化,但我们 实际 看到的差异却大不相同?这种不平衡的存在是因为 HSL 在感知上 并不 统一

现在看看同样的实验,这次使用 LCH 颜色:

HSL 和 LCH 之间的色调值不能完美对齐。在 LCH 中,0 的色调更粉红色,而在 HSL 中,它是纯红色。 啊,好多了!

这里看到的色调变化更加平衡,因为 LCH 在 感知上是均匀的。 接下来,我们来看看另外两种 HSL 颜色: 

 

 

 

这两种颜色具有相同的亮度值,但在我们的人眼看来却大不相同。左边的黄色比右边的蓝色“亮”得多。

这是一个类似的设置,但使用的是 LCH 颜色而不是 HSL: 

 

 

这还差不多!如上图所示,LCH 中的亮度值更准确地表示了我们所感知的内容——这与 LCH 的均匀色调分布相结合,将使我们 在创建和谐的调色板时更加轻松 。 

目前,这就是我们需要知道的全部内容,但如果您想了解更多信息,我强烈推荐Lea Verou 撰写的这篇文章。 

我们将在本教程中使用一个库,但本机 LCH 支持正在走向浏览器!事实上,它已经存在于 Safari 中,其他浏览器目前也在使用它。

 

跟着

 

在我们编写任何代码之前,我们需要一个简单的开发环境。此设置完全由您选择,但我建议您启动 CodePen 或者vscode以跟随示例,然后在需要时移至自定义设置/存储库。真的,我们在这里只需要一个 HTML/JavaScript 文件,我们将使用 Skypack 进行所有库导入,因此不需要任何花哨的构建过程等。

 

功能#1——“科学”

 

好的!首先,我们使用“传统”颜色理论生成颜色。要开始使用此方法,让我们看一下称为色轮的东西:

 

 

 

看起来熟悉?

色轮是色彩空间中色调的视觉表示。上面的轮子代表 LCH 中的色调,以 30 度的步长递增,从 0 度到 360 度——这是一种成熟的格式。事实上,数百年来,我们一直在使用轮子来寻找可以很好地协同工作的颜色!

这是如何做:

我们从基色开始。然后,我们围绕轮子旋转一定度数一定次数;为了完美 互补的 调色板,我们移动 180 度一次: 

 

 

 

迷人的!对于 三元 调色板,我们移动 120 度,两次: 

 

 

 

 

看看这是怎么回事?通过改变步数和旋转量,我们可以创建几个“经典”调色板:

 

 

 

代码  
function adjustHue(val) {
  if (val < 0) val += Math.ceil(-val / 360) * 360;

  return val % 360;
}

function createScientificPalettes(baseColor) {
  const targetHueSteps = {
    analogous: [0, 30, 60],
    triadic: [0, 120, 240],
    tetradic: [0, 90, 180, 270],
    complementary: [0, 180],
    splitComplementary: [0, 150, 210]
  };

  const palettes = {};

  for (const type of Object.keys(targetHueSteps)) {
    palettes[type] = targetHueSteps[type].map((step) => ({
      l: baseColor.l,
      c: baseColor.c,
      h: adjustHue(baseColor.h + step),
      mode: "lch"
    }));
  }

  return palettes;
}

要打破这一点:

    1. 定义一个createScientificPalettes需要单个baseColor参数的函数。

    2. 定义几个“经典”调色板的色调步骤。

    3. 对于每种调色板类型:迭代每个色调步长,将步长值添加到基本色调,并存储生成的颜色——确保其chroma和lightness值与基本色调匹配。使用一个小adjustHue函数来确保所有色调值都在 0 到 360 之间。

    4. 以 LCH 格式返回调色板。  

用法:

惊人的!我们可以createScientificPalettes这样调用我们的函数:

const baseColor = {
  l: 50,
  c: 100,
  h: 0,
  mode: "lch"
};

const palettes = createScientificPalettes(baseColor);

在上面的示例中,我们传递一个baseColor对象,该函数返回各种调色板,所有这些调色板都以该基础为中心。多亏了 LCH,这些调色板中颜色的亮度和强度将在视觉上保持一致,并且色调调制高度准确;这对于可访问性非常有用,因为与其他颜色空间不同,调色板中的每种颜色都将具有相同的 感知 对比度。 

凉爽的!现在剩下要做的就是将 LCH 颜色转换为更可用的格式。为此,我们可以使用Culori(本教程中使用的一个出色的颜色实用程序库)将 LCH 对象转换为 HEX:

import { formatHex } from "https://cdn.skypack.dev/culori@2.0.0";

const baseColor = {
  l: 50,
  c: 100,
  h: 0,
  mode: "lch"
};

const palettes = createScientificPalettes(baseColor);
const triadicHex = palettes.triadic.map((colorLCH) => formatHex(colorLCH));

// ["#ff007c", "#1f8a00", "#0091ff"]

 

 Culori 需要mode对所有颜色对象进行显式处理。您会注意到这包含在本教程的代码示例中。 

对于我们的第一个函数,就是这样!让我们看看我们如何在现实生活中使用它。

实际应用

使用代码(以编程方式) 创建我们的调色板的一个好处 是它使快速原型设计/实验变得非常容易。比如说,我们正在做一个设计,完全不知道要使用什么调色板。使用我们的createScientificPalettes函数以及一些简单的 CSS 自定义属性,我们可以生成近乎无限的调色板并使用我们的 UI 实时测试它们! 

这是一个 CodePen 来演示:

 

 

 

 

 

挑战

 

现在,我们的createScientificPalettes函数适用于所有调色板类型,除了 单色。您可以更新它以支持单色调色板吗? 

 

功能#2——“发现”

 

因此,此功能与前一个功能相似,但有 很大 的不同。我们仍在生成“经典”颜色组合,但不是科学地计算它们 (将设置“步骤”添加到基色的色调中), 我们正在 发现 它们!这是正确的; 我们的发现功能将采用一系列颜色并在其中找到最佳的调色板匹配——类似的、三色的、四色的等。 

 

这是一个图解示例:

 

使用此功能,我们可以在图像、颜色数据集等中发现漂亮的调色板!让我们看看它是如何工作的。

代码

 

import {
  nearest,
  differenceEuclidean,
} from "https://cdn.skypack.dev/culori@2.0.0";

function isColorEqual(c1, c2) {
  return c1.h === c2.h && c1.l === c2.l && c1.c === c2.c;
}

function discoverPalettes(colors) {
  const palettes = {};

  for (const color of colors) {
    const targetPalettes = createScientificPalettes(color);

    for (const paletteType of Object.keys(targetPalettes)) {
      const palette = [];
      let variance = 0;

      for (const targetColor of targetPalettes[paletteType]) {
        // filter out colors already in the palette
        const availableColors = colors.filter(
          (color1) => !palette.some((color2) => isColorEqual(color1, color2))
        );

        const match = nearest(
          availableColors,
          differenceEuclidean("lch")
        )(targetColor)[0];

        variance += differenceEuclidean("lch")(targetColor, match);

        palette.push(match);
      }

      if (!palettes[paletteType] || variance < palettes[paletteType].variance) {
        palettes[paletteType] = {
          colors: palette,
          variance
        };
      }
    }
  }

  return palettes;
}
  1. 将 LCH 颜色数组传递给discoverPalettes函数。 

  2. createScientificPalettes对于每种颜色,使用我们的函数 基于它创建“最佳”目标调色板。

  3. 对于每个调色板,为其每种颜色找到最接近的匹配。我们在这里使用 Culori 的最接近和差分欧几里得函数计算颜色匹配。 

  4. 确定“发现”调色板与目标的相似/不同程度。记录最接近的调色板匹配。 

  5. 返回每个调色板类型最接近的匹配! 

惊人的!这种方法非常令人兴奋,因为它的操作方式与人类非常相似——查看选择的颜色并找到最好的(但绝不是 完美的)调色板;这很棒,因为有时,纯粹的数学色彩理论可能会显得有些枯燥/可预测。 

 

用法  

作为快速参考,以下是我们如何使用discoverPalettes十六进制颜色数组: 

 

import {
  converter,
} from "https://cdn.skypack.dev/culori@2.0.0";

const toLCH = converter("lch");

const baseColors = [
  "#FFB97A",
  "#FF957C",
  "#FF727F",
  "#FF5083",
  "#F02F87",
  "#C70084",
  "#9A007F",
  "#6A0076",
  "#33006B"
];

const baseColorsLCH = baseColors.map((color) => toLCH(color));

const palettes = discoverPalettes(baseColorsLCH);

// { analogous: [...], complementary: [...], ... }

 至少需要四种颜色才能正常工作。 discoverPalettes

 

实际应用

最引人注目的方面之一discoverPalettes是它能够从几乎任何来源中提取连贯的颜色组合。就是这样,根据Unsplash中的图像发现调色板:

 

 

 

酷吧?从照片中提取调色板是一种奇妙的工作方式,当您遇到想法时,并且discoverPalettes使过程 非常容易。这种方法以前只能通过“神奇的”颜色生成器/应用程序获得,现在就在我们的指尖,可以进行调整、迭代和改进,以适应我们自己的个人用例和偏好!

挑战

现在,我们的discoverPalettes函数可以在一组颜色中找到最佳匹配,但控制起来并不容易。您可以为其选择添加一定程度的偏差/权重吗?例如,您如何修改函数以优先考虑更亮的颜色?

 

功能#3——“色相转换”

对于我们的第三个也是最后一个功能,我们将从像素艺术世界中汲取灵感!

通常在向精灵添加阴影/高光时,像素艺术家不仅会调制颜色的亮度/色度(如果使用 HSL,则为饱和度),还会改变其色调。这是一个关于这个主题的优秀视频,但简而言之,这就是它的样子:

 

 真好看!当颜色变浅时,它的色调就会上移;当它变暗时,它会向下移动。当巧妙地应用时,这种技术有助于确保颜色的色调/色调生动而有影响力。当“拨号”一点时,它是生成令人惊叹的独立调色板的绝妙方式。

代码
function adjustHue(val) {
  if (val < 0) val += Math.ceil(-val / 360) * 360;

  return val % 360;
}

function map(n, start1, end1, start2, end2) {
  return ((n - start1) / (end1 - start1)) * (end2 - start2) + start2;
}

function createHueShiftPalette(opts) {
  const { base, minLightness, maxLightness, hueStep } = opts;

  const palette = [base];

  for (let i = 1; i < 5; i++) {
    const hueDark = adjustHue(base.h - hueStep * i);
    const hueLight = adjustHue(base.h + hueStep * i);
    const lightnessDark = map(i, 0, 4, base.l, minLightness);
    const lightnessLight = map(i, 0, 4, base.l, maxLightness);
    const chroma = base.c;

    palette.push({
      l: lightnessDark,
      c: chroma,
      h: hueDark,
      mode: "lch"
    });

    palette.unshift({
      l: lightnessLight,
      c: chroma,
      h: hueLight,
      mode: "lch"
    });
  }

  return palette;
}

将其分解为以下步骤: 

  1. 将基色、最小/最大亮度和色调步长参数传递给createHueShiftPalette函数。最小/最大亮度值决定了我们的调色板在任一极端时有多暗/多亮。该步骤控制每种颜色的色调变化量。

  2. 将基色存储在数组中。在上图中,这是中间颜色。 

  3. 创建一个迭代四次的循环。每次迭代,在数组的开头添加较深的阴影,在末尾添加较浅的色调。在这里,我们map用来计算亮度值——一个函数,它接受一个通常存在于一个范围内的数字并将其转换为另一个范围——并使用我们的hueStep变量增加或减少色调。同样,adjustHue这里使用 来确保所有色调值都在 0 到 360 之间。

  4. 归还调色板! 

用法 

一旦我们的createHueShiftPalette函数被定义,我们可以像这样使用它:

import { formatHex } from "https://cdn.skypack.dev/culori@2.0.0";

const hueShiftPalette = createHueShiftPalette({
  base: {
    l: 55,
    c: 75,
    h: 0,
    mode: "lch"
  },
  minLightness: 10,
  maxLightness: 90,
  hueStep: 12
});

const hueShiftPaletteHex = hueShiftPalette.map((color) => formatHex(color));

// ["#ffb97a", "#ff957c", "#ff727f", "#ff5083", "#f02f87", "#c70084", "#9a007f", "#6a0076", "#33006b"]
实际应用

生成的调色板createHueShiftPalette非常 适合 图案/图形;这是一个使用它来创建随机/生成模式的示例,这些模式在每次渲染时都会略有不同: 

 

 

 

 

 

挑战

现在,亮度/色调值在我们的createHueShiftPalette函数中线性缩放。你可以对它们应用一些缓和吗?也许,从更大/更小的色调偏移开始,并随着每一步减少/增加它?好吧,伙计们,这就是现在的全部!我们已经学习了如何创建三个漂亮的颜色生成函数,了解如何应用它们并考虑如何改进/更改它们。从这里开始,我希望您采用这些功能并更改它们以适合您,甚至希望您自己编写!作为开发人员,我们拥有独特的技能组合, 非常 适合创建真正创新、令人惊叹的设计。无论这意味着为与您合作的设计师创建颜色生成工具,还是为您的网站添加令人兴奋的生成调色板——我们都应该对我们使用颜色的能力充满信心。

如有相关前端方面的技术问题 ,欢迎主页添加我们微信群,我会定期在群里给大家分享最新技术和解答问题 。

网友评论