前端工作中的用户体验
前端开发的工作中,很多设计稿、产品原型图都是静态的,以界面和描述功能为主。前端同学作为最贴近用户的开发,用户交互体验需要我们去关注和改善,不然就真的没有人管了。UX 对交互的实现,目前在国内还是不够重视。一份极致的设计稿,还会伴随过渡动画、响应式设计甚至无障碍等等。当原型图和设计稿缺失这些元素时,补充它们的职责就落在了咱们前端开发的同学身上了
看看流行 UI 框架中的用户体验实践:
这里我们以 Ant-Design、Material-UI 两大当下最流行的 UI 框架为例。它们不仅有技术方案能够直接使用,还提供了一套设计规范及资源,同时支持个性化主题。强大的功能、优雅的设计、良好的交互体验使它们在这几年使用量突飞猛进、经久不衰。
先看一个基础的组件:主要按钮Button type="primary" ,两个库的交互动画都分成三块,鼠标浮上 -> 鼠标点下 -> 鼠标松开。
别小看这三段动画,尤其是 鼠标点下 -> 鼠标松开,通常写一个简单点击的动画是比较快的,例如:
@keyframes clicked {
0% {
background-color: rgba(22, 119, 255, .8);
}
50% {
background-color: rgb(2, 64, 140);
}
100% {
background-color: rgba(22, 119, 255, .8);
}
}
但是 AntD 和 MUI 都做成了根据鼠标点下的时间控制动画进度,并且加上了额外的效果。AntD 是鼠标浮上颜色变浅、点下时颜色变深、松开回到浅色,并且按钮周围有边框散开的动画:
MUI 是鼠标浮上颜色和阴影变深,点击时在点击的地方有浅色放大的圆圈动画同时阴影变深,松开时颜色逐渐恢复。
Material-UI Button TouchRipple 动画源码赏析:
// 圆圈扩散时间
const DURATION = 550;
// 圆圈扩散延迟
export const DELAY_RIPPLE = 80;
// 鼠标点下时(圆圈进场) 控制圆圈从无到有 和透明度
const enterKeyframe = keyframes`
0% {
transform: scale(0);
opacity: 0.1;
}
100% {
transform: scale(1);
opacity: 0.3;
}
`;
// 鼠标松开时(圆圈离场) 控制圆圈透明度 慢慢消失
const exitKeyframe = keyframes`
0% {
opacity: 1;
}
100% {
opacity: 0;
}
`;
// 鼠标按住时,小动一下
const pulsateKeyframe = keyframes`
0% {
transform: scale(1);
}
50% {
transform: scale(0.92);
}
100% {
transform: scale(1);
}
`;
// 初始样式,不点的时候是不出现的
export const TouchRippleRoot = styled('span', {
name: 'MuiTouchRipple',
slot: 'Root',
})({
overflow: 'hidden',
pointerEvents: 'none',
position: 'absolute',
zIndex: 0,
top: 0,
right: 0,
bottom: 0,
left: 0,
borderRadius: 'inherit',
});
// This `styled()` function invokes keyframes. `styled-components` only supports keyframes
// in string templates. Do not convert these styles in JS object as it will break.
// 把动画加到对应动画阶段的 class 上、设置默认样式和时间等
export const TouchRippleRipple = styled(Ripple, {
name: 'MuiTouchRipple',
slot: 'Ripple',
})`
opacity: 0;
position: absolute;
&.${touchRippleClasses.rippleVisible} {
opacity: 0.3;
transform: scale(1);
animation-name: ${enterKeyframe};
animation-duration: ${DURATION}ms;
animation-timing-function: ${({ theme }) => theme.transitions.easing.easeInOut};
}
&.${touchRippleClasses.ripplePulsate} {
animation-duration: ${({ theme }) => theme.transitions.duration.shorter}ms;
}
& .${touchRippleClasses.child} {
opacity: 1;
display: block;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: currentColor;
}
& .${touchRippleClasses.childLeaving} {
opacity: 0;
animation-name: ${exitKeyframe};
animation-duration: ${DURATION}ms;
animation-timing-function: ${({ theme }) => theme.transitions.easing.easeInOut};
}
& .${touchRippleClasses.childPulsate} {
position: absolute;
/* @noflip */
left: 0px;
top: 0;
animation-name: ${pulsateKeyframe};
animation-duration: 2500ms;
animation-timing-function: ${({ theme }) => theme.transitions.easing.easeInOut};
animation-iteration-count: infinite;
animation-delay: 200ms;
}
`;
藏在功能下的交互细节
以上按钮的例子,不知道大家有没有感受到一点震撼,想说的是一款优秀的组件库,不仅仅能够实现功能需求,还在设计与体验上花了很大的心思。只有见识了足够多的使用场景,再与标准的设计规范相融合,才能写出操作反馈良好、扩展性强的组件。
良好的交互设计不仅能提高操作效率、用户的使用感受,还具有引导用户使用的能力。乔布斯发布iphone时,用了两个经典手势让我记忆犹新,一个是左右滑动控制界面前进后退,一个是两根手指在屏幕上放大缩小图片。这个手势大家马上就能记住,因为它是合理的、自然的、在生活中有相似行为的。这么多年来早已成为大家使用智能手机时潜移默化的操作了。
同样的,在 AntD 和 MUI 中也存在着一些培养用户操作习惯的交互设计。例如图片上传、表格的操作控件、日期选择等等,因为系统内通常是统一的风格,用户适应了组件后能够在所有场景下高效的使用。
用户的使用效率
纵然交互细节可以很好的提高使用美感,但是B端用户还是更关注使用效率。这里举一个使用效率的例子:
我认为,AntD 的 DatePicker 交互上还是有一些改进空间的
首先是输入,当用户输入 2023-01-01 时,日期选择器确实会跳到对应的日期,但是如果你不点击或者按回车的话,是不会选中当前的日期的。在你离开输入框焦点后,你输入的日期会消失。我认为输入合法的日期,应该当做已选中该日期以提高操作次数。
其次是要想快速的选择年和月,是可以点击日期弹窗中的年、月来进入年月选择列表的。但是这里缺少可交互的提示,用户不是开发,我们不能认为所有的用户在看到界面时都知道这边能够操作。
这里似乎是在挑刺,其实交互模式也是仁者见仁、智者见智,没有标准答案。或许我来做这个组件,会改变上述这些行为。为了验证这个思考是否合理,我又参考了 MUI Date picker 它的年份边上是有一个小箭头,告诉用户这里可以操作,并且它输入日期就能生效。
组件的演变方向
还是 DatePicker ,借官方的图看看组件演变生长的方向,即:从满足需求的 MVP 版本,到拓展功能变体,到为了不同领域和场景提供特色解决方案
产品的可用性
这个话题会偏向产品经理的范畴,但是咱们开发同学也需要对此有感知,有时能够提出优化建议、避免一些不合理的设计。
产品的可用性在C端应用中主要可以通过运营数据来考量,例如建立用户行为监控的漏斗模型,从首页到详情页到下单 每一步的转化率。站在用户的角度思考,是否能引起用户下单的兴趣、界面是否一目了然。
在一些功能型管理后台中,可用性更多体现在业务效能和信息表达严谨;有没有贴心的快捷操作;表单填写限制、校验提示、错误提示是否友好等等。对于业务效能的考量计算可以参考下图:
产品经理应该以用户的使用角度,对页面的展示重点、交互、使用流程做最后的确认,旨在使系统使用起来舒适又高效。其中有几条定律可以参考:
- 费茨法则
指用户达成目的需要花费的时间,在交互设计中,应该把主要、重要的功能放置在显眼,易触达的位置,提高用户的操作效率
例如移动端的主要按钮通常放在底部,靠近大拇指
- 席克法则
让复杂的东西变简单,可以通过结构化、层次化复杂的功能模块,将它们梳理得更可用更可读。
将应用分为几个主Tab;将设置分为多层级的树状操作
- 泰思勒定律
即复杂性守恒定律,每个功能模块都有一定的复杂性。在无法继续优化的时候,应该选择隐藏用户不需要感知的细节,以步骤的形式,让用户专注于当下的操作。
将一个复杂的操作步骤分解为多步骤,例如分步注册、分步填写资料
从上文可以看出,用户体验好的产品可以有以下优点:
- 操作反馈良好;
- 流程高效、提示明确;
- 跳出开发思维,不让用户困惑;
开发体验
开发体验是上文没提到的新词,意思是面向开发人员产品的用户体验。开发体验是我们选择技术栈时着重考虑的。
我们观察前端中流行的技术栈,无一不是有良好开发体验的,开发人员用脚投票,用起来爽,就口口相传。例如 JQuery、Webpack、AntD、React、Vue
怎样提高自己项目的开发体验
- 提高代码质量
- 可读性:以代码的自描述为主,注释为辅(例如 TS 更清晰的描述了变量类型,方法的入参和出参)
- 健壮性:良好的异常处理
- 可维护性:合理的项目结构;组件高内聚、低耦合,方便复用
- 做好文档
- 业务梳理,记录下常维护的功能模块
- 沉淀领域模型
- 为组件制作 playground
结语
如果说应用是一条路,技术就是在铺路,那么体验良好的应用就是一条宽阔平坦、风景优美的路。或许它不是必要的,但是作为开发和用户,能在行路时欣赏风景,也不失为一种乐趣