使用漂亮的调色板构建同心圆,为乐趣和科学

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费积分!

前几天我在浏览我的应用程序文件夹,希望清理一下。 我偶然发现了一个我曾经喜欢的但很久没用过的应用程序:Simple Desktops。 这是一个应用程序,可以将您的壁纸偶尔更改为随机、简单、经典的设计。 出现了一个像这样的

我只是有点心情,所以我就开始用前端代码重新创建它。

您知道什么擅长绘制圆圈吗?

SVG 是。 我认为绘制同心圆最简单的方法是元素。 更简单的是,使圆圈在网格上以 0, 0 为中心,只需增加半径即可。

<svg viewBox="-50 -50 100 100">
  <!-- first circle -->
  <circle cx="0" cy="0" radius="20" />
</svg>

我知道我想要 **五个** 圆圈组,每个圆圈内部有五个圆圈。 这将是手工编写很繁琐,而且调整起来更加困难。 因此,我求助于我们程序化的朋友 for 循环。

如何在 SVG 中编写 for 循环?

使用 HTML 预处理器! 我选择了 Pug。 一个简单的 Pug 循环看起来像这样

- for (var x = 1; x < 6; x++)
  p Print stuff five times.

我们的循环只会稍微复杂一些,因为有两个循环嵌套。 循环内部是一个元素,我们希望用循环的当前值来影响圆圈的半径。 Jade 可以做到!

- for (var y = 1; y < 6; y++)
  <svg viewBox="-50 -50 100 100">
  - for (var x = 1; x < 6; x++)
    circle&attributes({
      "cx": 0,
      "cy": 0,
      "r": 60-(x*10)
    })
  </svg>

这看起来有点奇怪。 尤其是那个 &attributes 部分。 这就是他们所谓的“展开”属性。 我很喜欢它。 以这种 JavaScript 对象格式设置属性非常不错。

编译后,最终结果如下

我相信您已经看到了如何在这些循环中轻松调整代码以快速调整大量代码。

使用 flexbox 轻松实现居中和布局

将 5 个 <svg> 排成一行非常容易。 在我们的演示中,只需将 <body> 设置为 flex 容器即可。

如果我们使用 flex: 1 扩展高度,则垂直居中将自动发生。 默认情况下,SVG 会将其绘制区域居中,并使其在 <svg> 区域内尽可能大。 occupies (the “viewport”).

html, body {
  height: 100%;
  overflow: hidden;
}
body {
  display: flex;
  padding: 0 50px;
}
svg {
  flex: 1;
  padding: 20px;
}

获取我们自己的漂亮的调色板

有一个 巧妙的方法 可以使用 JavaScript 生成随机颜色(十六进制代码)

'#'+Math.floor(Math.random()*16777215).toString(16);

随机颜色通常不太吸引人,尤其是五种随机颜色放在一起。

有一个很棒的小型库叫做 Please.js,我们可以使用它来获得令人愉悦的颜色。 它们甚至为调色板提供 API

Please.make_scheme({
  scheme_type: 'analogous'
});

但是……这可能不如手工创建和社区策划的调色板那么好。 这正是 COLOURlovers 拥有的

幸运的是,它们 有一个 API。 使用它的思路如下

1. 我们想要特定的调色板,所以

http://www.colourlovers.com/api/palettes

2. 我们想要特别好的,所以

http://www.colourlovers.com/api/palettes/top

3. 我们想在 JavaScript 中使用这些调色板,所以 JSON 会很棒,所以

http://www.colourlovers.com/api/palettes/top?format=json

4. 我们想要正好 5 个,所以

http://www.colourlovers.com/api/palettes/top?format=json&numResults=5

5. 我们想要每次都得到不同的结果,所以

这有点棘手。 幸运的是,它们的 API 支持“偏移量”,这意味着我们可以从它们排序中的任意位置获取 5 个结果。 所以让我们随机化一下。

让我们生成一个 1-50 之间的数字

var rand = Math.floor(Math.random() * (50 - 1)) + 1;

然后我们可以将其附加到我们正在构建的 URL 的末尾

var url = “http://www.colourlovers.com/api/palettes/top?format=json&numResults=5&resultOffset=” + rand;

我们想要在浏览器中使用它,所以
这意味着使用 Ajax 进行此 API 请求。 这样做时,我们将受到浏览器跨域限制的约束。 API 提供者可以通过设置所谓的 CORS 标头来解除这些限制,但出于某种原因,COLOURlovers 并没有设置这些标头。 另一种经典的解决方法是“JSONP”,但我们现在先不这样做。

相反,我们将使用代理服务器来获取数据,并使用适当的 CORS 标头将其重新提供给我们。 crossorigin.me 对此很有用。 您只需将其 URL 添加到我们一直在构建的 URL 的前面

var url = "http://crossorigin.me/http://www.colourlovers.com/api/palettes/top?format=json&numResults=5&resultOffset=" + rand;

获取颜色数据

现在我们有了返回所需数据的 URL,让我们使用 jQuery Ajax 方法来获取它。

$.getJSON("http://crossorigin.me/http://www.colourlovers.com/api/palettes/top?format=json&numResults=5&resultOffset=" + rand, function(data) {
  console.log(data);
});

拿到了!

给 SVG 着色

该数据对象包含我们进行着色所需的一切。 我们将遍历所有 <svg>,以及作为嵌套循环的内部所有 <circle>

jQuery 的 .each() 对此很有用,它还为我们提供了一个参数来跟踪迭代。 我们将使用它们从数组中提取单个颜色,并将其应用为 <circle>fill 属性

$("svg").each(function(x) {
  // x will be 0, 1, 2, etc.
  $(this)
    .find("circle")
    .each(function(y) {
      // y will be 0, 1, 2, etc.
      $(this).attr("fill", "#" + data[x].colors[y]);
    });
  console.log("Palette #" + x + ": " + data[x].colors)
  // "Palette #1: 351330,424254,64908A,E8CAA4,CC2A41"
});

瞧!

查看 CodePen 上的示例
调色板圆圈
,作者:Chris Coyier (@chriscoyier)
CodePen 上。