布局设计师不需要数学2:矩阵,基本转换,3D构造和图片过滤器





上次我们谈到的图表和轨迹的定格动画,今天将左右矩阵。我们将弄清楚如何在CSS,SVG和WebGL中进行基本转换,如何用自己的双手在屏幕上建立3D世界的显示,以及与Three.js之类的工具进行平行绘制的过程,并尝试对照片进行滤镜并弄清楚因为这种魔术是他们的核心。



让我提醒您,在本系列文章中,我们熟悉了数学领域中的各种事情,这些东西吓跑了布局设计师,但对解决工作问题很有用。我们尝试避免不必要的理论化,而是希望用手指来表示和解释,而重点放在前端的实际应用中。在这方面,从数学的角度来看,某些地方的公式可能不完全准确,或者不太完整。本文的目的是对发生的事情以及发生的事情从何处开始给出一个大致的了解。



以本系列文章的样式生成图像的脚本在GitHub上,因此,如果您想弄清楚它们,则知道该怎么做。



很少的定义



数学中的矩阵就是这样的抽象,可以说它在某种意义上是一种数据类型,并以矩形表的形式编写。列数和行数可以是任何数,但是在网络上,我们几乎总是处理2x2、3x3、4x4和5x5的正方形矩阵。



我们还需要一个定义,例如向量。我认为从学校几何学上,您可以回忆起与“长度”和“方向”相关的定义,但通常在数学中很多东西可以称为向量。特别是,我们将向量作为有序的值集进行讨论。例如,形式为(x,y)或(x,y,z)的坐标,或格式为(r,g,b)或(h,s,l,a)的颜色,等等。根据此类集合中包含多少个元素,我们将讨论一维或另一维的向量:如果两个元素是二维的,则三个元素是三维的,依此类推。同样,在所考虑主题的框架内,有时可以方便地将向量视为大小为1x2、1x3、1x4等的矩阵。从技术上讲,我们可以只使用术语“矩阵”,但仍将使用“向量”一词将这两个概念彼此分开,至少在逻辑上是这样。



对于矩阵以及向量,定义了可以用它们完成的各种操作。特别是乘法。我们不断地在我们中间繁殖它们。乘法算法本身并不是很复杂,尽管看起来有些混乱:



function multiplyMatrices(a, b) {
    const m = new Array(a.length);

    for (let row = 0; row < a.length; row++) {
        m[row] = new Array(b[0].length);

        for (let column = 0; column < b[0].length; column++) {
            m[row][column] = 0;

            for (let i = 0; i < a[0].length; i++) {
                m[row][column] += a[row][i] * b[i][column];
            }
        }
    }

    return m;
}


但实际上,对我们而言,解决日常问题时不断记住其操作原理并不是那么重要。在这里,我们为了完整起见而提及它,是为了提供更多示例的上下文。



在数学中处理复杂的实体时,抽象非常有用。像这里一样-我们将经常讨论乘法,但是我们不会关注以什么顺序出现的哪种算术运算。我们知道乘法已定义-这足以完成工作。


我们将仅在非常特定的一组问题中使用平方矩阵,因此一组简单的规则就足够了:



  • 您只能将相同维度的矩阵相乘。
  • 我们将矩阵乘以矩阵-得到矩阵。
  • 您可以将矩阵乘以向量-我们得到一个向量。
  • 乘法的顺序很重要。






我们将主要使用从左到右的乘法,因为它比较熟悉并且适合于解释,但是在某些书或库中,您可能会遇到从右到左的表示法,并且所有矩阵都将被对角镜像。这丝毫不影响所进行操作的本质,因此我们不再赘述,但是如果您复制粘贴内容,请注意。


同样,为了进一步的工作,我们将需要诸如恒等矩阵的概念。这是一个矩阵,在主对角线上有一个,在所有其他像元中为零。乘法算法的构建方式是将单位矩阵与另一个矩阵相乘-我们得到相同的矩阵。或向量,如果我们在谈论向量。换句话说,单位矩阵在通常的数字乘法中充当一个单元。这是一种中立的事物,相乘时“不会影响任何东西”。







最后,我们需要的是上图所示的示例。这就像将矩阵乘以向量的特殊情况一样,当矩阵的最后一行是一个``单位矩阵'',并且向量的最后一个元素也等于1。



在此示例中,我们使用字母(x,y),并且您可能已经猜到了,下面的讨论将集中于2D坐标。但是,为什么要添加第三个坐标并将其保留为一个坐标呢?- 你问。这一切都是为了方便甚至更好的多功能性。我们经常添加+1坐标以简化计算,例如2D使用3x3矩阵,使用3D-使用4x4矩阵,以及使用4D,例如,格式(r,g,b,a)的颜色与矩阵一起使用5x5。乍一看,这似乎是一个疯狂的主意,但是稍后我们将看到它如何统一所有操作。如果您想更详细地了解该主题,可以使用Google表达式“统一坐标”。



但是有足够的理论,让我们继续实践。



一,计算机图形学的基本转变



让我们从上面的示例中获取表达式,并在矩阵上下文之外按原样查看它们:



newX = a*x + b*y + c
newY = d*x + e*y + f


您可以将其视为我们上次绘制的参数方程式。如果在其中设置这些系数或这些系数,会发生什么?让我们从下一个选项开始:



newX = 1*x + 0*y + 0 = x
newY = 0*x + 1*y + 0 = y


这里没有任何变化-新坐标(x,y)与旧坐标相同。如果我们将这些系数代入矩阵并仔细观察,就会看到我们得到了单位矩阵。



如果取其他系数会怎样?例如,这些是:



newX = 1*x + 0*y + A = x + A
newY = 0*x + 1*y + 0 = y


我们将在X轴上得到一个偏移,但是这里还可能发生什么呢?如果这对您不明显,那么最好返回第一部分,我们在这里讨论了图表和系数。



更改这6个系数-a,b,c,d,e,f-并观察x和y的变化,我们迟早会得出它们的四个组合,这些组合似乎实用且方便。让我们以矩阵的形式立即编写它们,回到原始示例:







这些矩阵的名称可以说明一切。将这些矩阵乘以带有某些点,场景中对象等的坐标的矢量时。我们为他们获得新的坐标。此外,我们以直观的变换进行操作-移动,缩放,旋转和倾斜,系数确定沿相应轴的特定变换的严重程度。



将矩阵视为某些事物(例如坐标)的变换通常很方便。这是关于抽象的另一句话。


转换可以堆叠。在矩阵方面,我们将使用乘法运算,这可能会有些混乱,但这是口头语言的开销。如果需要将某个对象移到一边并增加,则可以采用位移矩阵,缩放矩阵并将它们相乘。结果将是一个同时提供偏移和缩放比例的矩阵。它仅需借助其帮助来变换对象的每个点。







CSS的基本转换



但是这些都是话。让我们看看真实前端中的外观。在CSS中,我们(突然之间)具有矩阵函数。在代码的上下文中看起来像这样:



.example {
    transform: matrix(1, 0, 0, 1, 0, 0);
}


这个问题涵盖了许多初次接触新手的人-为什么会有六个参数?这很奇怪。那应该是4或16-仍然没有去哪里,但是6?他们在做什么?



但实际上,一切都很简单。这六个参数正是我们刚刚为基本变换组装矩阵的系数。但是由于某些原因,它们以不同的顺序排列:







而且在CSS中还有一个matrix3d函数,以便使用矩阵设置3D变换。已经有16个参数,正好构成一个4x4矩阵(不要忘记我们增加了+1维)。



基本3D变换的矩阵的构建方式与2D相同,只需要更多系数即可将它们布置在两个坐标而不是三个坐标中。但是原理是一样的。


自然,每次在CSS中进行简单转换时,围住矩阵并监视系数的正确放置总是很奇怪的。我们程序员通常试图使我们的生活更轻松。因此,我们现在在CSS中具有创建单个转换的简短功能-translateX,translateY,scaleX等。通常,我们使用它们,但是重要的是要了解它们内部创建了我们所讨论的相同矩阵,只是将这一过程对我们隐藏在另一层抽象后面。



SVG中具有相同的平移,旋转,缩放和倾斜变换,以及用于定义变换的通用矩阵函数。语法略有不同,但本质是相同的。当使用3D图形(例如WebGL)时,我们还将诉诸相同的转换。但是在此之后的更多内容中,现在重要的是要了解它们无处不在,并且它们根据相同的原理在任何地方工作。



小计



让我们总结一下:



  • 矩阵可以用作向量的转换,尤其是页面上某些对象的坐标。
  • 我们几乎总是使用平方矩阵进行运算,并添加+1维以简化和统一计算。
  • 有4种基本转换-平移,旋转,缩放和倾斜。从CSS到WebGL,它们在任何地方都可以使用,并且在任何地方都以类似的方式工作。


二。DIY 3D场景构建



有关坐标变换的主题的逻辑发展是构建3D场景并将其显示在屏幕上。以一种或另一种形式,此任务通常存在于所有计算机图形学课程中,但是在前端课程中通常不存在。我们将看到,也许有些简化,但仍然是一个完整的版本,说明如何制作具有不同视角的相机,需要执行哪些操作来计算屏幕上所有对象的坐标并生成图片,还需要与Three.js进行平行绘制-最受欢迎用于WebGL的工具。



这里应该提出一个合理的问题-为什么?如果拥有现成的工具,为什么还要学会用手做所有事情?答案在于性能问题。您可能访问过具有Awwwards,CSS Design Awards,FWA等竞赛的网站。还记得表演网站如何参加这些比赛吗?是的,几乎每个人都减速,加载时滞后并使笔记本电脑嗡嗡作响!是的,当然,主要原因通常是复杂的着色器或过多的DOM操作,但第二个原因是脚本数量惊人。这对此类站点的加载具有灾难性的影响。通常所有事情都是这样的:您需要在WebGL上做一些事情-使用某种3D引擎(+ 500KB)和一些插件(+ 500KB);您需要使物体掉落或有东西飞散-它们需要一个物理引擎(超过1MB,甚至更多);您需要更新页面上的一些数据-好吧,添加带有一打插件(+ 500KB)的一些SPA框架,等等。这样,键入了几兆字节的脚本,不仅需要客户端下载(这是大图片的补充),而且浏览器在下载后也会对它们进行处理-它们不只是飞向他。此外,在99%的情况下,直到脚本起作用为止,用户不会从一开始就看到他需要展现的所有美感。客户端需要下载的内容(这是大图片的补充),因此浏览器在加载后会对其进行处理-它们不仅仅是出于某种原因而来。此外,在99%的情况下,直到脚本起作用为止,用户不会从一开始就看到他需要展现的所有美感。客户端需要下载的内容(这是大图片的补充),因此浏览器在加载后会对其进行处理-它们不仅仅是出于某种原因而来。此外,在99%的情况下,直到脚本起作用为止,用户不会从一开始就看到他需要展现的所有美感。



人们普遍认为,生产中每666KB脚本都会将页面加载时间增加足够的时间,以使用户将站点开发人员发送到下一个地狱。最低配置中的Three.js重量为628KB ...


此外,通常任务根本不需要连接复杂的工具。例如,要在WebGL中显示几个带有纹理的平面并添加几个着色器,以使图片以波浪形发散,则不需要整个Three.js。为了使物体掉落,您不需要成熟的物理引擎。是的,它可能会加快您的工作速度,特别是如果您熟悉它的话,但是您将花费用户的时间来为此付出代价。在这里,每个人都自己决定什么对他更有利。



坐标转换链



实际上,在屏幕上构建3D场景的坐标转换的本质非常简单,但是我们仍将逐步分析它,因为对于许多布局设计师而言,此过程很可能是新事物。



就是这样了。假设设计师绘制了3D模型。让它成为一个多维数据集(在示例中,我们将使用最简单的构造,以免使插图变得异常复杂):







此模型是什么样的?实际上,它是某个坐标系中的一组点以及它们之间的一组关系,以便您可以确定平面应位于哪些点之间。 WebGL上下文中的平面问题将落在浏览器本身的肩膀上,坐标对我们很重要。您需要弄清楚如何进行转换。



正如我们所说,该模型具有坐标系。但是通常我们想要很多模型,我们想和他们一起做一个场景。场景,即我们的3D世界,将拥有自己的全局坐标系。如果我们仅将模型的坐标解释为全局坐标,那么我们的模型将位于“世界中心”。换句话说,什么都不会改变。但是我们想在世界上的不同地方添加许多模型,如下所示:







该怎么办?您需要将每个模型的坐标转换为全局坐标。模型在空间中的位置由偏移,旋转和缩放比例设置-我们已经看到了这些基本转换。现在,我们需要为每个模型构建一个转换矩阵,该矩阵将仅存储有关模型相对于世界的位置以及其旋转方式的信息。



例如,对于多维数据集,大约有以下矩阵:



//     .
//   «  »      .
const modelMatrix1 = [
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1]
];

// ,     X.
const modelMatrix2 = [
    [1, 0, 0, 1.5],
    [0, 1, 0, 0  ],
    [0, 0, 1, 0  ],
    [0, 0, 0, 1  ]
];

// ,     X   .
const modelMatrix3 = [
    [1, 0, 0, -1.5],
    [0, 1, 0, 0   ],
    [0, 0, 1, 0   ],
    [0, 0, 0, 1   ]
];


此外,我们将大致采取以下行动:



    {
       = [    ] *  
}


因此,每个模型都需要自己的矩阵。



同样,您可以制作一些对象的链。如果鸟类必须拍打翅膀,则将翅膀点的坐标转换为鸟类的坐标,然后转换为全局世界坐标是合适的。立即在全局坐标中猜测机翼轨迹会容易得多。顺便说一下,这是事实。




接下来,您需要确定我们将看待世界的哪一侧。我需要照相机。







相机就是这样的抽象,就像对物理相机的模仿一样。它具有坐标和一些倾斜角,这些坐标和倾斜角定义了它在全局坐标中的位置。我们的任务是将一组现在的全局坐标转换为相机坐标系。原理与前面的示例相同:



     {
        = [   ] *  
}


, , . !


让我们从条件摄影机所在的位置看一下场景:







现在,将所有点转换为摄影机坐标系后,我们可以简单地丢弃Z轴,并将X和Y轴解释为“水平”和“垂直”。如果在屏幕上绘制模型的所有点,则会得到图片,如示例中所示-没有透视图,很难理解场景的哪一部分实际落入框架中。相机在各个方向上的大小似乎都是无限的。我们可以以某种方式调整所有内容,使我们所需的内容适合屏幕,但是最好有一种通用的方法来确定场景的哪个部分将落入相机的视野,而哪些部分将不属于相机的视野。



借助物理相机,我们可以谈论诸如视角之类的问题。为什么不在这里添加它呢?



为此,我们需要另一个矩阵-投影矩阵。通常,可以用不同的方式来构建它。根据初始参数的不同,您会对此矩阵有一个稍微不同的看法,但本质是相同的。我们将采用以下稍微简化的版本:



//     90 
const s = 1 / (Math.tan(90 * Math.PI / 360));
const n = 0.001;
const f = 10;

const projectionMatrix  = [
    [s, 0, 0,          0],
    [0, s, 0,          0],
    [0, 0, -(f)/(f-n), -f*n/(f-n)],
    [0, 0, -1,         0]
];


投影矩阵(一种或另一种)包含三个参数-这是视角,以及与工作点的最小和最大距离。它可以用不同的方式表示,以不同的方式使用,但是无论如何,这些参数都将在此矩阵中。



我知道,矩阵为什么看起来像这样从来都不是显而易见的,但是要想得到解释并推导它,您需要2至3页的公式。这再次使我们回到抽象有用的想法-我们可以以更一般的结果进行操作,而不必在不需要解决特定问题的细节上进行细化。



现在,进行已经熟悉的转换:



       {
      = [   ] *   
}


我们完全符合我们的期望。增大角度-我们看到的大部分是侧面,减小角度-我们只能看到更接近相机定向的方向。利润!







但实际上没有。我们忘记了观点。在少数地方需要没有希望的图片,因此您需要以某种方式添加它。在这里,突然之间,我们不需要矩阵。这项任务看起来非常困难,但是可以通过将X和Y坐标除以W来平分每个点来解决:







*在这里,我们将摄像机移至侧面,并在“地面”上添加了平行线,以使该透视图的显示位置更加清晰。



通过选择适合您口味的系数,我们将获得不同的视角选项。从某种意义上说,这里的系数决定了镜头的类型,以及它“拉平”了周围空间的程度。


现在我们有了一张完整的图片。您可以获取每个点的X和Y坐标,并以任意方式将其绘制在屏幕上。



通常,这足以构建场景,但是在实际项目中,您可能最终还会遇到与缩放相关的其他转换。这个想法是,在投影之后,我们获得1内的坐标(x,y)(归一化的坐标),然后将它们乘以屏幕或画布的大小,以使坐标显示在屏幕上。这个额外的步骤将画布大小从所有计算中删除,仅保留在最后。有时这很方便。



在这里,您可能会因信息量而感到头疼,所以让我们放慢速度,并在一处重复所有的转换:







如果将这些转换组合为一个,则会有一个小的引擎。



在Three.js中看起来如何?



现在,我们了解了这个小引擎的来源,让我们看一下Three.js中默认顶点着色器的示例,该着色器“什么都不做”:



void main() {
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}


或更充分地:



void main() {
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
}


他有没有让你想起什么?是的,这是这个特殊的引擎。所谓“不执行任何操作”,是指它基于从Three.js精心传递的矩阵来完成重新计算坐标的所有工作。但是没有人会费心用自己的双手来制作这些矩阵,对吗?



计算机图形和Three.js中的相机类型



摄像机类型的主题与矩阵没有直接关系,但是由于我们仍在谈论Three.js,有时我们会花一些时间,有时人们对此会一团糟。



相机是一种抽象。它可以帮助我们以与现实世界相同的方式思考3D世界。就像我们说过的,相机具有在空间中的位置,所看的方向和视角。所有这一切都使用两个矩阵以及可能的其他坐标分割来创建透视图来指定。



在计算机图形学中,我们有两种类型的相机-“有视角”和“无视角”。从技术上来讲,这是两种根本不同类型的相机,需要采取不同的操作来获取图像。就这样。没有别的了。其他所有内容都是它们的组合,还有一些更复杂的抽象。例如,Three.js拥有一个立体摄像头-从技术上讲,这不是某种“特殊类型”摄像头,而只是一种抽象-两台摄像头在空间上间隔很小并成一定角度放置:







对于屏幕的每一半,我们都拥有自己的摄像头,结果立体图片。CubeCamera是从某个点位于不同侧面的6个普通摄像机,仅此而已。



下一步是什么?



在获得对象的坐标之后,下一步是确定哪些对象将是可见的,哪些对象将隐藏在其他对象的后面。在WebGL的上下文中,浏览器将自行执行此操作。嗯,仍然会有相关的任务,例如向其应用纹理,通过法线,阴影计算光照,后期处理图像等。但是我们已经完成了最重要和最难理解的部分。这很棒。实际上,许多生成性物品并不需要这些纹理和光照,因此很可能现在所获得的知识足以与它们一起使用。



顺便说一句,将阴影从物体投射到平面上,无非就是将物体以一定角度投射到这个平面上,然后混合颜色。该过程本质上与照相机非常相似,但是它还会在投影平面和“视线方向”之间增加一个角度。


关于WebGL上的图像的纹理和效果(包括不带库的图像),我们在前几篇文章中多次讨论。如果您对此主题感兴趣,可以参考它们。因此,通过将所有这些知识结合在一起,我们将能够用自己的双手来构建成熟的彩色3D事物。



3D- . – - . , Three.js . , , , - , - . , .




现在是时候总结一下上面的内容了,这样您的脑海中就可以容纳下一个矩阵用例。



所以:



  • 您可以使用来自矩阵的火车来建立3D世界,并用自己的双手在屏幕上计算对象的坐标。
  • 在3D世界中,我们使用“相机”这样的抽象来进行操作。它具有位置,方向和视角。所有这些都是使用相同的矩阵设置的。相机有两种基本视图-透视图和非透视图。
  • 在WebGL的上下文中,在屏幕上手动渲染图片或进行物理计算通常可以消除繁重的依存关系并加快页面加载速度。但是,重要的是要在脚本,现成的工具以及其他解决问题的方法之间取得平衡,不仅要注意方便性,还要注意下载速度和最终性能(包括手机)的问题。


三,图片过滤器



最后,我们将把矩阵作为图像过滤器应用于这样一个领域。如果我们将RGBA格式的颜色视为矢量,则可以假定在这里我们可以应用与坐标坐标类似的变换:







并根据显而易见的原理将此变换应用于图片:



    {
       = [  ] *   
}


如果身份矩阵充当矩阵,则什么都不会改变,我们已经知道。如果应用类似于平移和缩放转换的过滤器会怎样?







OU 结果是亮度和对比度过滤器。有趣。



在尝试使用此类滤镜时,应始终记住调整值,以免图像曝光过度。如果将某物乘以大量,则很可能需要在某处减去或除某物。如上例所示。


如何用彩色图像制作黑白图像?首先想到的是将RGB通道值相加,除以3,然后对所有三个通道使用结果值。在矩阵格式中,它将看起来像这样:







尽管我们确实获得了黑白图像,但仍可以对其进行改进。实际上,我们的眼睛以不同的方式感知不同颜色的亮度。为了在去饱和过程中以某种方式传达这一点,我们在此矩阵中为每个RGB通道设定了不同的系数。



下面的示例将介绍这些系数的公认值,但没有人会费心去玩。总的来说,这些系数应为1,但根据其比例,我们将获得略有不同的黑白图像。在使用胶卷相机时,这可以在某种程度上模拟不同的色彩再现。



而且,如果我们也将主对角线略微相乘,则会得到一个通用的饱和度滤镜:







它可以在两个方向上起作用-在去饱和度(您可以达到完全的黑白图像)和饱和度上。这完全取决于相应的系数。



通常,您可以长时间使用滤镜,并获得各种结果:







*此示例中使用的矩阵可以在GitHub上查看如果您突然需要它们。要插入文章中,它们的体积将过大。



但是,让我们仍然稍微注意一下它的实际应用。显然,为每个像素替换颜色的想法暗示了用于处理照片或对某些3D场景进行后期处理的着色器,但也许它仍然在前端?



CSS中的过滤器



在CSS中,我们有一个filter属性。特别是对于与颜色相关的滤镜,有以下选项:



  • 亮度(我们做到了)
  • 对比(完成)
  • 反转(与对比度相同,仅主对角线系数具有不同的符号)
  • 饱和(完成)
  • 灰度(如前所述,这是饱和的特殊情况)
  • 棕褐色(一个非常模糊的概念,通过使用系数获得棕褐色的不同版本,在某种程度上我们减少了蓝色的出现)


这些过滤器接受系数作为输入,然后将其以一种或另一种形式替换为我们之前制作的矩阵。现在我们知道了这种魔术是如何从内部起作用的。现在很清楚这些过滤器是如何在CSS解释器的肠道中组合的,因为此处的所有内容都是根据与坐标相同的原理构建的:乘法矩阵-添加效果。是的,在CSS中,此属性中没有自定义函数矩阵。但是它在SVG中!



在SVG中过滤矩阵



在SVG中,我们有feColorMatrix,用于创建图像过滤器。在这里,我们已经拥有了完全的自由-我们可以根据自己的喜好建立矩阵。语法是这样的:



<filter id=’my-color-filter’>
    <feColorMatrix in=’SourceGraphics’
        type=’matrix’,
        values=’1 0 0 0 0
                0 1 0 0 0
                0 0 1 0 0
                0 0 0 1 0
                0 0 0 0 1‘
    />
</filter>


您还可以将SVG过滤器应用于CSS中的常规DOM元素,对此有一个特殊的url函数……但是我没有告诉您!



实际上,并非所有浏览器都支持CSS内的SVG过滤器(并非将矛头指向IE),但是有传言称Edge最终将转向Chrome引擎,并且在可预见的将来,旧版本将失去支持,因此该使用该技术了。大师,您可以用它做很多有趣的事情。


还有什么呢?



除了基于变换原理的图片效果外,还有许多基于像素位移,混合其颜色和其他操作的事物,其中矩阵可以是一种很好的格式,用于存储应该进行这种操作的数据。



核矩阵



特别是在前端,我们遇到了诸如内核矩阵及其相关效果之类的东西。重点很简单-有一个正方形矩阵,通常为3x3或5x5,尽管可能更多,并且将系数存储在其中。在矩阵的中心-对于“当前”像素,在中心周围-对于相邻像素。如果矩阵为5x5,则中心周围会出现另一层-像素位于当前层的其中一层。如果是7x7-然后是另一层,等等。换句话说,我们认为矩阵是一个二维字段,您可以在不考虑任何方程式的情况下自行决定布置系数。它们的解释如下:



    {
       =
           ,      
}


一块空白画布不太适合此类任务,但着色器非常均匀。但是很容易猜到,矩阵越大,我们将使用的相邻像素越多。如果矩阵是3x3,我们将添加9种颜色,如果是5x5-25,如果是7x7-49,等等。更多操作-处理器或视频卡上的负载更多。这将不可避免地影响整个页面的性能。



如果需要实时将小型矩阵覆盖在某处,请尽可能使用较小的矩阵。


在SVG中,我们有一个特殊的feConvolveMatrix标签,该标签仅用于创建以下效果:



<filter id=’my-image-filter’>
    <feConvolveMatrix
        kernelMatrix=’0 0 0
                      0 1 0
                      0 0 0’
    />
</filter>


在这里我们为不做任何事情的图片做了一个简单的过滤器-每个像素的新颜色将等于当前值乘以1,然后相邻像素的颜色值将被乘以0。



请注意,不同的浏览器呈现SVG的方式也不同,并且彩色呈现的范围也很广。有时,差异只是灾难性的。因此,请务必测试您的SVG过滤器或使用画布,在我们的上下文中这更可预测。


如果我们开始按层数排列,从大到小,我们就会变得模糊:







矩阵越大,我们触摸到的相邻像素越多,图片被冲洗的越多。这里最主要的是不要忘记对这些值进行标准化,否则图像只会点亮。



现在,了解了模糊的工作原理后,我们可以了解为什么在CSS或SVG内的页面上频繁使用模糊会导致刹车-浏览器对每个像素进行大量计算。


如果您开始尝试更改系数的符号并将其排列为不同的样式,则将获得锐化效果,边缘检测等。尝试自己和他们一起玩。这可能会有所帮助。







因此,您可以实时为照片甚至视频制作不同的效果,并使它们依赖于某些用户操作。这完全取决于您的想象力。



小计



让我们总结一下这部分的内容:



  • 矩阵不仅可以用于与坐标有关的变换,而且还可以用于创建滤色器。一切都按照相同的原则完成。
  • 矩阵可以用作某些数据的便捷2D存储,包括不同的视觉效果系数。


结论



如果我们从复杂的算法中抽象一点,那么矩阵将成为解决实际问题的负担得起的工具。在他们的帮助下,您可以用自己的双手来计算几何变换,包括在CSS和SVG框架内,构建3D场景,还可以在WebGL框架内为照片或后处理图像创建各种滤镜。所有这些主题通常都超出了经典的前端范围,并且通常与计算机图形更为相关,但是即使您没有直接解决这些问题,了解它们的解决方案原理也可以使您更好地了解某些工具的工作原理。它永远不会是多余的。



我希望本文能帮助您了解前端中矩阵的实际使用的主题,或者至少为您提供了一个基础,可以在此基础上进行进一步的开发。如果您认为与数学或物理相关的其他一些主题在版面设计中也值得进行同样的评论,那么请在评论中写下您的想法,也许下一篇文章将对此进行讨论。



All Articles