在本教程中,我们将学习仅在几行JavaScript中创建超级多功能生成/随机网格布局。使用称为Quadtree的数据结构,我们将基于随机数,源图像,用户输入等和谐网格生成和谐网格。
混乱,但完美对齐的生成网格世界正在等待我们 - 让我们走!
注意:我从五角星文件中获取了我的历史最喜欢的设计代理人之一。在他们为GraphCore的品牌工作中,它们可以广泛使用四肢曲线来生成随机且视觉相干的模式。输出令人惊叹,并且是您可以使用此方法创建的奇妙示例。您可以查看此处的工作案例研究!
首先是首先,让我们在本教程中完成我们正在烹饪的内容。这是一个动画的Quadtree网格中的动画示例:
将一些{x,y}添加到2d空间。在该示例中,点的位置是随机的,但朝向焦点偏置。
使用生成的网格区域来定位东西!在上面的示例中,我使用正方形和圆圈来形成简单的模式。
通过尝试具有创造性的方式来定位点,我们可以创建一些超级有趣的网格布局。此示例使用偏见随机数,但如果是,则何时何地来自图像的亮度值?
我们可以在斐波那克拉斯,一个圆形,广场,无论如何的照片中传递,并根据其像素值生成我们的点。可能性是无止境!任何用于在2D空间中定位对象的方法都将起作用。黎思,越好。
我们在这里看到的细分魔法全部由称为Quadtree的数据结构处理。我喜欢像小容器一样想到四轮节。一旦Quadtree填充了一定数量的对象,它就会将其自身拆分为四个Quadtrees。一旦那些Quadtrees填满,他们再次划分自己,等等。
Quadtree可以棘手可视化,因此这里是一个交互式示例 - 单击以添加对象/点并观察Quadtree Subdivides的方式。在此示例中,Quadtree可以包含的最大项目数是四个。
非常满足......这是我们需要了解的一切关于这一教程的四章,但如果您想了解更多关于他们如何工作/如何使用它们,请查看丹Shiffman的这段视频。
虽然任何人都是欢迎来遵循 - 本教程非常适合与JavaScript舒适的人,熟悉SVG / HTML画布。
为了保持简单的事情,让我们专注于有趣的东西 - 我已经向我的生成-Utils repo添加了一个方便的createqtgrid函数。此函数需要一系列点并返回即用的Quadtree网格。如果您希望潜入源代码,则在此存储库中可用。
我还创建了一个罢工码头,你可以叉开始。这支笔有即将到来的示例所需的所有JS导入/基本CSS。但是,尽管如此,欢迎您在您喜欢的任何环境中关注。
要开始,让我们创建一个Quadtree网格,并偏见随机分布点。偏见随机数在这里工作得很好,因为它们提供了强烈的视觉焦点。具有讽刺的随机性,讽刺的是,往往有点无聊地为四肢网格。网格区域看起来太统一,因为该点散落在2D空间上。
在此示例中,我们将使用SVG元素呈现我们的网格区域。让我们首先定义SVG's ViewBox的宽度和高度属性:
接下来,让我们创建一个新的< svg>元素渲染我们的网格。为此,我们将使用svg.js - 一个大大简化了动态SVG脚本的JavaScript库。在我的生成SVG入门套件中,您可以在SVG.js中阅读更多信息。
现在我们有我们的SVG元素,我们可以生成一些偏见的随机点。为此,我们可以利用Randombias函数。此函数基于四个参数返回一个随机数:
偏见 - 最小值和最大数量之间的任何数字,这是“焦点”
影响 - 0 - 1之间的数字,该参数确定返回的数字可能是偏差的关闭程度。
让我们弹出一些代码来生成100个随机点,重点朝向视图框的中心,并使用svg.js呈现它们:
const点= [... array(100)]。映射(()=> {return {x:randombias(0,宽度,宽度/ 2,1),y:randombias(0,高度,高度/ 2,1),宽度:1,高度:1,}; });要点。 foreach((point)=> {svg。圆圈(2)。cx(point .x)。cy(point .y);});
这个点分布看起来很可爱,但我们应该更新代码,以便焦点可以变化一点。让我们发生这种情况:
const focus = {x:随机(0,宽度),y:随机(0,高度),}; const点= [... array(100)]。地图(()=> {return {x:randombias(0,宽度,焦点.x,1),y:randombias(0,高度,焦点,1),宽度:1,高度:1,}; });
在此代码段中,我们使用随机函数来在网格上生成随机{x,y}焦点点。更新代码后,您应该看到这样的内容:
完美的!这种聚焦尚随机的分布将非常适合四栅格网格。让我们创建一个:
在此代码段中,我们调用宽度值,高度值,级别限制以及我们刚才生成的点的CreateQTGrid。我们还通过差距属性来给网格区有点呼吸室。
电平限制(由MaxQtlevels控制)定义了Quadtree可以细分的次数。较高的值,配对较高的点,将导致更详细的网格。
如果您现在的console.log(网格),您应该看到一个具有少数不同属性的对象 - 但此时,我们只对网格区域感兴趣。让我们遍历这些并渲染SVG< rect>每一个人:
优秀的。就是这样!我们已成功地生成了一个美丽的生成网格,随时准备充满您喜欢的任何东西。作为一个简单的例子,这里是我们如何将圆圈添加到随机选择网格区域:
嘿,这是一些非常酷的原种艺术!所有只是几行代码。我们现在已经完成了这个演示,但作为下一步,我建议使用点数,最大细分量(maxqtevels)和点分布逻辑 - 看看你可以创造的东西!
在生成的Quadtree菜单上接下来是一些基于图像的网格。对于此示例,我们将使用图像文件的像素值来确定我们的底层点。
要设置,我们可以重复使用在最后一个演示中定义的SVG元素和宽度/高度变量。注释出上一点,渲染代码或叉笔并创建一个新的画布。你的来电!
好的,所有集合?让我们找到合适的形象。对于我们的演示,仅包含完全黑色或白色像素的简单图片是完美的。形状(圆形,方形,螺旋)的基本轮廓是理想的。想想这样的事情:
如果您不喜欢鞭打任何自定义图像,那么我越早的一些。 *从奇怪的数字烤箱中删除预先制造的形状...... *
这些图像的大小为192x192px,匹配示例SVG ViewBox和Quadtree网格的宽度/高度属性。将图像示例格式化以这种方式,以节省必须执行任何时髦的计算。您不必为此分辨率工作,但请尝试并确保您的图像尺寸匹配代码中定义的宽度/高度尺寸。
注意:虽然这些源图像非常小,但最终结果将扩展到任何大小。
选择图像后,弹回代码并创建一个新的画布元素,将其宽度和高度设置为SVG Viewbox /网格,并将其上下文存储在新变量中。我们将在片刻中使用此画布来渲染我们的图像并提取其像素数据。
一旦图像加载,我们将其渲染为我们的画布,定义一个新的点数组,并循环通过所有画布的像素。如果像素具有红色,绿色和蓝色值为0(黑色像素),则我们将其坐标存储在点数组中 - 这就是我们使用仅由黑色或白色像素组成的图像的原因。
注意:您可以扩展此代码以处理全彩色图像,但我们正在为演示保持简单的事物。
要在此处进行一些可视反馈,请让我们在这些点中的每个点渲染SVG圈:
img。 onload =()=> {CTX。拔迹(IMG,0,0); const点= []; for(设定x = 0; x<宽度; x ++){for(设定= 0; y< height; height; y ++){const {data} = ctx。 getimagedata(x,y,1,1); if(数据[0] +数据[1] +数据[2] === 0){点。推({x,y,宽度:1,高度:1}); SVG。圆圈(1)。 cx(x)。 cy(y); }}}};
嘿,看看!它是原始图像变成{x,y}点。完美的。让我们将这些点传递给我们的CreateQTGrid函数,就像以前一样。这次,尝试将MaxQtlevels设置为稍高的数字 - 这应该有助于在网格中带出详细信息:
img。 onload =()=> {... const grid = createqtgrid({宽度,高度,点,间隙:1,maxqtlevels:6}); }
现在,我们可以以与演示#1相同的方式循环通过网格区域,渲染每个ON的SVG矩形:
美丽的!我们创建了一种基于底层源图像的生成网格布局。在这种情况下,源图像是斐波纳契螺旋。非常花哨的确!这是这个网格看起来像一个圆形/矩形的东西:
值得注意的是,不同的图像需要略微不同的maxqtlevels值。就像生成艺术中的一切一样,没有单一的魔法号码。最好的结果来自屏幕上的许多调整和眯眼。
到目前为止在我们的Quadtree冒险中,我们专门使用SVG来渲染我们的网格,但似乎有点羞耻地离开CSS网格,对吧?
好吧,我有一些好消息! CreateQTGrid返回的区域对象也具有COL和行值。使用这些值,我们可以轻松创建生成CSS网格布局 - 准备用于各种创新设计。
我不会在这里进入太多细节,因为创建CSS网格布局的过程与前一个示例的进程相同,但这是一个代码文,显示如何使用HTML / CSS的CreateQtGrid函数: 嘿,我们做了! 非常感谢你的阅读直到最后。 我知道这些概念有点沉重,但这里学到的技术将在您的生成艺术冒险中为您提供服务。 如果您在本教程中授课的内容酷,请告诉我! 没有我的喜爱,而不是看到基于我的教程的人们做些什么。 注册每月更新对我的新内容,选择我最喜欢的新代号,美味的字体,方便的前端+设计提示等等! ✨