跳至正文
全部文章

设计「易」:六根斜杠是怎么来的

从一个字的上下结构出发,在打印的辅助线上用铅笔推演,再把手稿收成整数坐标、1:2 斜度的几何,最后做成跟随主题变色的组件和可以按下的等轴测 3D。

约 5 分钟#设计#Logo#SVG

本站左上角的标志是一个「易」字:上面三道细斜杠是「日」,下面三道粗斜杠是「勿」,六根杠的右端切齐在同一条竖线上。下面三道杠的颜色跟着站点的颜色主题走,切到红色主题它就是红的。

这篇讲它从一个想法变成组件的过程:为什么用斜杠,在纸上怎么推出来,怎样把手稿收成可以检查的几何,以及放到页面上时遇到的问题。

意图:一个「易」字,两组三道杠

「易」上面是「日」,下面是「勿」。这个字有变易、简易、交易三层意思,对一个写代码的人来说,把复杂的东西变简单,本身就是「易」。

把「易」拆成上「日」下「勿」,再落到六根斜杠上

这个方向不是一开始就有的。上一版标志是一个带 >_ 终端提示符的方块,下面接三道 45° 斜撇,用了几天总觉得复杂:外轮廓 18 个顶点,加两个孔,缩小以后细节全糊在一起。但整个标志里最有辨识度的,一直是下面那三道斜撇。

于是反过来想:既然三道杠最好认,能不能整个字都用杠来写?「勿」本来就是几道撇,三道粗杠可以留下;「日」是一个扁框,里面一横,正好也是三道横画,可以换成三道细杠。上下两组,各三道。

推演:在打印的辅助线上用铅笔涂

这种几何在屏幕上拖点很难找到感觉,我干脆打印出来手画。先做了一张 A4 辅助线稿,一页四格,每格里预先填好下面三道粗杠,斜线统一 1:2,杠厚 72,杠距 26,方格边长也是 26。然后用铅笔在上半部分试各种「日」的画法:

打印辅助线后,用铅笔涂出来的四种「日」

右下那格是最直白的写法:「日」是一个封闭的框,里面三道杠。其余几格在试杠的长短和起点。涂完能看出两件事:上面的杠要比下面细,否则两组粘成一团,分不出上下;杠与杠之间可以再靠近一点。

接下来就是做减法,每一步都比上一步少一样东西:

从上一版标志到六根斜杠,一步一步减

  1. 上一版标志里,被圈出来的是下面三道斜撇;
  2. 把它们放到下面做「勿」,「日」先画成一个实心块加一个孔;
  3. 「日」拆成三道细杠,左右两边各用一根竖条封住,还是一个框;
  4. 去掉左边的竖条,「日」不再闭合;
  5. 右边的竖条也去掉,每道杠缝都从右边穿出去。

到最后一步,六根杠彼此独立,只靠右端齐平连成一个整体,看上去像六道向右上扫过去的笔画。

收形:把手稿变成可以检查的几何

手稿只定方向,尺寸要在电脑上定。上组的杠厚和左端位置有好几种合理的组合,我把它们排成一张表,同一个尺寸、同一种配色并排看,也顺便看了双色的效果:

上杠厚度与左端位置的组合,以及双色示意

最后选的是上杠厚 36、上组左端和下组第三道杠对齐的那一版。然后把“看起来对齐”全部写成“必须落在这条线上”:

  • 外框 416 × 584;
  • 所有斜边都是 1:2,每根杠两端竖直切齐;
  • 下组三道杠厚 72,左端依次是 0 / 78 / 156,每道比上一道往右缩 78;
  • 上组三道杠厚 36,左端都在 156,和下组第三道杠对齐;
  • 杠与杠之间、两组之间的缝都是 26;
  • 六根杠的右端都切在 x=416。

手工制图:1:2 的斜向辅助线、杠厚与杠缝

几何由一个 Python 脚本生成,脚本里有三条自检:所有顶点必须是整数,斜边必须是精确的 1:2,总高必须是 584,不满足就直接报错。1:2 的好处是每横走 2 个单位正好升 1 个单位,只要左右端的 x 都是偶数,所有顶点就落在整数上,不会出现 130.5 这种坐标。脚本同时输出一张核对图,每条边的辅助线和每个尺寸都标在上面:

核对图:红色虚线是每条边,右侧数字是斜线在右边界处的高度,蓝色是杠厚与杠缝

最终的标志是六个平行四边形,上下两组各一条路径:

logo.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 416 584">
  <path fill="var(--logo-upper, currentColor)" d="M156 130 416 0 416 36 156 166ZM156 192 416 62 416 98 156 228ZM156 254 416 124 416 160 156 290Z"/>
  <path fill="var(--logo-lower, currentColor)" d="M0 394 416 186 416 258 0 466ZM78 453 416 284 416 356 78 525ZM156 512 416 382 416 454 156 584Z"/>
</svg>

不设置 CSS 变量时两组都是 currentColor,就是单色版;设置以后可以分别上色。

「易」从 256px 到 16px:亮色、暗色和双色

28px 以上两组都清楚。到 24px 和 16px,上组的细杠会糊成一片斜纹,剪影还认得出来,但已经看不清是六根杠了。

落地:组件与主题色

站点里的标志是一个 React 组件,直接内联 SVG。上组用 currentColor,跟着文字颜色走;下组加一个 fill-primary,跟着主题色走:

site-logo.tsx
export function SiteLogo({ className, ...props }: React.ComponentProps<"svg">) {
  return (
    <svg
      viewBox="0 0 416 584"
      fill="currentColor"
      aria-hidden="true"
      className={cn("h-8 w-auto overflow-visible", className)}
      {...props}
    >
      <path data-part="upper" d="M156 130 416 0 …Z" />
      <path data-part="lower" className="fill-primary" d="M0 394 416 186 …Z" />
    </svg>
  )
}

站点的亮暗模式和颜色主题是两个独立的维度,颜色全部来自主题变量。这样写以后,标志不需要知道当前是哪个主题:暗色模式下上组变白,切到橙色主题下组变橙。默认的中性主题里,主题色本身就接近黑白,两组看起来是同一个颜色,切到彩色主题才看得出双色。

宽高从固定的正方形改成了 h-8 w-auto,高度对齐页头,宽度按 416:584 自己算。浏览器标签页的图标不能跟着页面主题变,用的是单色版;SVG 图标里写了 prefers-color-scheme,系统切到暗色时变白。

立体:挤出成等轴测 3D

我写过一个通用组件 isometric-mark:传入平面多边形,自动挤出成等轴测线条 3D。顶面填斜纹,侧面填背景色挡住后面的线,线条上有一圈跟着鼠标走的高光,按下时顶面带着斜纹一起弹簧下沉。

铅笔速写:六根杠挤出成立体

新标志的六根杠是六个互不相连的平行四边形,正好可以直接传进去,每根杠各自挤出、各自遮挡。试着晃一晃鼠标、按住它:

正在加载…

组件里没有手画的路径,投影、背面剔除和遮挡排序都由代码从平面多边形算出来,换了标志只需要换一组顶点。

组件的用法和几何细节见 等轴测标志。

现在这组坐标同时用在三个地方:页头的标志、分享卡片左上角,以及首页那个可以拖动视角的等轴测 3D,改一处就得三处一起改。下次再动它,我大概还是会先打印一张辅助线稿,拿铅笔涂几格再说。