在B端产品中,数据主要通过表格的形式展现。本文是我从实际工作出发,结合项目和过去经验对于复杂业务类的表格设计的一次总结。
表格(Table),又称为表,是用来收集、整理、组织、分析数据的二维矩阵。它既是一种可视化交流模式,又是一种组织整理数据的手段。
通常表格的组成元素以及相关元素会有多个部分,笔者根据自己设计表格的工作经验将表格概括为容器、筛选区、功能性按钮、表头、表体以及底栏等六个部分,其各个部分包含的相关元素如图所示。
容器:包含表格的所有内容。
筛选区:包括搜索和条件筛选。方便用户快速查询定位数据,一般位于表格上方。
功能性按钮:比如常见的[新增]按钮和各种批量操作按钮。
表头:说明数据的内容,可以包含筛选、排序等功能。
表体:包含行和列数据,按列可以分为多选列、数据列、操作列。(多选列=多选框;数据列=呈现业务展现需要的信息;操作列=针对单行数据的操作按钮,比如管理、编辑信息等。)
底栏:包含数据量、单页条目、总条目、分页等,底栏数据也可以放置在表格顶部。
1)几种常见的风格样式
a.网格型:表格有均匀而明显的分割线,边框单元格比较明显。
b.水平线型:仅显示水平线可减少整个网格的视觉噪声。
c.斑马条纹型:隔行交替使用不同底色来区分数据。
d.自由形式:移除所有分割线,通过尽可能减少视觉噪声来创建极简外观。
2)关于样式的选取技巧
网格型:对于数据之间的关系紧密(列信息较多而没有足够空间用留白来分割信息)且有对比关系的。
水平线型:它能显著减轻表格在垂直方向的视觉重量,提升用户进行大量数据对比时的速度。因此对于所有数据集大小,此样式都是最常见的。
斑马条纹型:每行交替使用不同的颜色背景是帮助用户在阅读时保持其位置的另一种好方法。对于较大的数据集,建议使用此样式,在较大的数据集中,交替模式将很清晰,并且不会引起特定行突出显示的混乱。
自由形式:对于小型数据集,如果用户在阅读时不需要帮助就可以保持位置,则建议使用此样式。
信息内容的有效传达是表格设计的本质,就表格本身而言应该是隐型的,应该让用户注意力聚焦在核心内容上。所以,边框的颜色应非常淡,不能妨碍快速浏览。
表格是为可读性而生的,一个结构清晰的布局能大大提升用户对信息的接收速度和理解程度。因此,设计易读,易扫视,易比较,易操作的表格结构是表格设计的首要目标。
下面我将以公司财务中台的表格改版为例,逐步说明表格中每个结构的设计。
这是改版前后样式对比图:
筛选区可以看作表格的导航,由搜索和筛选这两部分组成。一般搜索和筛选会同时出现,但是两者一般很少同时使用来对数据进行定位。搜索更多的是对单一或者包含某个字段的的数据来进行定位;筛选则是用来查询一类数据。
根据MECE分析法,筛选区可以有以下的表现形式:
常用搜索少用筛选,若筛选项多,可以选择隐藏筛选项,筛选少可以展示出来;
搜索和筛选都常用,可以将搜索和筛选都展示出来;
常用筛选少用搜索,筛选和搜索同时展示;
筛选和搜索都不常用,展示搜索隐藏筛选。
1)搜索
在样式上,搜索可以分为简单搜索、标签搜索、高级搜索等三类。
简单搜索:由一个搜索框和一个按钮组成。可以输入一个或多个条件进行搜索。
标签搜索:在简单搜索的基础上加上标签,即先选标签,在输入搜索内容。
高级搜索:即点击更多展开其他搜索条件,减少了更多条件对用户的干扰,但降低了易发现性。
2)筛选
根据筛选的位置,可以分为标签筛选、表头筛选两类。
3)案例小讲堂
对于数据集较大的B端系统来说,往往筛选条件比较多,都将其展示出来会导致空间占比过大,影响了用户对表格信息的获取。下面以我公司的财务中台为例,讲讲如何优化筛选区,希望对大家有所启示。
3.2.3 版本中筛选区样式
筛选条件全部展开,目的是让用户对信息进行快速的查询、过滤,以快速准确完成目标任务。但业务复杂,数据集过多少,筛选条件也相应增加(空间占比大),看起来非常冗余,不利于快速定位目标。为了平衡扫描、查询、过滤、分析等这些操作,复杂业务的表格区筛选需要进行一定的优化处理,这样才能满足满足业务需求同时,又符合用户心智模型。
方案A 整齐划一
整合筛选项,采用表头筛选+标签筛选的样式,缩减筛选区的页面空间占比。
讨论结果:虽然这个方案使筛选区的空间占比缩小,整体页面也看似整洁不少。但表头筛选在复杂的业务系统中存在几个弊端:
a.数据集往往很庞大,表格不能展示所有字段,往往采用列固定的形式来呈现数据的完整性。以财务中台为例,高频筛选功能已被遮挡(如上图),筛选前需先对表格进行横向滚动,无端增加操作;
b.应无法展示全部字段,用户无法清晰的感知到筛选了哪些内容,增加认知学习成本;
c.表头中的属性并不是都可以进行筛选,用户不可感知哪些可以筛选,需要滑动表格检索。
方案B 强调主次关系
采用展开式的标签筛选样式,对不常用的筛选项做隐藏处理。但因业务场景的复杂度,高频筛选功能还是很多,没有解决本质的问题,如下图:
方案C 分状态展示(逐渐呈现)
在方案B的基础上进行了优化。提炼与流程相关的状态,按步骤显示,每一步只显示当前需要关注的内容,如图:
状态的提炼过程
1)整理每个单据的状态,理清关系
结合业务流程可以很明显的注意到,单据只有通过了审核才能收款,只有收款才能进行核销。状态是一种递进关系(审核 ➡️ 收款 ➡️ 核销)。
2)结合财务人员的工作流,提炼出单据的以下几种状态,之前存在到问题(表格中单行数据的操作不一致),也得到了完美的解决。如图:
1)按钮的表现形式
建议在复杂系统设计中使用圆角矩形的按钮样式。
理由如下:
a.人眼处理圆角更容易(认知负荷说)
Jürg Nänni(Visual Perception的作者)表示,视网膜中区处理正圆形的时候是最快速的,而处理边边角角的时候则比较费力,大脑处理的速度也较慢。于是,长得圆润的圆角矩形相较于一般矩形,对于使用者来说就容易接纳许多。
Barrow Neurological Institute (巴罗神经病学研究)的研究也显示,一个物体的显著度与边角的角度呈线性变化,锐角相较于钝角要显得更明显突出。换句话说,角度越尖锐,物体就看起来越明亮;而越明亮的物体就越难以直视。
如上图所示角度越尖锐,看起来越显眼,在视觉上也比较令人感到明亮,不适,大脑的认知符合也越高。
b.使相似的内容更容易被区别
举个例子,如下图所示,即便间距相同,B 排的圆角矩形辨识度还是明显比A 排的矩形高。
这是为什么呢?
首先,第一眼看过去的时候,A 排的矩形整体是连在一起的,中间找不到断点。而B 排矩形,因为有圆角的关系,所以断点很明显。
其次,两种矩形的视觉聚焦:A 排由于直角的关系,视觉聚焦向外推,整体的效果比较发散。这会使得第一眼看过去的时候,容易分不清楚哪一条边框属于哪一块矩形。反之B 排因为圆角收拢的关系,视觉聚焦向中心推,区块就比较容易区别开来。
综上所示,圆角矩形是非常有效率的容器,在复杂场景业务中(存在很多种功能型按钮),按钮采用圆角矩形样式最提效。
这里要注意,圆角不是越大越好
在相同面积中,按钮的可操作区域随着圆角的增大而递减,因此在同等尺寸下的按钮中,小圆角的按钮明显比大圆角的按钮更容易操作。
同时在实际业务中,按钮常常被当作原子与下拉框联动组成下拉菜单控件。如若使用半圆按钮则无疑增加了下拉框的设计难度并且匹配起来也会略显突兀。
2)批量操作按钮的位置思考
来看个举个例子(针对财务中台批量操作的优化方案)
现存问题
方案A 信息前置
批量操作按钮全部展开不做折叠处理,信息前置来降低认知成本,方便用户记忆。
讨论结果:对于复杂业务来说,会有很多批量操作功能,按钮很多,造成页面拥挤,进而影响用户操作体验;一个位置出现2个主按钮样式,不推荐。
方案B 沉浸式操作体验
对于一开始不可用的批量操作按钮进行隐藏,勾选激活状态,显示在筛选区。
讨论结果:方案B的阻断性强 — 无法兼顾批量操作和数据筛选功能,无法满足复杂系统的场景操作。
方案C 上内容下操作,前2个方案的优化
不做隐藏,类灰布置于底部。勾选触发操作条件,未做勾选时,用户点击时给出引导操作提示
为什么选择方案C?理由如下:
首先,根据古腾堡原则,用户的在做表格操作的时候,视觉流是左做到右,从上到下,方案A和方案B的视觉落脚点在表格的上方,显然是不符合眼动规律的。
其次,批量操作的功能属于财务中台的核心功能点,隐藏不是第一选择,而是类置灰的特除处理(在按钮旁给提示信息)
2.3表头设计
表头在能够概括的情况下,尽量简练、准确,一般可根据上下文关系来进行减短简化,以达到节省表格头部空间和减轻视觉压力的作用,让用户注意力聚焦在数据本身。如果精简后的生僻字段难以自我解释,可以跟一个释义标识,鼠标悬停时出现该字段的详细解释,同时满足新手用户、普通用户以及专家用户的需求。
在数据的对齐方式上,有以下3个建议:
a.文本左对齐
b.数字右对齐
c.表头与信息内容对齐方式一致
文本左对齐,符合正常的心智模型(阅读习惯从左到右);表头与内容对齐一致,则是为了简化和降低视觉噪音,以便更好的获取数据信息。数字右对齐,有利于数据间的对比。
要注意的一个细节,例如,当列数=2的时候,由于列与列直接的间距过大,导致两者的关联性较弱,如图:
这时又该如何处理?
为了增强列与列之间的相关性,当鼠标hover在行的时候,产生高亮。这种方式可能不是最优的,但目前只能想到这种方法,如果读者有更好的想法欢迎留言。
2)数字的字体选择
建议选用:Helvetica Neue、Helvetica、Arial、sans-serif.
苹方在数字字符上,不同数字宽度不一致,导致千位分隔符不在一条线上。而Helvetica Neue数字等宽,千位分隔符有序的排列在一条线上。所以,选择Helvetica Neue作为数字字体的首选字体。数值上下对比的时候,相同位置的数字在同一条竖线上,更加容易对比。
3)对操作项进行“解耦”处理
在财务中台系统中,常常由于权限的不同或者单据状态不同这两种原因,使得每行的数据拥有不同的操作项,如下图所示:
存在的问题:
当信息过载,操作项这个list非常长的话,页面将会非常拥挤;
文字按钮因为视觉特征比较明显,造成了不必要的分散注意力;
误操作率相对较高,同样因为表格空间有限,当操作区非常靠近,很容易一不小心就点错了。
针对这个问题所出的解决方案,如下:
方案A 下拉框样式
讨论结果:下拉框中可能存在不同操作,同样避免不了误操作这个问题。
方案B 错位显示
讨论结果:首先,这样的设计浪费大量的屏幕空间;其次,浪费开发工作量!因为在列表中实现一系列权限判断和操作,在详情界面中往往还需要再开发一次相同的权限判断和操作;再次,不同单据可能存在操作顺序不一样,上下移动鼠标会存在不同操作,用户代价非常高。
方案C 以不变应万变
回归『一个界面一个用户任务』的原则,列表中的单行数据只保留[查看]或[管理]操作,所有其它的单独操作都去往该单据的详情界面完成。
讨论结果:从开发的角度上看,此方案界面高度解耦,功能迭代方便,节约开发工作量;从认知成本上看,列表界面操作高度一致性,利于养成用户习惯;从操作效率上看,在详情页用户会明显确认目标单据,几乎不会误操作; 同时此方案节约了大量屏幕空间,更有利于用户对信息的获取;
4)关于表格中套表格的解决方案
场景:在财务中台中,有这样一种用户,需要对表格内的数据进行对比并编辑。
来看看之前的页面:
这样处理的不足点:
1.在查看和编辑信息时,无效的信息太多。降低了获取信息的效率;
2.切换单条数据时,页面出现跳动,无法快速检索到相对应的信息;
对此,在3.3.2版本中,我们对其做了相应的优化。运用侧视图(快速视图)的方式来呈现信息。一旦选择一个单据,它就会从侧面弹出的。
这个方案,它可以保持上下文,易于使用,即使是在垂直滚动视图中显示大量字段的情况下也效果良好。同时信息呈现的地方是固定的,利于检索,查找。
5)行高的制定方法
开始之前首先明确一下开发是怎么实现行高的。
从上图可以看出,开发在实现设计稿时,通常是按照行高来写的。
因此,表格行高=文字行高+上下间距。其中,文字行高可以设定为字号的1.2~1.8倍,上下间距可以设定为字号的1~1.5倍。
行高影响每行信息的易读性。除了上述的做法外,还有以下2种做法,来保证各场景下获取信息的效率与易读性。
做法1:不同分辨率使用不同行高
设计两套不同的行高,在大分辨率下显示较高的行高,给数据间提供更多呼吸的空间;在小分辨率下显示较小的行高,使一屏内可以看到更多的行高。Gmail就是这样设计的,如下图所示:
做法2:自定义行高
自定义行高为兴奋需求,可以提高用户的用户体验。所以我们可以视表格的具体情况来设计设置行高的形式,可以放置在设置按钮里,也可以在外部按钮较少的情况下展示出来。
2.5底栏设计
最后是表格的底栏,底栏也是不可缺少的一部分,承载的作用主要是告诉用户数据条数以及当前位置。分页的设计是根据不同的场景进行选择最优的设计方案。在不需要定点跳转的场景,建议建议删除跳页,删除多于的功能,使页面简洁、清爽。
表格中经常会出现空数据或无数据的情况,留白处理会给用户造成一定的困惑和误解,是系统没有加载出来吗?明智的做法,是无数据时用「-」来填充显示,数据为零时与上下数据单位、小数点相同的0来显示。
尽量减少视觉符号的使用,因为视觉符号可能会使你的用户界面复杂,产生难以理解的内容。去除不必要的视觉干扰,例如不必要的图标、无规律的色彩等。
当列表中数据过长时,我们需要根据屏幕宽度调整列表展示方式,超过列表默认宽度的内容可以省略,通常用...表示,鼠标移入后出现气泡展示全部内容。
位置:建议展示在上方,因为我们的阅读顺序是从上到下,鼠标向下移动时不会被上面的气泡遮挡住。气泡面积不宜过大,根据屏幕尺寸控制在一定比例,一版不超过内容区的四分之一,展示不下的内容可以在气泡中增加滚动条。
感谢阅读!本文结合了实际项目经验对表格设计做了一次总结,在具体项目中,你可能需要根据产品特性和用户需求进行调整。如果你还有什么好的想法和建议,可以在评论里留言讨论。
文章来源:站酷 作者:Hi_Nick
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
单页面应用特征
假设: 在一个 web 页面中,有1个按钮,点击可跳转到站内其他页面。
多页面应用: 点击按钮,会从新加载一个html资源,刷新整个页面;
单页面应用: 点击按钮,没有新的html请求,只发生局部刷新,能营造出一种接近原生的体验,如丝般顺滑。
SPA 单页面应用为什么可以几乎无刷新呢?因为它的SP——single-page。在第一次进入应用时,即返回了唯一的html页面和它的公共静态资源,后续的所谓“跳转”,都不再从服务端拿html文件,只是DOM的替换操作,是模(jia)拟(zhuang)的。
那么js又是怎么捕捉到组件切换的时机,并且无刷新变更浏览器url呢?靠hash和HTML5History。
hash 路由
特征
类似www.xiaoming.html#bar 就是哈希路由,当 # 后面的哈希值发生变化时,不会向服务器请求数据,可以通过 hashchange 事件来监听到 URL 的变化,从而进行DOM操作来模拟页面跳转
不需要服务端配合
对 SEO 不友好
原理
hash
HTML5History 路由
特征
History 模式是 HTML5 新推出的功能,比之 hash 路由的方式直观,长成类似这个样子www.xiaoming.html/bar ,模拟页面跳转是通过 history.pushState(state, title, url) 来更新浏览器路由,路由变化时监听 popstate 事件来操作DOM
需要后端配合,进行重定向
对 SEO 相对友好
原理
Html5 History
vue-router 源码解读
以 Vue 的路由vue-router为例,我们一起来撸一把它的源码。
Tips:因为,本篇的重点在于讲解单页面路由的两种模式,所以,下面只列举了一些关键代码,主要讲解:
注册插件
VueRouter的构造函数,区分路由模式
全局注册组件
hash / HTML5History模式的 push 和监听方法
transitionTo 方法
注册插件
首先,作为一个插件,要有暴露一个install方法的自觉,给Vue爸爸去 use。
源码的install.js文件中,定义了注册安装插件的方法install,给每个组件的钩子函数混入方法,并在beforeCreate钩子执行时初始化路由:
Vue.mixin({
beforeCreate () {
if (isDef(this.$options.router)) {
this._routerRoot = this
this._router = this.$options.router
this._router.init(this)
Vue.util.defineReactive(this, '_route', this._router.history.current)
} else {
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
}
registerInstance(this, this)
},
// 全文中以...来表示省略的方法
...
});
区分mode
然后,我们从index.js找到整个插件的基类 VueRouter,不难看出,它是在constructor中,根据不同mode 采用不同路由实例的。
...
import {install} from './install';
import {HashHistory} from './history/hash';
import {HTML5History} from './history/html5';
...
export default class VueRouter {
static install: () => void;
constructor (options: RouterOptions = {}) {
if (this.fallback) {
mode = 'hash'
}
if (!inBrowser) {
mode = 'abstract'
}
this.mode = mode
switch (mode) {
case 'history':
this.history = new HTML5History(this, options.base)
break
case 'hash':
this.history = new HashHistory(this, options.base, this.fallback)
break
case 'abstract':
this.history = new AbstractHistory(this, options.base)
break
default:
if (process.env.NODE_ENV !== 'production') {
assert(false, `invalid mode: ${mode}`)
}
}
}
}
全局注册router-link组件
这个时候,我们也许会问:使用 vue-router 时, 常见的<router-link/>、 <router-view/>又是在哪里引入的呢?
回到install.js文件,它引入并全局注册了 router-view、router-link组件:
import View from './components/view';
import Link from './components/link';
...
Vue.component('RouterView', View);
Vue.component('RouterLink', Link);
在 ./components/link.js 中,<router-link/>组件上默认绑定了click事件,点击触发handler方法进行相应的路由操作。
const handler = e => {
if (guardEvent(e)) {
if (this.replace) {
router.replace(location, noop)
} else {
router.push(location, noop)
}
}
};
就像最开始提到的,VueRouter构造函数中对不同mode初始化了不同模式的 History 实例,因而router.replace、router.push的方式也不尽相同。接下来,我们分别扒拉下这两个模式的源码。
hash模式
history/hash.js 文件中,定义了HashHistory 类,这货继承自 history/base.js 的 History 基类。
它的prototype上定义了push方法:在支持 HTML5History 模式的浏览器环境中(supportsPushState为 true),调用history.pushState来改变浏览器地址;其他浏览器环境中,则会直接用location.hash = path 来替换成新的 hash 地址。
其实最开始读到这里是有些疑问的,既然已经是 hash 模式为何还要判断supportsPushState?是为了支持scrollBehavior,history.pushState可以传参key过去,这样每个url历史都有一个key,用 key 保存了每个路由的位置信息。
同时,原型上绑定的setupListeners 方法,负责监听 hash 变更的时机:在支持 HTML5History 模式的浏览器环境中,监听popstate事件;而其他浏览器中,则监听hashchange。监听到变化后,触发handleRoutingEvent 方法,调用父类的transitionTo跳转逻辑,进行 DOM 的替换操作。
import { pushState, replaceState, supportsPushState } from '../util/push-state'
...
export class HashHistory extends History {
setupListeners () {
...
const handleRoutingEvent = () => {
const current = this.current
if (!ensureSlash()) {
return
}
// transitionTo调用的父类History下的跳转方法,跳转后路径会进行hash化
this.transitionTo(getHash(), route => {
if (supportsScroll) {
handleScroll(this.router, route, current, true)
}
if (!supportsPushState) {
replaceHash(route.fullPath)
}
})
}
const eventType = supportsPushState ? 'popstate' : 'hashchange'
window.addEventListener(
eventType,
handleRoutingEvent
)
this.listeners.push(() => {
window.removeEventListener(eventType, handleRoutingEvent)
})
}
push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
const { current: fromRoute } = this
this.transitionTo(
location,
route => {
pushHash(route.fullPath)
handleScroll(this.router, route, fromRoute, false)
onComplete && onComplete(route)
},
onAbort
)
}
}
...
// 处理传入path成hash形式的URL
function getUrl (path) {
const href = window.location.href
const i = href.indexOf('#')
const base = i >= 0 ? href.slice(0, i) : href
return `${base}#${path}`
}
...
// 替换hash
function pushHash (path) {
if (supportsPushState) {
pushState(getUrl(path))
} else {
window.location.hash = path
}
}
// util/push-state.js文件中的方法
export const supportsPushState =
inBrowser &&
(function () {
const ua = window.navigator.userAgent
if (
(ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&
ua.indexOf('Mobile Safari') !== -1 &&
ua.indexOf('Chrome') === -1 &&
ua.indexOf('Windows Phone') === -1
) {
return false
}
return window.history && typeof window.history.pushState === 'function'
})()
HTML5History模式
类似的,HTML5History 类定义在 history/html5.js 中。
定义push原型方法,调用history.pusheState修改浏览器的路径。
与此同时,原型setupListeners 方法对popstate进行了事件监听,适时做 DOM 替换。
import {pushState, replaceState, supportsPushState} from '../util/push-state';
...
export class HTML5History extends History {
setupListeners () {
const handleRoutingEvent = () => {
const current = this.current;
const location = getLocation(this.base);
if (this.current === START && location === this._startLocation) {
return
}
this.transitionTo(location, route => {
if (supportsScroll) {
handleScroll(router, route, current, true)
}
})
}
window.addEventListener('popstate', handleRoutingEvent)
this.listeners.push(() => {
window.removeEventListener('popstate', handleRoutingEvent)
})
}
push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
const { current: fromRoute } = this
this.transitionTo(location, route => {
pushState(cleanPath(this.base + route.fullPath))
handleScroll(this.router, route, fromRoute, false)
onComplete && onComplete(route)
}, onAbort)
}
}
...
// util/push-state.js文件中的方法
export function pushState (url?: string, replace?: boolean) {
saveScrollPosition()
const history = window.history
try {
if (replace) {
const stateCopy = extend({}, history.state)
stateCopy.key = getStateKey()
history.replaceState(stateCopy, '', url)
} else {
history.pushState({ key: setStateKey(genStateKey()) }, '', url)
}
} catch (e) {
window.location[replace ? 'replace' : 'assign'](url)
}
}
transitionTo 处理路由变更逻辑
上面提到的两种路由模式,都在监听时触发了this.transitionTo,这到底是个啥呢?它其实是定义在 history/base.js 基类上的原型方法,用来处理路由的变更逻辑。
先通过const route = this.router.match(location, this.current)对传入的值与当前值进行对比,返回相应的路由对象;接着判断新路由是否与当前路由相同,相同的话直接返回;不相同,则在this.confirmTransition中执行回调更新路由对象,并对视图相关DOM进行替换操作。
export class History {
...
transitionTo (
location: RawLocation,
onComplete?: Function,
onAbort?: Function
) {
const route = this.router.match(location, this.current)
this.confirmTransition(
route,
() => {
const prev = this.current
this.updateRoute(route)
onComplete && onComplete(route)
this.ensureURL()
this.router.afterHooks.forEach(hook => {
hook && hook(route, prev)
})
if (!this.ready) {
this.ready = true
this.readyCbs.forEach(cb => {
cb(route)
})
}
},
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
你平时填写过的最复杂的表单是什么?调查问卷还是文档信息录入?如果一个表单字段内容巨多,结构多变,填写耗时耗力,那你将如何设计你的表单,使之体验更佳?
1. 业务复杂,功能较多;
不知道大家是否看过法律合同之类的文件,多则好几箩筐,少也有厚厚一叠,类似的文档如果进行线上结构化,势必要同样要花费巨大的人力去填写表单,完成基础信息的录入工作,同时,由于录入的时间不确定,流程不明确等问题,也制约着表单的填写。
2. 流程较长,操作繁琐;
多个不同表单之间的互有关联又相互区别,填写的时候需要来回查看以确认信息,查阅和填写相互并行,操作繁琐。
3. 字段较多,关联项较多;
几乎每一个字段都有对应的关联项,每个单选字段的不同项决定不同的内容,同时,由于字段数量,层级划分不明确,会使填写的人失去定位,产生迷惑。
1. 内容分组,分步填写;
根据业务内容分级,合理运用颜色、间距、字体大小、卡片层级等进行信息分级
2. 实时保存,避免数据丢失,提供草稿功能,避免任务中断;
3. 字段分组,示意结构,联动项隐喻;
4. 信息自动带入,节省时间;
一般表单是与某项功能挂钩的,信息会在多个入口录入,因此在填写长表单的时候,如果能从系统中自动获取到数据,就可以自动为其填充,可根据业务场景,判断是否让其修改和更新。
5. 提供二次编辑功能,防止信息输入有误;
一般的长表单在涉及非审批流的时候,可以让其无限二次编辑,如果是处于审批流,则需要根据业务场景限制其编辑次数或者限定其编辑规则(草稿可编辑,一旦提交则不可编辑)。
6. 提供多人协作编辑功能;
如果一个长表单,需要多个不同的业务域的人来填写,那么需要协同编辑,并实时显示编辑的人员信息,同时,为了避免信息丢失和编辑错乱,在同一个表单下,同一时间应该限制只允许一个人进行编辑,等其提交完后,可允许其他人进行编辑。
7. 实时检验;
前端实时校验字段输入规则,后端统一校验信息交换规则。
比如对于数字输入框的校验、电话号码的校验、身份证号的校验,应该在前端实时完成,在鼠标离开焦点区域或定位到下一个字段的时候,提示其填写有误,这样做的目的是减少后续修改的次数,在长表单下,统一提示其填写错误会是一场灾难。
在点击保存并填写下一步或点击提交信息的时候,就需要跟后端交换数据,验证录入的信息,如果不匹配,则提示错误,并从上至下定位至相应的错误字段。
8. 做好填写引导功能;
要通过多种方式,引导表单的填写,
在开始填写之前,简要说明该表单的业务目标,大概需要花费的时间等;
开始填写后,关于每个字段的特殊说明,都需要标注出来,重要的要显示在页面上,不重要的就收起在注释符号中;
填写的过程中,切记不要到最后才告诉用户哪里出错了,重要的信息一定要提示到位,否则一旦出错,前功尽弃;
填写完成后,引导其下一步的操作,或者返回至列表。
9. 详情页也需要注意信息分级
表单填写完毕后的产出物就是详情页,详情页是需要浏览的,因此在设计详情页的时候,应该本着让用户浏览方便的原则去设计,需要注意以下几个点:
结构清晰。是指不要将内容一股脑的全堆在页面上,要做好信息的分类,同时,注意规划页面的层级。
设置快捷导航。如果一个表单是长且复杂的,那么其对应的详情页也会变得复杂和冗长,因此在页面的右侧或者顶部设置合理的快捷导航是很有必要的。
1. 提供快速返回顶部的按钮;
快速返回顶部按钮的使用要注意场景,如果你的页面比较长,且没有分组浏览的导航,那就需要设置快速返回顶部的按钮,但是在存在分组浏览导航和顶部悬浮标签的情况下,不建议使用快速返回顶部的按钮,因为在填写表单的时候,使用快速置顶的场景比较少。
2. 提供分组模块收起展开功能;
当一个模块混杂着各种信息的时候,单纯的模块分组已经无法处理它的复杂度了,因此需要收起高频且信息量大的模块,可以合理的减少页面的复杂度。
3. 步骤提供信息填写完成度提示;
步骤条可以单纯的作为步骤指示器使用,也可以作为一个表单完成度的提示区域。
4. 重要说明性文字尽量显示而非收起;
在填写大量字段的表单时,阅读表单内容和填写表单同样耗时耗力,如果我们将所有的提示信息隐藏在提示符中,一般情况下,用户不会去查看,但是如果去挨个查看提示信息,则会多花费一个步骤去点击或者悬停来查看提示信息,浪费了大量的时间,因此如果涉及到重要的提示信息,请直接展示在字段的后面,不要隐藏起来。
5. 产品内组件应该规范统一;
在后台产品上,关于组件的规范统一,想必是人尽皆知的设计原则,无论是各类平台型设计组件,还是各个公司自造的设计组件,保持统一和规范对产品设计有着重要的作用,在这里不赘述组件应该怎样规范统一,因为无论是Ant Design还是其他设计语言,都有详尽的关于组件的定义方法,我在这里讲述一个产品设计更高层面或者更深层面的原因:
组件的规范统一并不仅仅是为了省时省力,而是为了使用户在使用的过程中达到认知上的统一和行为上的统一,在进行高频次的操作后,界面的流程或者组件样式已大致在用户脑海中形成固定印象,因此在操作相同类的流程时,用户会有更多的掌控感,试想一下,如果你在操作人事相关的流程后,去填写绩效部分的内容时,发现一个迥异的界面或者弹窗,你肯定觉得这是不是哪里出错了,甚至会怀疑这是否是同一个系统,目前大多数公司的管理系统经过多次缝缝补补,内部的跳转逻辑已经异常感人,界面风格也大放异彩,但是使用起来却无从下手,深感迷茫。
因此大到界面样式,小到间距大小,产品设计的规范和统一应该是最基础又不可缺少的原则。
6. 庞大的信息录入,表单内部要分步填写,外部可拆分成不同的表单分别填写;
对付复杂的表单,你需要解决的主要问题并不是填写方式或者页面设计,而是信息分级和结构拆分,解决了这个问题,基本上就解决了业务问题,其余部分就跟我们常用的表单一致。
将复杂度降低并不意味着减少页面的信息,而是通过设计师合理的信息划分,降低视觉上的复杂度和流程上的复杂度,这样才会达到当前场景下的「最佳解决方案」。
随着互联网信息化的深入发展,复杂是避免不了的,我知道大家都推崇简洁的设计,但那只是对视觉和样式的定义,而非对信息的定义,我们所处的世界是复杂的,行业更是复杂的,信息的复杂度与日俱增,想要处理复杂的信息,就需要从复杂中寻求规律,这规律与业务息息相关,
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
按钮在界面设计中,属于最基础的元素部分组成,按钮设计的精致,整个页面的品质也会上升不少的档次。今天给大家分享这篇文章,主要讲解在设计按钮时我们应该考虑哪些因素,包括视觉上,有哪些万能的方法及公式,能够正确的制定按钮的设计标准,来提升整个设计的系统性。
在设计按钮之前,需要先理解按钮起到的代表含义。什么地方该加按钮,什么地方不加按钮,在系统化设计思路中需要非常有讲究。通常按钮在页面,主要起到以下三点作用:
1. 某一类型的功能操作
这种比较常见,如一些控件形态的按钮,比如加减、折叠、展开,下拉等。这类按钮会起到一些功能形态的作用,常用于交互场景。所以在这类按钮设计中,应当弱化按钮形式,重点强调功能,突出主体信息。
2. 下一步的明确指引
当页面内容信息过多后,用户容易失去信息焦点,从而忘记下一步操作。信息种类越多,用户权衡的时间就会越久,用户选择罢手及跳出的几率也会越大。所以这个时候,在合适的地方增添按钮,能够很好的引导用户进行下一步操作,提升整体操作的成功率。其次从体验层面,也一定程度能起到页面动线的引导作用,比如下方的一组卡片,在增添了按钮后行动点很明确,非常有点击欲望~
3. 固定习惯,明确心理预期
当用户知悉某个按钮能指向某个操作,或者获取某类信息后,长期以往用户就会形成使用这个按钮的习惯,这样对提升复访及固定心智是非常有效果。
所以如果你认为你负责的产品或者是内容,能持续为用户带来价值,那么在页面的关键节点,不如将按钮设计的更醒目。这样用户下次再看到这个按钮时,固定习惯会引导他持续的点击。
这里我不以按钮的长相来区分按钮的类型,如汉堡按钮或者别的什么的,意义不大。我主要还是想通过以按钮的功能区分,来划分类型,这样大家理解起来更为清晰。
1. 功能性质按钮
这类按钮见到的最多,我们常用的APP里,大量都充斥了这类按钮,这类按钮会起到重点的功能交互,帮助用户得到TA想要的信息。其次样式上面,其实圆形的点击欲,会更强一些,看起来也更利于点击。而方型的按钮,则显得更为正式、严谨。
公式:如果是圆形按钮,圆角的半径=高度的50%比较合适,而如果是方按钮,边角的小圆角半径控制在15%以下比较合适,我个人喜好用10%。
2. 聚焦大按钮
这类按钮通常见于一些核心页面的强指引,比如登录、注册、提交表单、或者是保存,等对页面全局进行操作的一些按钮。需要注意的是,这类按钮只适合对页面全局进行操作,而且页面中大按钮的数量不宜超过2个,信息尽量需要保持聚焦。
公式:基于@2x,这类大按钮的高度≥72px是比较合适的,通常的尺寸有 80px、88px、96px,大家可以根据产品面向的人群来定高度,如果页面面向的人群较为广泛,我建议采用 88px 或者是 96px 的这种大号版本,毕竟操作起来更为方便。
3. 吸底按钮
这类按钮的优先级,在整个页面属于最高,页面的所有信息,都将聚焦在这个按钮中。由于按钮是吸底的,所以会一直浮在页面上,不受页面篇幅影响控制。
需要注意的是,吸底按钮一定是页面最重要的功能,或者是整个页面的下一步指引,比如淘宝的立即购买,或者是饿了么、美团的立即下单,又或者是常见的充值界面。
公式:基于@2x,吸底的高度≥80px是比较合适,常见的尺寸有88px、100px、112px ,按钮的大小可以根据内容来定,建议高度保持在72px以上比较合适。这里需要注意的是,吸底的按钮,需要产出两套设计稿,一套为常规稿,一套为iPhoneX的适配稿。iPhoneX底部控件的区域高度为68px,所以iPhoneX设计稿的吸底高度=常规设计稿吸底高度+68px
另外在设计按钮的时候,也别忘了补充按钮的多个状态的设计稿。常见的状态,有以下四种:
1. Normal-正常态
这个为按钮的正常显示态,就是正常页面中的显示效果。
2. Hover-悬浮态
这个为按钮的悬浮态,一般只会出现在使用鼠标的时候。当鼠标指针停留在按钮时,按钮发出的特殊反馈,则为悬浮态。这类形式在移动端交互中无作用,所以移动界面设计中不需要考虑这个状态。
公式:正常情况 Hover 态增加 10% 黑色就可以,原理如下
3. Pressed-点击态
这个为按钮的按压态,就是按钮在被点击或者是按压后的效果。
公式:在APP设计中,点击后的效果我们设一个标准值让开发实现就好了。常用的值有按钮减少20%的透明度,或者增添20%的暗度,这两个都可以。通常我建议在亮色上的按钮,使用暗度叠加(增添20%的黑色),在暗色上的按钮,则使用透明度减少(透明度改为80%),实现效果原理参考 Hover 态那张配图
4. Disable-禁用态
当信息未填充完整,或者是某类条件未到,按钮会出现不可点击的状态,处于禁用形式,这个时候,按钮就会呈现禁用态。这个禁用态无论是web还是app,很多场景都会用到,所以建议设定一套标准的设计规范,避免重复定义这个效果。
公式:禁用态尺寸及大小不变,仅使用色值做区分。建议使用灰色或者是不透明色,常用的禁用色有#CCC或者#999,需要尽可能把样式做弱,避免用户做无效的点击。
在目前移动互联网设计中,虽然按钮的种类很多,但风格变的逐渐统一,更多都是色值及细节上的差异。从大的风格来看,按钮还是分为这这几种类型:扁平化、轻拟物、重拟物及游戏按钮。
1. 扁平化按钮
这类按钮我们设计用的最多,信息简洁,操作方便,形式追随功能。这里也给大家分享一下我在设计扁平化按钮的一些经验,比如高度宽度,以及阴影的色值。
公式:按钮高度,这个通常是文字字号的2.4倍然后取4的倍数整数,比如字号是24,那么按钮的高度=57.6,离4倍数最近的是56,所以高度=56,圆角=10%的高度,取整后是6px。
另外如果觉得不合适,也可以单位往8递增或者是递减即可,例如 56、64、72、80、88 px
按钮宽度:如果不是那种全局按钮,通常按钮的宽度=最多容纳字数的宽度+按钮高度,就好啦。还是以上面那个例子为例,按钮高度=56,文字宽度=96,那么按钮的宽度=56+96=152
2. 轻拟物按钮
这类按钮近几年变的非常流行,甚至QQ、淘宝,都开始大面积使用,因为这类按钮在保持信息简洁的同时,仍然有较强的点击欲,视觉上面也能够增添页面的品质感。
公式:渐变方向,建议采用水平渐变,重色在右侧,轻色在左侧更为合适。阴影色值我之前就写过,不知道大家还记得么,阴影颜色=按钮颜色的 Alpha50%,x=0,y=按钮高度的20%,模糊值=按钮高度的50%,扩展=按钮高度的 -15%,高级又简单,完美!
如果觉得这个弥散阴影太大的同学,也可以自己手动简单调整下,不碍事。(这个公式仅适用于Sketch,用PS的同学,也可以按照这个逻辑自行研究一下)
另外说一句,实际上这个阴影公式并没有什么很多的依据,大多数都是我个人原创总结出来的,简单好用。比如下面的这些按钮的样式,用了公式后的效果大家可以自行感受~
3. 重拟物及游戏按钮
在一些营销页面中,按钮的样式通常需要做的比较游戏化。游戏化的按钮,大部分会采取游戏场景中的元素,再采用拟物的手法,来进行打造。
通常游戏化的按钮,需要重点几个部分组成,学过素描的同学应该会知道,立体的物体,通常会有几大特征,分别为高光,亮部,暗部,投影及反光。那么如果我们需要绘制一个在营销或者游戏场景中使用的按钮,只需要保证这个按钮有高光,亮部,暗部,投影及反光的这些特征,然后饱满一点就,立马就可以出效果啦。
当然,我举的这几个例子都是最基础版本,如果你想做的更丰富一些,那也是没问题的,这个可以case by case 来定。
这个没有太多的公式可以总结,更多的是看设计师的基础美术水平啦~~
在写这篇文章的时候,突然刷到了一套新拟态的控件设计风格,有种眼前一亮的感觉。虽然这套设计视觉上很有层次很好看,不过感觉短时间之内,比较难大面积推广,因为开发实现起来还是会比较耗费成本。
我把源文件保存下来了,对这个感兴趣或者好奇这种效果如何实现的同学,可以下载源文件研究~~ sketch、psd、Figma 格式都有。
文章来源:优设 作者:UX小学
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
章节名称 | 地址 |
---|---|
Vue.js教程-安装和HelloWorld | https://coderhqf.blog.csdn.net/article/details/107574556 |
Vue.js教程-Vue项目的目录结构和.vue文件的构成 | https://coderhqf.blog.csdn.net/article/details/107621070 |
Vue.js教程-Vue基本指令 | https://coderhqf.blog.csdn.net/article/details/107677588 |
Vue.js教程-组件化开发 | https://coderhqf.blog.csdn.net/article/details/107783664 |
与传统PC桌面不同,手机屏幕的尺寸更加小巧操作,方式也已触控为主,APP界面设计不但要保证APP功能的完整性和合理性,又要保证APP的功能性和实用性,在保证其拥有流畅的操作感受的同时,满足人们的审美需求。
接下来为大家介绍几款手机appui界面设计
--手机appUI设计--
--手机appUI设计--
--手机appUI设计--
--手机appUI设计--
--手机appUI设计--
--手机appUI设计--
--手机appUI设计--
--手机appUI设计--
--手机appUI设计--
--手机appUI设计--
--手机appUI设计--
(以上图片均来源于网络)
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
更多精彩文章:
还记得2019年4月上映的复仇者联盟4么,漫威电影宇宙的第三阶段结束了,电影很精彩,但最令人震撼的是先导版的电影海报!就是那个「五彩斑斓」的黑~
从设计上看,海报的设计师是把光运用到极限了,通过逆光和环境塑造出了酷+神秘的视觉感受。光是一切视觉表现的基础,是构图和传递调性的关键,也是视觉表现重要的组成部分。所以今天就和大家聊聊啥样的光是一个牛X的光以及如何塑造一个合格的光影?
常见形式1-聚光
△ 图片来源:小米米家台灯1S
聚光是最常见光,也是在设计中用到最多的光,通常在塑造一个物体的时候就会用的到。
因为聚光的原因,场景更像个舞台,凸显「主角」的存在。具体的原理可以根据下图去理解。
常见形式2-自然光
自然光其实就是阳光,理论上讲其实光源是太阳也是聚光,但由于光源太过于庞大,无法真正的聚焦,所以就把这种光当成一种泛光源就好。在产品设计中也会经常看到类似的光源出现,比如行为召唤按钮:
因为不需要强有力的表现和氛围的营造,所以通常产品设计中更需要自然光来作为核心光源,通过泛光源去统一控制产品的光影体系就好(发布的 Mac OS – big Sur 的整体光源同样是自然光,下文会讲到)。
常见形式3-逆光
坦诚的讲逆光也是聚光的一种,只不过由于角度特殊,呈现的视觉效果也非常不一样,所以就单独把逆光拿出来说一说。当画面需要逆光来营造氛围的时候,只需要在固有色上加上黑色蒙板和边缘的高光就可以大概塑造出一个处于逆光的物体了。
小米是典型的逆光氛围营造高手,但万变不离其宗,依旧可以从海报里看到相同的方法。
△ 图片来源:小米传播物料
通常现实中的光源并非那么理想,光线的复杂超出肉眼所见。所以我们在绘制的过程需要注意到,可以适当的抽象。举个例子,自然光是普照的,所以我们抽象为四个小光源平均分布,依次打到物体上:
在他们叠加的部分可以清晰的看到,1是最重的,2其次,3再次。按照这个办法就可以获得光影的层级关系,在绘制轻拟态的图标或者运营活动中更加细腻。
△ 图片来源:09UI设计工作室-陌陌直播礼物设计
所有的光影其实都是帮助主体塑造体积感,一个合格的立体图形必须具备:高光/过度色/明暗交界线和反光这四个基本属性。
然后需要一点超现实主义的手法,把太阳光过滤下,从「赤橙黄绿青蓝紫」的色调里提取跟主体和谐的颜色(通常是补色),营造出介于真实与玄幻之间的美妙效果hiahia~
然后再在投影上加一点点色彩倾向,一个完美的黑八就出现啦~按照这种方法,你可以试着去尝试更多的物体/场景。(下图是笔者作品「插着红旗的地球」hiahia)
影响主体的除了光影之外就是材质了,近年来的三大巨头apple/Microsoft/Google的设计都在材质上下足了功夫,苹果的毛玻璃,微软的亚克力和谷歌的「纸」。
从趋势上看,材质的引入对产品中拉开层级关系上有巨大意义,以往的设计仅仅是通过光影和焦距来拉开关系,这两个维度在少量的叠加界面中还能有效果,但到了复杂的多窗口互压互叠里就不是那么奏效了,所以铁子们要善于运用材质区分产品显示的优先级。
△ 图片来源:Eric Hoffman – Big Sur Mac Icons
△ 图片来源:JIAJIE – WeSing Live gift
图标好坏除了造型之外最重要的就是质感了,通常图标也就是4种形式(如下图),类似苹果的系统图标和抖音直播间礼物的图标都是最后一种形式。
但如果仅仅是这样就太水了,既然都说了是干货预警,那就要拿出哥们看家的本领~此图是大家关注公号后就会收到的推图,主体就是一个POI的图标加上微信的对话框和代表干货的小星星营造出的氛围。
刨析下这个图,三个发光体和底下的投影,通过上文的讲解依次绘制完成~
之后就到了amazing的时刻了,打开photoshop找到「滤镜-模糊画廊-场景模糊」设置几个key-point,调试模糊值和透明度/亮度,最终完成对光影的塑造。
空气中的灰尘相信大家都不陌生,这种情况多数是一束光影从窗户里射入后,在光的折射下把平时看不到的灰尘统统照了个遍。
如果你是mac用户一定熟知keynote里的动画效果「轰然坠落」,这个效果是在模拟物体振动后弹开周围灰尘,非常震撼。在PPT的设计中你也可以同样借助光和雾来营造你想要的效果,下图是我在做工作总结的时候为了凸显Q4工作采用的办法。
光影轻拟物在产品设计中的应用面还是很广的,比如:图标、数据可视化、插图等等。而在大量扁平设计时代适量使用会显得很出彩,当然再好的教程也比不上大家多动手试试练练,所以铁汁们行动起来咯~
文章来源:优设 作者:Nana的设计锦囊
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
JavaScript 语言中的 for 循环用于多次执行代码块,它是 JavaScript 中最常用的一个循环工具,还可用于数组的遍历循环等。
我们为什么要使用 for 循环呢?打个比方,例如我们想要控制台输出1到1000之间的所有数字,如果单写输出语句,要写1000句代码,但是如果使用 for 循环,几句代码就能实现。总之,使用 for 循环能够让我们写代码更方便快捷(当然啦,否则要它干嘛)。
for 循环语法
语法如下所示:
for(变量初始化; 条件表达式; 变量更新) {
// 条件表达式为true时执行的语句块
}
变量初始化,表示代码块开始前执行。
条件表达式,定义运行循环代码块的条件。
变量更新,在循环代码块每次被执行之后再执行。
示例:
例如我们在一个HTML文件中,编写如下代码,实现计算1到100的总和:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS_侠课岛(9xkd.com)</title>
</head>
<body>
<script>
var result = 0;
for(var i = 1; i <= 100; i++) {
result = result + i;
}
alert(result);
</script>
</body>
</html>
在浏览器中打开这个文件,会弹出一个弹出层,弹出层中显示的是1到100的总和:
上述代码中,我们声明了一个变量 result 并给它赋值为 0,表示初始的总和为 0 。
然后在 for 循环中三个语句:
变量初始化 i = 1,表示从 1 开始计算。
条件表达式 i <= 100,表示只要 i 小于等于 100 循环就会一直执行,当 i 大于 100 循环会停止。
变量更新 i++,之前我们学运算符的时候学过,这是递增运算符 ++,表示为其操作数增加 1。
此时我们可以一点点来看这个 for 循环:
第一次循环: result = 0 + 1 // 此时result值为0, i的值为1
第二次循环: result = 1 + 2 // 此时result值为0+1,i的值为2
第三次循环: result = 3 + 3 // 此时result值为1+2,i的值为3
第四次循环: result = 6 + 4 // 此时result值为3+3,i的值为4
第五次循环: result = 10 + 5 // 此时result值为6+4,i的值为5
...
我们只需要搞清楚 for 循环中的执行原理,不需要手动来计算求和,只要写好代码,执行代码后计算机会很快会告诉我们1到 100 的总和。
再补充一下,上述代码中result = result + i,我们也可以写成 result += i,这是我们之前学过的加赋值运算符,还记得吗?
示例:
再来看一个例子,例如我们可以使用 for 循环来实现数组遍历,首先定义一个数组 lst:
var lst = ["a", "b", "c", "d", "e"];
在写 for 循环时,首先就是要搞清楚小括号里面的三个语句,因为我们可以通过数组中元素的下标索引来获取元素的值,而数组的索引又是从 0 开始,所以变量初始化可以设置为i = 0。第二个条件表达式,因为数组中最后一个索引为 lst.length - 1,所以只要小于等于 lst.length - 1,循环就会一直执行。而i <= lst.length - 1 就相当于 i<lst.length。第三个变量更新,当循环每循环一次,索引值就加一,所以为 i++。
所以循环可以像下面这样写:
for(i = 0; i<lst.length; i++){
console.log(lst[i]); // 输出数组中的元素值,从索引为0的值开始输出,每次加1,一直到lst.length-1
}
输出:
a
b
c
d
e
其实遍历数组还有一种更好的方法,就是使用 for...in 循环语句来遍历数组。
for...in 循环
for...in 循环主要用于遍历数组或对象属性,对数组或对象的属性进行循环操作。for...in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。
语法如下:
for (变量 in 对象) {
// 代码块
}
for 循环括号内的变量是用来指定变量,指定的可以是数组对象或者是对象属性。
示例:
使用 for...in 循环遍历我们定义好的 lst 数组:
var lst = ["a", "b", "c", "d", "e"];
for(var l in lst){
console.log(lst[l]);
}
输出:
a
b
c
d
e
除了数组,for...in 循环还可以遍历对象,例如我们遍历 侠侠 的个人基本信息:
var object = {
姓名:'侠侠',
年龄:'22',
性别:'男',
出生日期:'1997-08-05',
职业:'程序员',
特长:'跳舞'
}
for(var i in object) {
console.log(i + ":" + object[i]);
}
输出:
姓名: 侠侠
年龄: 22
性别: 男
出生日期: 1997-08-05
职业:程序员
特长:跳舞
动手小练习
请自定义一个长度为7的数组,然后通过 for 循环将数组中的元素遍历出来。
求和:1~100的奇数和。
求和:1~100的偶数和。
使用对象定义一个人的个人信息(包括姓名、性别、年龄、出生日期、兴趣爱好、职业、特长等),然后使用 for...in 循环将这些信息遍历输出。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
表格需求
一般管理系统对表格会有以下需求
可以分页(需要有分页条)
可以多选(表格带复选框)
顶部需要加一些操作按钮(新增,删除等等)
表格每行行尾有操作按钮
表格行可以编辑
如下图为一个示例表格
如果我们直接使用element-ui提供的组件的话,那么开发一个这样的表格就需要使用到以下内容
需要使用表格的插槽功能,开发每一行的按钮
需要通过样式调整顶部按钮,表格,分页条的布局样式
需要监听分页的事件然后去刷新表格数据
顶部按钮或操作按钮如果需要获取表格数据,需要调用表格提供的api
对于有行编辑的需求,还需要通过插槽去渲染行编辑的内容,同时要控制行编辑的开关
不仅仅开发表格比较麻烦,而且还要考虑团队协作,如果每个人实现表格的方式存在差别,那么可能后期的维护成本也会变得很高。那怎么办呢?
项目安装
安装插件
在使用element-ui的项目中,可以通过以下命令进行安装
npm install vue-elementui-table -S
在项目中使用
在main.js中添加以下代码
import ZjTable from 'vue-element-table'
Vue.use(ZjTable)
然后即可像下文中的使用方式进行使用
表格配置
为了满足团队快速开发的需要,小编对上面提出来的需求进行了封装,然后使用的时候,开发人员只需要配置一些JSON便可以完成以上功能的开发。
基础配置
一个基础的表格包含了数据和列信息,那么如何用封装的表格去配置呢?
<template>
<zj-table
:columns="columns"
:data="data"
:pagination="false"
/>
</template>
<script>
export default {
data() {
return {
// 表格的列信息, 数组每一项代表一个字段,可以使用element 列属性的所有属性,以下仅为示例
columns: Object.freeze([
{
// 表头显示的文字
label: '姓名',
// 对应数据里面的字段
prop: 'name'
},
{
label: '性别',
prop: 'sex',
// 格式化表格,与element-ui 的表格属性相同
formatter(row, column, cellValue) {
return cellValue === 1 ? '男' : '女'
}
},
{
label: '年龄',
prop: 'age'
}
]),
data: [
{
name: '子君',
sex: 1,
age: 18
}
]
}
}
}
</script>
通过上面的配置,就可以完成一个基础表格的开发,完整代码见 https://github.com/snowzijun/vue-element-table/blob/master/example/views/demo/base.vue,效果如下图所示
表格默认会显示复选框,也可以通过配置selectable属性来关闭掉
添加分页
简单的表格用封装之后的或未封装的开发工作量区别并不大,我们继续为表格添加上分页
<template>
<!--
current-page.sync 表示页码, 添加上 .sync 在页码发生变化时自动同步页码
page-size.sync 每页条数
total 总条数
height="auto" 配置height:auto, 表格高度会根据内容自动调整,如果不指定,表格将保持充满父容器,同时表头会固定,不跟随滚动条滚动
@page-change 无论pageSize currentPage 哪一个变化,都会触发这个事件
-->
<zj-table
v-loading="loading"
:columns="columns"
:data="data"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
:total="total"
height="auto"
@page-change="$_handlePageChange"
/>
</template>
<script>
export default {
data() {
return {
columns: Object.freeze([
// 列字段与上例一样,此处省略
]),
data: [],
// 当前页码
currentPage: 1,
// 每页条数
pageSize: 10,
// 总条数
total: 0,
// 是否显示loading
loading: false
}
},
created() {
this.loadData()
},
methods: {
// 加载表格数据
loadData() {
this.loading = true
setTimeout(() => {
// 假设总条数是40条
this.total = 40
const { currentPage, pageSize } = this
// 模拟数据请求获取数据
this.data = new Array(pageSize).fill({}).map((item, index) => {
return {
name: `子君${currentPage + (index + 1) * 10}`,
sex: Math.random() > 0.5 ? 1 : 0,
age: Math.floor(Math.random() * 100)
}
})
this.loading = false
}, 1000)
},
$_handlePageChange() {
// 因为上面设置属性指定了.sync,所以这两个属性会自动变化
console.log(this.pageSize, this.currentPage)
// 分页发生变化,重新请求数据
this.loadData()
}
}
}
</script>
完整代码请参考 https://github.com/snowzijun/vue-element-table/blob/master/example/views/demo/pagination.vue
通过封装,表格将自带分页功能,通过上面代码,实现效果如下所示,是不是变得简单了一些。接下来我们继续给表格添加按钮
添加顶部按钮
表格上面可能会有新增,删除等等按钮,怎么办呢,接下来我们继续通过配置去添加按钮
<template>
<zj-table
:buttons="buttons"
/>
</template>
<script>
export default {
data() {
return {
buttons: Object.freeze([
{
// id 必须有而且是在当前按钮数组里面是唯一的
id: 'add',
text: '新增',
type: 'primary',
icon: 'el-icon-circle-plus',
click: this.$_handleAdd
},
{
id: 'delete',
text: '删除',
// rows 是表格选中的行,如果没有选中行,则禁用删除按钮, disabled可以是一个boolean值或者函数
disabled: rows => !rows.length,
click: this.$_handleRemove
},
{
id: 'auth',
text: '这个按钮根据权限显示',
// 可以通过返回 true/false来控制按钮是否显示
before: (/** rows */) => {
return true
}
},
// 可以配置下拉按钮哦
{
id: 'dropdown',
text: '下拉按钮',
children: [
{
id: 'moveUp',
text: '上移',
icon: 'el-icon-arrow-up',
click: () => {
console.log('上移')
}
},
{
id: 'moveDown',
text: '下移',
icon: 'el-icon-arrow-down',
disabled: rows => !rows.length,
click: () => {
console.log('下移')
}
}
]
}
])
}
},
created() {},
methods: {
// 新增
$_handleAdd() {
this.$alert('点击了新增按钮')
},
// 顶部按钮会自动将表格所选的行传出来
$_handleRemove(rows) {
const ids = rows.map(({ id }) => id)
this.$alert(`要删除的行id为${ids.join(',')}`)
},
// 关注作者公众号
$_handleFollowAuthor() {}
}
}
</script>
表格顶部可以添加普通的按钮,也可以添加下拉按钮,同时还可以通过before来配置按钮是否显示,disabled来配置按钮是否禁用,上面完整代码见 https://github.com/snowzijun/vue-element-table/blob/master/example/views/demo/button.vue
通过上面的代码就可以配置出下面的表格,是不是很简单呢?
表格顶部可以有按钮,行尾也是可以添加按钮的,一起来看看
行操作按钮
一般我们会将一些单行操作的按钮放在行尾,比如编辑,下载等按钮,那如何给行尾配置按钮呢?
<template>
<zj-table
:columns="columns"
/>
</template>
<script>
export default {
data() {
return {
columns: Object.freeze([
{
// 可以指定列的宽度,与element-ui原生用法一致
width: 220,
label: '姓名',
prop: 'name'
},
// 行编辑按钮,在表格末尾出现,自动锁定右侧
{
width: 180,
label: '操作',
// 通过 actions 指定行尾按钮
actions: [
{
id: 'follow',
text: '关注作者',
click: this.$_handleFollowAuthor
},
{
id: 'edit',
text: '编辑',
// 可以通过before控制按钮是否显示,比如下面年龄四十岁的才会显示编辑按钮
before(row) {
return row.age < 40
},
click: this.$_handleEdit
},
{
id: 'delete',
text: '删除',
icon: 'el-icon-delete',
disabled(row) {
return row.sex === 0
},
// 为了拿到this,这里需要用箭头函数
click: () => {
this.$alert('女生被禁止删除了')
}
}
]
}
])
}
},
methods: {
// 关注作者公众号
$_handleFollowAuthor() {
console.log('微信搜索【前端有的玩】,这是对小编最大的支持')
},
/**
* row 这一行的数据
*/
$_handleEdit(row, column) {
this.$alert(`点击了姓名为【${row.name}】的行上的按钮`)
}
}
}
</script>
行操作按钮会被冻结到表格最右侧,不会跟随滚动条滚动而滚动,上面完整代码见, https://github.com/snowzijun/vue-element-table/blob/master/example/views/demo/button.vue
通过上面的代码就可以完成以下效果
最后再来一起看看行编辑
行编辑
比如上例,我希望点击行尾的编辑按钮的时候,可以直接在行上面编辑用户的姓名与性别,如何配置呢?
<template>
<zj-table
ref="table"
:columns="columns"
:data="data"
/>
</template>
<script>
export default {
data() {
return {
columns: Object.freeze([
{
label: '姓名',
prop: 'name',
editable: true,
field: {
componentType: 'input',
rules: [
{
required: true,
message: '请输入姓名'
}
]
}
},
{
label: '性别',
prop: 'sex',
// 格式化表格,与element-ui 的表格属性相同
formatter(row, column, cellValue) {
return cellValue === '1' ? '男' : '女'
},
editable: true,
field: {
componentType: 'select',
options: [
{
label: '男',
value: '1'
},
{
label: '女',
value: '0'
}
]
}
},
{
label: '年龄',
prop: 'age',
editable: true,
field: {
componentType: 'number'
}
},
{
label: '操作',
actions: [
{
id: 'edit',
text: '编辑',
// 如果当前行启用了编辑,则不显示编辑按钮
before: row => {
return !this.editIds.includes(row.id)
},
click: this.$_handleEdit
},
{
id: 'save',
text: '保存',
// 如果当前行启用了编辑,则显示保存按钮
before: row => {
return this.editIds.includes(row.id)
},
click: this.$_handleSave
}
]
}
]),
data: [
{
// 行编辑必须指定rowKey字段,默认是id,如果修改为其他字段,需要给表格指定row-key="字段名"
id: '0',
name: '子君',
sex: '1',
age: 18
},
{
// 行编辑必须指定rowKey字段,默认是id,如果修改为其他字段,需要给表格指定row-key="字段名"
id: '1',
name: '子君1',
sex: '0',
age: 18
}
],
editIds: []
}
},
methods: {
$_handleEdit(row) {
// 通过调用 startEditRow 可以开启行编辑
this.$refs.table.startEditRow(row.id)
// 记录开启了行编辑的id
this.editIds.push(row.id)
},
$_handleSave(row) {
// 点击保存的时候,通过endEditRow 结束行编辑
this.$refs.table.endEditRow(row.id, (valid, result, oldRow) => {
// 如果有表单验证,则valid会返回是否验证成功
if (valid) {
console.log('修改之后的数据', result)
console.log('原始数据', oldRow)
const index = this.editIds.findIndex(item => item === row.id)
this.editIds.splice(index, 1)
} else {
// 如果校验失败,则返回校验的第一个输入框的异常信息
console.log(result)
this.$message.error(result.message)
}
})
}
}
}
</script>
不需要使用插槽就可以完成行编辑,是不是很开心。上述完整代码见 https://github.com/snowzijun/vue-element-table/blob/master/example/views/demo/row-edit.vue
效果如下图所示:
其他功能
除了上面的功能之外,表格还可以配置其他许多功能,比如
可以指定字段为链接列,需要给列配置link属性
可以通过插槽自定义顶部按钮,行操作按钮,行字段等
可以在按钮区域右侧通过插槽配置其他内容
其他等等
表格开发说明
通过上面的代码示例,我们已经知道了封装之后的表格可以完成哪些事情,接下来一起来看看表格是如何实现的。完整代码见 https://github.com/snowzijun/vue-element-table/tree/master/src/components/zj-table
表格布局
整个表格是通过JSX来封装的,因为JSX使用起来更加灵活。对于我们封装的表格,我们从竖向可以分为三部分,分别是顶部按钮区,中间表格区,底部分页区,如何去实现三个区域的布局呢,核心代码如下
render(h) {
// 按钮区域
const toolbar = this.$_renderToolbar(h)
// 表格区域
const table = this.$_renderTable(h)
// 分页区域
const page = this.$_renderPage(h)
return (
<div class="zj-table" style={{ height: this.tableContainerHeight }}>
{toolbar}
{table}
{page}
</div>
)
}
通过三个render函数分别渲染对应区域,然后将三个区域组合在一起。
渲染表格列
通过前文的讲解,我们可以将表格的列分为以下几种
常规列
行编辑列
操作按钮列
插槽列
链接列(文档后续完善)
嵌套列(文档后续完善)
$_renderColumns(h, columns) {
// 整体是否排序
let sortable = this.sortable ? 'custom' : false
return columns
.filter(column => {
const { hidden } = column
if (hidden !== undefined) {
if (typeof hidden === 'function') {
return hidden({
columns,
column
})
}
return hidden
}
return true
})
.map(column => {
const {
useSlot = false,
// 如果存在操作按钮,则actions为非空数组
actions = [],
// 是否可编辑列, 对于可编辑列需要动态启用编辑
editable = false,
// 是否有嵌套列
nests,
// 是否可点击
link = false
} = column
let newSortable = sortable
if (column.sortable !== undefined) {
newSortable = column.sortable ? 'custom' : false
}
column = {
...column,
sortable: newSortable
}
if (nests && nests.length) {
// 使用嵌套列
return this.$_renderNestColumn(h, column)
} else if (editable) {
// 使用编辑列
return this.$_renderEditColumn(h, column)
} else if (useSlot) {
// 使用插槽列
return this.$_renderSlotColumn(h, column)
} else if (actions && actions.length > 0) {
// 使用操作列
column.sortable = false
return this.$_renderActionColumn(h, column)
} else if (link) {
// 使用链接列
return this.$_renderLinkColumn(h, column)
} else {
// 使用默认列
return this.$_renderDefaultColumn(h, column)
}
})
},
行编辑列
当前表格行编辑支持input,select,datepicker,TimeSelect,InputNumber等组件,具体渲染代码如下所示
// 编辑单元格
$_renderEditCell(h, field) {
const components = {
input: Input,
select: ZjSelect,
date: DatePicker,
time: TimeSelect,
number: InputNumber
}
const componentType = field.componentType
const component = components[componentType]
if (component) {
return this.$_renderField(h, field, component)
} else if (componentType === 'custom') {
// 如果自定义,可以通过component指定组件
return this.$_renderField(h, field, field.component)
}
return this.$_renderField(h, field, Input)
},
$_renderField(h, field, Component) {
// 编辑行的id字段
const { rowId, events = {}, nativeEvents = {} } = field
const getEvents = events => {
const newEvents = {}
Object.keys(events).forEach(key => {
const event = events[key]
newEvents[key] = (...rest) => {
const args = [
...rest,
{
rowId,
row: this.editRowsData[rowId],
value: this.editRowsData[rowId][field.prop]
}
]
return event(...args)
}
})
return newEvents
}
// 事件改写
const newEvents = getEvents(events)
const newNativeEvents = getEvents(nativeEvents)
return (
<Component
size="small"
on={newEvents}
nativeOn={newNativeEvents}
v-model={this.editRowsData[rowId][field.prop]}
{...{
attrs: field,
props: field
}}
/>
)
}
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
配色,设计师的世纪难题。从平面到屏幕,CMYK 到 RGB,墨点到像素,色彩越来越丰富,形式越来越复杂。UI 的发展从拟物的繁琐细节中挣脱出来,却在色彩的展现中放飞了自我。
零售业有个有趣的研究成果 —— 「七秒钟定律」:人们在挑选商品和服务时 ,只需要 7 秒钟就可以确定是否感兴趣,而在这短暂的 7 秒钟内,色彩的作用占到了 67%。
要在小小的手机屏幕中加入这么多颜色,并保持其中的联系和逻辑,着实不易。如果你还对配色一无所知,完全不知道配色应该怎么入手,那么你需要了解一下,我几年经验总结的配色思路。
无论我们用 PS、AI,还是 Sketch、XD、Figma,和色彩打交道最多的地方就是拾色器窗口,我们来看看这些案例:
虽然是不同的应用,但是这个拾色器的用法大同小异,但是,很多新人并没有搞懂拾色器的正确应用逻辑。
很多人知道,UI 的色彩使用 RGB 模式,但是拾色器主要的选色原理遵循的是 HSB 模式的逻辑,也就是色相(H)、饱和度(S)、明度(B)。
HSB 是色彩科学中对所有颜色属性的理论划分,是种概念上的定义,可以用来解释任何色彩,也就是说可以和 RGB 和 CMYK 相互转化,且 HSB 的选色逻辑更清晰、简洁、干练。
因为一个正确的选色过程,是先确定出色相,然后再在这个色相维度下选出明度和饱和度,所以我们首先要关注色相选择条。
细心的同学应该已经发现了,它们的首尾都是红色,那是因为色相的序列是一个首尾相接的环形模式,所以它实际上就是色环的柱状展示图,应用起来和色环没有实际区别。
接下来就要说到重点,饱和度和明度选择区,我自己使用的习惯,是将这个选择区通过黄金三分法的方式切割成等比的 9 个区域,然后明确它们在 UI 中的对应情绪和应用场景。
在过去的大量分析中,互联网产品的主色和重要辅助色都会往右上角聚集,一些次要、不可点的色彩聚集在中上方,而文字背景色则聚集在左侧,无人区则是我们重点避开的对象。
下面我们分析几个案例,看看它们在这个选择区中的色彩分布情况:
大家也可以自己拿一些主流的应用做截图,然后把它们的 UI 元素色彩排列到拾色面板中,就会得到基本一致的结果。牢记这9个区域的场景划分,可以帮助我们非常、安全地完成 UI 配色。
在众多的 UI 设计规范中,色彩部分的介绍,都必然包含三种类型,分别是:
1. 主色的选择
主色是一个应用的最核心的色彩,品牌的象征色,比如想到饿了么的蓝色、微信的绿色、京东的红色、淘宝的橙色。
确定主色,并没有大家想象的那么复杂,它的要点在于——你想让用户感受到哪种情绪,然后通过情绪关联一个大致的色彩范围,再进行微调。
在今天的互联网产品中,主色的应用选择范围在拾色器区域的右上角,前面已经有解释了。这和平面设计中的用色有非常大的不同。
移动端产品要在一个方寸大的空间中争夺用户的注意力,引起用户的兴趣,那么低饱和清淡的色调是无法实现这个目标的,所以今天主色饱和度越来越,比如我们之前整理的一篇总结:
为什么支付宝要换 Logo 颜色?分析下目前 Logo 的主色趋势
再加上屏幕的 RGB 显示特性,高对比度,高动态范围的特质能给用户提供更好的观感。所以选择主色最安全的做法,就是在确定色相类型后,在右上方区域选出合适的色值。
2. 辅助色的选择
辅助色是丰富应用中的次要色彩,它会包含一到若干个和主色不同的色彩,除了品牌传达外,具有更强的实用性。
前面我们提到过色环,这里就要派上用场了。我们知道色环是个色彩序列首尾相连的环形模型,它蕴含一个最朴素的原则,即两个颜色在这个环形中角度越大,那么视觉差异性越大,对比越强,比如下图的展示:
这些配色的模式是不能闭着眼随便挑的,它们仅仅作为一个色彩对比度的判断标准。而真正辅助色的选择,是根据实际场景的功能决定的。
比如通知、提醒、取消用大红色,确认、同意用绿色或者蓝色,收藏、打分、评价用橙黄色。都是已经在用户心智中建立了标准的用色类型,跟着常规方法来做,是没有其它思路的情况下最简单、最安全的辅助色选择方式。
没有标准元素用色的情况下,再考虑应用色环的 「角度原则」,越需要被突出的颜色,可以在色环中离主色越远,越不需要被突出的则越近。
比如下方携程的案例,主色在蓝色的情况下,支付、保险金标签这些需要被重点突出的色彩,使用了主色的互补色, 让我们一眼就能看见并产生强烈的操作欲望。
3. 中性色的选择
中性色,是页面中文字、背景用到的颜色,它们承担起最基本的层次表现、便于阅读的重任。多数新手觉得中性色无关紧要,实际情况恰恰相反。
主色辅助色决定了界面视觉是否出彩,而中性色的应用直接决定了页面能不能正常使用。如果看过比较多的原型案例,就应该明白,即使只有黑白灰的状态下,我们理解这些页面和进行使用也不会有丝毫的障碍。
中性色的配置,就是制定一个由深到浅的灰度阶梯,应用在对应权重的元素上,色彩轻重的主要判断依据是 HSB 中的 B(明度) 值。
中性色虽然指的是无个性,但并不是只能用纯灰色,常见的一种做法,就是为中性色添加适量的蓝色饱和度,提升观看体验(满足RGB的某种特性)。
这种做法,颜色越浅的时候饱和度应用色值就越低,将这个规律在拾色器中进行表现,那么我们就可以得到一个 L 型曲线,我称它为 「中性曲线」。
掌握对于主色、辅助色、中性色的选择方法,那么对于UI配色的奥义来说,你已经掌握了一半,接下来就要了解更具体的实践思路了。
配色并不是只有色彩的色值本身,大家一直在研究各种色彩心理学和理论,却很少关心它们如何应用,如何配置。
所以,我根据主色和辅助色应用总结了一个配色的四象限表格,再分别看看它们对应的案例:
1. 主色占比大,色彩丰富度高
主色会作为顶部标题栏或其它重要模块中的背景色,进行大面积应用,加深用户对品牌的认知和辨识度。而产品中又包含了大量功能和服务,需要用丰富的色彩来进行暗示,吸引用户关注。
2. 主色占比大,色彩丰富度低
这类配色中,主色的应用占比也大,出现频率高,鲜有其它颜色出现。比较适用于图片内容丰富的题材中,或者是相对正式、品牌感强的应用。
3. 主色占比小,色彩丰富度高
这是多数主流应用的趋势,降低主色占比,留出更多的空间给内容模块的展示上,突出自身带有的服务和功能。
4. 主色占比小,色彩丰富度低
通常,会应用这种方式是因为产品的服务是相对单一,但也需要用户投入注意力的应用,设计师就会尽力避免给予用户过多的干扰。
每次在进行配色的时候,我们都需要对自己要应用哪种配色应用方式做出规划,然后再动手执行。有了这个目标,后面在整个项目的设计中的配色步骤就是水到渠成的事情了。
在实践前,我们要简单讲讲一个应用或者界面的标准配色的流程了,流程顺序如下:
具体应该怎么使用这套流程,我们用一个图虫APP改版的案例来做演示,首先从四象限中的第一个主色占比高、色彩丰富度高的类型做起。
1. 配色流程演示
原型是 UI 设计的基本艺能了,在开始具体设计、配色前,搭建页面的框架原型是一个必备的条件,下面,是我们已经准备好的原型案例。
然后,我们确定以橙色作为应用主色,并在拾色器中进行确认。
有了主色,就可以对页面进行色彩填充和图片填充了。既然我们主色是占比大的,那么首先可以用到的就是顶部标题栏的背景色了,以及底部 Tabbar 中的选中色,大按钮色等。
接着,我们开始整理中性色的使用,选择新的颜色来填充文字和背景,清晰的表现模块层级,文字信息的权重。
最后,就是添加辅助色和其它色彩的元素了,这个步骤建议都是放在最后一步操作。因为色彩越丰富,越难控制,容易让整个画面显得杂乱无序,所以先完成基础搭建,可以更好的帮助我们判断彩色的使用是否合理。
下面,我们使用彩色的金刚区图标,然后将用户关注、认证用户、标签等元素使用其它色彩,来丰富页面的色彩内容。
2. 其他配色类型应用
根据第一个方案,我们可以再用这个原型来实现其余的三个方案的配色。
比如下面的主色占比大,但是色彩丰富度低的。因为已经不太适用其它辅助色,所以主色填充上我们不再填充顶部导航栏的背景,而是将更多元素应用主色,减少辅助色数量。
然后是主色占比小,色彩丰富度高的方案,进一步降低主色应用的比例,然后在金刚区、标签等处使用较为丰富的配色。
最后,就是主色占比小,色彩丰富性也低的方案,那么使用中性色的元素就开始增多,只保留最核心的一些元素使用主色,和极少的辅助色。
根据四种不同的配色方案,我们就可以得到四种不同的配色结果和风格,在每次设计开始实施前,我们都可以根据这种做法来做尝试,并选出自己满意的方案。
要再次强调,UI 配色是极其强调形式的应用科学,最后做的往往会和一开始想的效果有极大出入,所以需要我们有几个备选方案,可以随时进行调整,并选出合理的那个。
以上是我们关于配色有关知识点的分享,希望可以帮助大家提升对 UI 配色的认识。
文章来源:优设 作者:超人的电话亭
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
蓝蓝设计的小编 http://www.lanlanwork.com