Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【译】三角网格—Triangular mesh #24

Open
JChehe opened this issue Aug 11, 2018 · 0 comments
Open

【译】三角网格—Triangular mesh #24

JChehe opened this issue Aug 11, 2018 · 0 comments

Comments

@JChehe
Copy link
Owner

JChehe commented Aug 11, 2018

原文:Triangular mesh

本文由才华横溢的 maxwellito 撰写。如果你对编写文章感兴趣,可以像他一样提交一份 提案

这种三角网格效果常出现库和 SVG 中。今天我们将用 canvas 实现它!同时,这也是一个说明坐标系和替换细节而得到漂亮效果的案例。

老规矩,首先是初始化得到一个方形 canvas。

var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');

var size = window.innerWidth;

canvas.width = size;
canvas.height = size;

创建点网格的常规方式是通过行和列。这些点将会被绘制在 canvas 上,并被存储在一个数组中,以便后续使用。

点是由一个含有 xy 属性的对象表示。

行列之间的间距通过 gap 变量表示。我们将点绘制成圆后,便看到网格在 canvas 上的样子。

var line,
    lines = [],
    gap = size / 7;

for (var y = gap / 2; y <= size; y+= gap) {
  line = []
  for (var x = gap / 2; x <= size; x+= gap) {
    line.push({x: x, y: y})
    context.beginPath();
    context.arc(x, y, 1, 0, 2 * Math.PI, true);
    context.fill();
  }
  lines.push(line)
}

gap 间距的点

然后替换隔行的 x 坐标。这里我们通过 odd 变量交替赋值 true 或 false 实现。

一个正三角网格将在新坐标下形成。

var line, dot,
    odd = false, 
    lines = [],
    gap = size / 8;

for (var y = gap / 2; y <= size; y+= gap) {
  odd = !odd
  line = []
  for (var x = gap / 4; x <= size; x+= gap) {
    dot = {x: x + (odd ? gap/2 : 0), y: y}
    line.push(dot)
    context.beginPath();
    context.arc(dot.x, dot.y, 1, 0, 2 * Math.PI, true);
    context.fill();
  }
  lines.push(line)
}

正三角形网格的点

下一步是使用点绘制三角形。

创建一个接收三角形三个坐标,并连接绘制它们的函数。

function drawTriangle(pointA, pointB, pointC) {
  context.beginPath();
  context.moveTo(pointA.x, pointA.y);
  context.lineTo(pointB.x, pointB.y);
  context.lineTo(pointC.x, pointC.y);
  context.lineTo(pointA.x, pointA.y);
  context.closePath();
  context.stroke();
}

现在,结合 drawTriangle 函数和点数组绘制所有三角形。

这部分也许会有点难以理解。脚本会遍历所有线,并组合相邻线的点以形成三角形。为了便于理解,我们将相邻的两条线分别称为 ab。然后将两线符合要求的点合并到一个数组中,使其看起来像“之”字型:a1b1a2b2a3 以此类推。

这将为我们提供了一个含有三角形所有坐标的数组。如:[a1, b1, a2]、[b1, a2, b2], [a2, b2, a3] 等。

var dotLine;
odd = true;

for (var y = 0; y < lines.length - 1; y++) {
  odd = !odd
  dotLine = []
  for (var i = 0; i < lines[y].length; i++) {
    dotLine.push(odd ? lines[y][i]   : lines[y+1][i])
    dotLine.push(odd ? lines[y+1][i] : lines[y][i])
  }
  for (var i = 0; i < dotLine.length - 2; i++) {
    drawTriangle(dotLine[i], dotLine[i+1], dotLine[i+2])
  }
}

正三角形网格

至此,我们得到一个正三角网格。接着,我们为一个细节赋予魔法。

现在每个点与相邻点之间的间距相同。其实,我们可以将点在该区域内进行位移,而避免与其它点发生重叠(译者注:每个点的安全位移区域是点间距的一半)。利用 Math.random() 对点进行位移。

line.push({
  x: x + (Math.random()*.8 - .4) * gap  + (odd ? gap/2 : 0),
  y: y + (Math.random()*.8 - .4) * gap,
})

随机位移

另外,还可以增加一些生成艺术的乐趣。比如填充只有 16 种色调的灰色!

var gray = Math.floor(Math.random()*16).toString(16);
context.fillStyle = '#' + gray + gray + gray; 
context.fill();

最终效果——三角网格

如果想探索该效果的更多实现细节,可看看我的库:triangulr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant