Skip to content

从零开始 Mapbox 应用开发

这是本系列开发专栏的第 02 章, 我们继续丰富上一章创建的脚手架,并添加一些必要的配置。

应用模板:lingr-dev/lingr-map-mapbox: A Lingerer map application, using Mapbox GL. (github.com)

1. 字体


运行在PC端浏览器上的页面通常默认采用操作系统提供的默认字体来渲染页面上的文字性内容,由于操作系统平台、版本包括用户个性化上的差异,可能会导致页面内容的布局排版产生不一致。

Web Font网络字体的出现为应用页面的视觉一致性提供了可能,近年来,各大平台厂商大力推广开源商用字体,也进一步丰富了我们的选择,让我们不必为字体美观而可能产生的版权纠纷而困扰。

以阿里提供的普惠体为例,我们首先将我们需要的字体文件拷贝至 public/fonts 目录下,由于字体文件普遍较大,运行在互联网环境时,我们也可以托管至 CDN 以提高加载性能。

public/fonts 目录下创建 font.css 文件以引用需要的网络字体。

css
@font-face {
  font-family: "AlibabaPuHuiTi";
  src: url("Alibaba-PuHuiTi-Regular.ttf") format("truetype");
  font-weight: normal;
  font-style: normal;
}

通过根目录下的 index.html 文件,我们可以引入写好的网络字体文件样式,并进行全局设置。

index.html

html
<!doctype html>  
<html lang="en">  
  <head>
  <link rel="stylesheet" crossorigin href="./fonts/font.css" />
  <style>
	* {  
	  font-family: "AlibabaPuHuiTi";
	  font-size: 14px;
	  font-weight: normal;  
	}
  </style>

我们还可以按需引入其他的网络字体包,包括各种数字字体,标题字体等。其他免费的可商用字体包括:

2. 颜色


现代前端应用构建通常离不开UI套件的支持,得益于像Ant Design、Element UI、Naive UI等前端优秀的UI套件,我们现在不需要花费太多的精力去完善常用的原生组件的样式。

很多时候因为有专职的UI设计师协同工作,前端开发人员在拿到完整的UI设计稿之后,首先会通过选型UI套件中提供的内置主题,找到与设计师设计接近的UI套件色彩,在此基础上完善应用其他的部分。有时设计师选用的色彩难以匹配任何UI套件的主题色,亦或者我们的应用代码本身也需要考虑主题色彩切换的功能,这里我们讨论的颜色并非设计师考量的搭配、色轮或者色彩学,而是从软件设计师的角度出发,对应用框架中的颜色和样式代码进行合理的代码架构设计和划分,以便于开发人员自身对全局色彩的调用以及实现更多高阶的功能。

1)系统颜色变量管理

在上一章节,我们通过对scss预处理器的配置,约定了在 /src/assets/style/mixin.scss 路径下的文件作为全局的样式表,并通过Vite自动注入到每个Vue组件的样式中方便调用。

而对mixin文件中的颜色,我们采用Scss变量的方式来声明,首先我们对应用全局可能用到的样式进行如下分组:

颜色组命名前缀
交互色interactive
UI主色ui
UI背景ui-background
文本色text
反转色inverse
区域色field
辅助色support
焦点色focus
悬浮色hover
活动色active
选中色selected
禁用色disabled
访问色visited

通过以上的初步分组,我们将统一声明以下的全局的颜色变量以供组件调用:

css
// interactive
$interactive-01: #;
$interactive-02: #;
$interactive-03: #;
$interactive-04: #;

// ui
$ui-01: #;
$ui-02: #;
$ui-03: #;
$ui-04: #;
$ui-05: #;
$ui-background: #;

// text
$text-01: #;
$text-02: #;
$text-03: #;
$text-04: #;
$link-01: #;
$inverse-01: #;
$inverse-02: #;
$field-01: #;
$field-02: #;

// support
$support-01: #;
$support-02: #;
$support-03: #;
$support-04: #;

$focus-01: #;
$hover-primary: #;
$hover-primary-text: #;
$hover-secondary: #;
$hover-tertiary: #;
$hover-ui: #;
$hover-selected-ui: #;
$hover-danger: #;

$active-primary: #;
$active-secondary: #;
$active-tertiary: #;
$active-danger: #;

$visited-link: #;
$disabled-01: #;
$disabled-02: #;
$disabled-03: #;

3. 图标


图标作为一类通用的设计资源,现在网页设计中大量应用到了图标,以至于出现了如Material Icons、Material Symbols一类的图标资源包。我们在现代的应用开发设计中不可避免的需要用到各类图标资源,国内也有例如iconfont这一类直接下载各种图标资源的网站可以按需取用。然而,每当需要某个图标时都要先去网站搜索并下载,然后拷贝至应用public目录再通过相对路径来引用的方式不仅繁琐,也极大的影响到了开发的效率,我们需要一种方式将常用的图标资源库整体配置到开发脚手架当中来,做到一步到位,随时使用。

Iconify 便是这样的一个图标集合资源库,他提供一站式的方式可以让我们仅引入一次便可以畅享其中多种不同来源的图标资源包,包括了Google Material Icons等在内的海量主流图标资源。Iconify网站提供了多种不同的形式让我们快捷引用其中的图标资源,其中就包括了通过svg标签的形式直接复制每个图标的形状,无论是作为svg标签嵌入html,还是作为css资源,这会造成我们的源代码文件变得冗长而难以阅读。另外一种方式是通过unplugin-icons 插件包来直接通过 package/name 的形式快速引用图标,配合 @iconify/json 全量图标离线包,我们可以做到在应用页面中按需引入对应的图标资源,同时满足各种离线环境的使用。

我们首先安装所需的插件与全量图标库:

bash
pnpm i -D @iconify/json
pnpm i -D unplugin-icons

之后,我们为vite配置图标组件的处理插件,即可像普通的组件引用一般直接使用任何图标。

javascript
// vite.config.ts
import Icons from 'unplugin-icons/vite'

export default defineConfig({
  plugins: [
    Icons({ /* options */ }),
  ],
})

通过联合 unplugin-vue-components,可以让vite帮助我们自动引入所需要的任何图标组件,避免大量无谓的import语句。

bash
pnpm i -D unplugin-vue-components
javascript
// vite.config.js
import Vue from '@vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import Components from 'unplugin-vue-components/vite'

export default {
  plugins: [
    Vue(),
    Components({
      resolvers: [
        IconsResolver(),
      ],
    }),
    Icons(),
  ],
}

至此,在Vue的单文件组件代码中,我们可以直接通过以下的形式引用来自iconify的任何图标资源包:

html
<template>
  <i-carbon-accessibility/>
  <i-mdi-account-box style="font-size: 2em; color: red"/>
</template>

对于vue-router等非组件环境下,我们可以借助于Vue提供的defineAsyncComponent来动态引用任意的图标资源。

javascript
// router.js
import { defineAsyncComponent } from "vue";

const router = createRouter({
	routes: [{
		path: "home",  
		name: "首页",  
		meta: {  
		  icon: defineAsyncComponent(() => {  
		    return import("~icons/mdi/home?width=18px&height=18px");  
		  }),  
		},  
		component: () => import("../pages/home.vue"),
	}]
});

通过以上这些配置,我们为应用脚手架添加了更多灵活的开发能力,后面我们将继续在此基础上扩展和深入的定制我们的开发框架。

如果你觉得本文对你有些许启发,请持续关注我的公众号“戈伊星球”吧!

Released under the MIT License.