CSS `blending-modes` 叠加 (`overlay`, `soft-light`, `hard-light`) 的数学模型

各位观众老爷们,晚上好! 今天咱们来聊聊 CSS 里的“妖艳贱货”—— blending-modes, 尤其是叠加系列的三剑客:overlaysoft-lighthard-light。 这三个家伙经常被用来实现各种炫酷的视觉效果,但它们背后的数学原理,emmm… 可能让不少小伙伴望而却步。 别怕! 今天我就带大家扒掉它们华丽的外衣,看看它们“内心”到底藏着什么。 准备好纸笔,咱们开始咯!

一、Blending Modes:概述

首先,我们要搞清楚 blending-modes 是个什么玩意儿。 简单来说,它就是控制两个图层(通常是背景和前景)如何混合在一起的属性。 想象一下,你把两张透明的彩色玻璃叠在一起,最终呈现出来的颜色,就取决于它们的混合方式。

CSS 提供了多种混合模式,比如 multiply(正片叠底)、screen(滤色)、color-dodge(颜色减淡)、color-burn(颜色加深),以及我们今天要重点关注的 overlaysoft-lighthard-light

二、RGB 颜色模型:基础知识

在深入了解叠加模式的数学模型之前,我们需要复习一下 RGB 颜色模型。 这是计算机世界里最常用的颜色表示方法。

RGB 颜色模型使用三个分量(红色 R、绿色 G、蓝色 B)来描述颜色。 每个分量的取值范围通常是 0 到 255(或 0.0 到 1.0)。 例如,rgb(255, 0, 0) 代表纯红色,rgb(0, 255, 0) 代表纯绿色,rgb(0, 0, 255) 代表纯蓝色。 rgb(255, 255, 255) 代表白色,rgb(0, 0, 0) 代表黑色。

记住这一点,后面的公式就好理解多了。

三、Overlay(叠加)模式:左右逢源的墙头草

overlay 模式的特点是:它会根据底色的亮度来决定混合的方式。 如果底色比较亮,它就类似于 screen 模式; 如果底色比较暗,它就类似于 multiply 模式。 简直就是墙头草,风往那边吹往哪边倒!

具体公式如下 (假设 Cb 是底色,Cs 是源色):

if (Cb <= 0.5) {
    Result = 2 * Cb * Cs;  // 类似于 Multiply
} else {
    Result = 1 - 2 * (1 - Cb) * (1 - Cs); // 类似于 Screen
}

这个公式看起来有点吓人,但其实很简单。

  • Cb <= 0.5 的情况: 这意味着底色比较暗。 此时,结果颜色是底色和源色相乘的两倍。 这跟 multiply 模式很相似,会使颜色变暗。

  • Cb > 0.5 的情况: 这意味着底色比较亮。 此时,结果颜色是 1 - 2 * (1 - Cb) * (1 - Cs)。 仔细观察,这其实是 screen 模式的变种,会使颜色变亮。

代码示例(JavaScript):

function overlay(Cb, Cs) {
  if (Cb <= 0.5) {
    return 2 * Cb * Cs;
  } else {
    return 1 - 2 * (1 - Cb) * (1 - Cs);
  }
}

// 示例:底色是浅灰色,源色是红色
let baseColor = 0.7; // 浅灰色
let sourceColor = 1.0; // 红色

let result = overlay(baseColor, sourceColor);
console.log("Overlay Result:", result); // 输出:0.8

表格总结:

条件 混合方式 效果
Cb <= 0.5 类似于 Multiply 颜色变暗
Cb > 0.5 类似于 Screen 颜色变亮

四、Soft Light(柔光)模式:温柔一刀的伪君子

soft-light 模式是一种比较柔和的混合模式。 它的效果取决于源色的亮度。 如果源色比 0.5 亮,则图像变亮,但程度比 screen 模式要轻; 如果源色比 0.5 暗,则图像变暗,但程度比 multiply 模式要轻。 这家伙表面上温柔,下手可不轻啊。

soft-light 的公式略微复杂一些:

if (Cs <= 0.25) {
    Result = Cb + (Cs * (Cb * (4 * Cb - 3)));
} else if (Cs <= 0.5) {
    Result = Cb + (Cs * (Cb * (12 * Cb - 15) + 4));
} else if (Cs <= 0.75) {
    Result = Cb + ((Cs - 0.5) * (Cb * (4 * Cb - 3)));
} else {
    Result = Cb + ((Cs - 0.5) * (Cb * (12 * Cb - 15) + 4));
}

或者等价于:

if (Cs <= 0.5) {
    Result = Cb - (1 - 2 * Cs) * Cb * (1 - Cb);
} else {
    Result = Cb + (2 * Cs - 1) * (D(Cb) - Cb);
}

其中 D(Cb) 是:

if(Cb <= 0.25) {
    D(Cb) = ((16 * Cb - 12) * Cb + 4) * Cb;
} else {
    D(Cb) = Math.sqrt(Cb);
}

这个公式把源色分成了两段: Cs <= 0.5Cs > 0.5

  • Cs <= 0.5 的情况: 结果颜色会变暗,但变暗的程度取决于源色的亮度。 源色越接近 0,变暗的程度越大。

  • Cs > 0.5 的情况: 结果颜色会变亮,但变亮的程度也取决于源色的亮度。 源色越接近 1,变亮的程度越大。

代码示例(JavaScript):

function softLight(Cb, Cs) {
    let D = (x) => {
        if(x <= 0.25) {
            return ((16 * x - 12) * x + 4) * x;
        } else {
            return Math.sqrt(x);
        }
    }

    if (Cs <= 0.5) {
        return Cb - (1 - 2 * Cs) * Cb * (1 - Cb);
    } else {
        return Cb + (2 * Cs - 1) * (D(Cb) - Cb);
    }
}

// 示例:底色是灰色,源色是深蓝色
let baseColor = 0.5; // 灰色
let sourceColor = 0.2; // 深蓝色

let result = softLight(baseColor, sourceColor);
console.log("Soft Light Result:", result); // 输出:0.45

表格总结:

条件 效果
Cs <= 0.5 颜色变暗,源色越接近 0,变暗的程度越大。
Cs > 0.5 颜色变亮,变亮的程度取决于源色的亮度。 源色越接近 1,变亮的程度越大。

五、Hard Light(强光)模式:简单粗暴的直男

hard-light 模式是三种模式中最直接、最简单粗暴的。 它就像一个开关,直接将底色和源色互换角色,然后应用 overlay 模式。

换句话说,hard-light(Cb, Cs) 等价于 overlay(Cs, Cb)。 简单粗暴,不玩虚的!

公式如下:

if (Cs <= 0.5) {
    Result = 2 * Cs * Cb;
} else {
    Result = 1 - 2 * (1 - Cs) * (1 - Cb);
}

代码示例(JavaScript):

function hardLight(Cb, Cs) {
  if (Cs <= 0.5) {
    return 2 * Cs * Cb;
  } else {
    return 1 - 2 * (1 - Cs) * (1 - Cb);
  }
}

// 示例:底色是蓝色,源色是黄色
let baseColor = 0.3; // 蓝色
let sourceColor = 0.8; // 黄色

let result = hardLight(baseColor, sourceColor);
console.log("Hard Light Result:", result); // 输出:0.88

表格总结:

条件 混合方式 效果
Cs <= 0.5 类似于 Multiply 颜色变暗
Cs > 0.5 类似于 Screen 颜色变亮

六、实际应用:几个小例子

理论学完了,咱们来点实际的。 看看这些 blending-modes 在 CSS 中怎么用。

1. 给图片添加复古滤镜:

.image-container {
  position: relative;
}

.image-container img {
  width: 100%;
  display: block;
}

.image-container::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(255, 200, 150, 0.3); /* 淡黄色 */
  mix-blend-mode: overlay;
}

这个例子中,我们给图片容器添加了一个伪元素,并设置了淡黄色的背景。 然后,通过 mix-blend-mode: overlay 将背景和图片混合,从而实现复古滤镜的效果。

2. 创建动态光影效果:

.container {
  width: 300px;
  height: 200px;
  background-color: #333;
  position: relative;
  overflow: hidden;
}

.light {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, rgba(0, 0, 0, 0) 70%);
  mix-blend-mode: soft-light;
  animation: moveLight 5s linear infinite;
}

@keyframes moveLight {
  0% {
    transform: translate(-50px, -50px);
  }
  100% {
    transform: translate(50px, 50px);
  }
}

这个例子中,我们创建了一个容器,并添加了一个带有径向渐变的 light 元素。 通过 mix-blend-mode: soft-light 将光照效果和容器背景混合,并通过动画来模拟光影的移动。

3. 突出显示文本:

.text-container {
  background-image: url("your-image.jpg");
  background-size: cover;
  color: white;
  padding: 20px;
}

.text-container p {
  mix-blend-mode: hard-light;
}

通过将文本的 mix-blend-mode 设置为 hard-light,可以使文本颜色根据背景图片的亮度进行调整,从而确保文本始终清晰可见。

七、注意事项:性能优化

虽然 blending-modes 效果很炫酷,但使用不当可能会影响页面性能。 尤其是在处理大型图片或复杂动画时,要格外小心。

  • 尽量减少使用 blending-modes 的元素数量。
  • 避免在滚动事件或动画中频繁修改 blending-modes
  • 使用 will-change 属性来提前告诉浏览器,元素即将发生变化。 例如: will-change: mix-blend-mode;

八、总结

今天我们深入探讨了 CSS blending-modes 中的 overlaysoft-lighthard-light 三种叠加模式。 它们都基于 RGB 颜色模型,通过不同的数学公式来实现不同的混合效果。

  • overlay 模式根据底色的亮度来决定混合方式,类似于 multiplyscreen 的结合体。
  • soft-light 模式是一种比较柔和的混合模式,效果取决于源色的亮度。
  • hard-light 模式是最直接、最简单粗暴的,相当于将底色和源色互换角色后应用 overlay 模式。

掌握了这些原理,你就可以更加灵活地运用 blending-modes 来创建各种炫酷的视觉效果啦!

好了,今天的讲座就到这里。 感谢各位的观看! 希望大家多多练习,早日成为 blending-modes 大师! 咱们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注