概要
本文通过解决一个假想的问题介绍了 css screen 混合模式,并介绍了如何用 svg 滤镜、canvas 2d、canvas webgl 实现相同的效果。
问题
下面的图片演示三种颜色光叠加的效果,请在 html 中实现这种效果。
约定
词语 | 指代 |
---|---|
混合 | blend |
加色 | additive color - 名词 |
特性 | attribute,比如 <a id=1> ,说 id 是元素 a 的特性 |
透明度 | α、alpha |
伪输入图像 | pseudo input image |
着色器 | shader |
着色器程序 | shader program |
xml 应用程序 | XML application |
chrome | google chrome 41 |
firefox | firefox developer edition 40 |
ie | internet explorer 11 |
3 个浏览器 | 上面 3 个版本的浏览器 |
opera 已经基于 webkit 了,所以未测试 opera,若在 chrome 中可用那我就认为在 opera 中也可用。
分析
当然可以用 photoshop 制作图片,html 用 <img>
引用该图片,本文不讨论这种方法。
观察重叠部分发现该部分的颜色不仅受自己的影响、还受它下面背景颜色的影响,重叠部分的颜色是自己的颜色和背景颜色混合的结果。换句话说,一个像素绘制出来的颜色等于像素颜色和背景像素颜色的混合,即
C=B(Cb,Cs) ,其中,
C 是绘制的颜色
Cb 是背景颜色
Cs 是前景颜色,即像素的颜色
这里面 C 的 r、g、b 颜色分量都是 [0, 1] 的小数而不是 [0, 255] 的整数。显然,对同一个像素来说不同的
rgb(1, 0, 0)
、rgb(0, 1, 0)
、rgb(0, 0, 1)
,
重点:不同的 B 得到不同的
C
不可行的方法
html 中经常用到下面 3 个方法,
- css opacity 属性
- css rgba()/hsla() 颜色
- 用
<img>
引用带 alpha 通道的图像
它们使用相同的混合函数,叫做 α 混合或简单 α 复合,
αs 是前景透明度, αb 是背景透明度,上面的式子计算混合后的 r、g、b 颜色,混合后的透明度 αo 由公式 αo=αs+αb×(1−αs) 给出。很多时候背景不透明,即 αb 是 1,上面把 1 代入了 αb 。
简单 α 复合 - http://dev.w3.org/fxtf/compositing/#simplealphacompositing
opacity - http://stackoverflow.com/questions/8743482/calculating-opacity-value-mathematically
下面给上面的式子代入几组实际值。设 Cs 是不透明红 rgba(1, 0, 0, 1)
, Cb 是不透明蓝 rgb(0, 0, 1)
,它俩混合的结果不用计算都知道仍然是不透明红,计算过程如下,
r = 1 x 1 + 0 x (1 - 1) = 1
g = 0 x 1 + 0 x (1 - 1) = 0
b = 0 x 1 + 1 x (1 - 1) = 0
红蓝得红,混合失败。另外一组, Cs = rgba(1, 0, 0, 0.5)
, Cb = rgb(0, 0, 1)
,有,
r = 1 x 0.5 + 0 x (1 - 0.5) = 0.5
g = 0 x 0.5 + 0 x (1 - 0.5) = 0
b = 0 x 0.5 + 1 x (1 - 0.5) = 0.5
要想让得到的 rgb(0.5, 0, 0.5)
和 rgb(0, 1, 0)
的绿色混合以得到 rgb(1, 1, 1)
的白色,α 需要满足下面的方程组,
上面的方程组无解,即无论如何设置 α 都无法通过 B 混合 rgb(0.5, 0, 0.5)
和 rgb(0, 1, 0)
得到 rgb(1, 1, 1)
。
回过头来观察式子
可行的方法
如果可以自己逐一计算像素的颜色,得出要求的效果自然不在话下。除了自己计算外,如果存在正好能够实现要求效果的固定函数,则调用该函数也可以。
在 html 中处理颜色有 3 种工具,css、svg、canvas。
css
css 有个模块叫复合与混合,这个模块定义了若干固定函数,其中一个叫 screen,它的 B