前端工作中的用户体验

280 阅读8分钟

前端工作中的用户体验

前端开发的工作中,很多设计稿、产品原型图都是静态的,以界面和描述功能为主。前端同学作为最贴近用户的开发,用户交互体验需要我们去关注和改善,不然就真的没有人管了。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 是鼠标浮上颜色变浅、点下时颜色变深、松开回到浅色,并且按钮周围有边框散开的动画:

image.png

MUI 是鼠标浮上颜色和阴影变深,点击时在点击的地方有浅色放大的圆圈动画同时阴影变深,松开时颜色逐渐恢复。

image.png

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 版本,到拓展功能变体,到为了不同领域和场景提供特色解决方案

微信图片_20230403091721.png

微信图片_20230403091703.png

产品的可用性

这个话题会偏向产品经理的范畴,但是咱们开发同学也需要对此有感知,有时能够提出优化建议、避免一些不合理的设计。

产品的可用性在C端应用中主要可以通过运营数据来考量,例如建立用户行为监控的漏斗模型,从首页到详情页到下单 每一步的转化率。站在用户的角度思考,是否能引起用户下单的兴趣、界面是否一目了然。

在一些功能型管理后台中,可用性更多体现在业务效能和信息表达严谨;有没有贴心的快捷操作;表单填写限制、校验提示、错误提示是否友好等等。对于业务效能的考量计算可以参考下图:

微信图片_20230403091547.png

产品经理应该以用户的使用角度,对页面的展示重点、交互、使用流程做最后的确认,旨在使系统使用起来舒适又高效。其中有几条定律可以参考:

  1. 费茨法则

指用户达成目的需要花费的时间,在交互设计中,应该把主要、重要的功能放置在显眼,易触达的位置,提高用户的操作效率

例如移动端的主要按钮通常放在底部,靠近大拇指

  1. 席克法则

让复杂的东西变简单,可以通过结构化、层次化复杂的功能模块,将它们梳理得更可用更可读。

将应用分为几个主Tab;将设置分为多层级的树状操作

  1. 泰思勒定律

即复杂性守恒定律,每个功能模块都有一定的复杂性。在无法继续优化的时候,应该选择隐藏用户不需要感知的细节,以步骤的形式,让用户专注于当下的操作。

将一个复杂的操作步骤分解为多步骤,例如分步注册、分步填写资料

从上文可以看出,用户体验好的产品可以有以下优点:

  1. 操作反馈良好;
  2. 流程高效、提示明确;
  3. 跳出开发思维,不让用户困惑;

开发体验

开发体验是上文没提到的新词,意思是面向开发人员产品的用户体验。开发体验是我们选择技术栈时着重考虑的。

我们观察前端中流行的技术栈,无一不是有良好开发体验的,开发人员用脚投票,用起来爽,就口口相传。例如 JQuery、Webpack、AntD、React、Vue

怎样提高自己项目的开发体验

  • 提高代码质量
    • 可读性:以代码的自描述为主,注释为辅(例如 TS 更清晰的描述了变量类型,方法的入参和出参)
    • 健壮性:良好的异常处理
    • 可维护性:合理的项目结构;组件高内聚、低耦合,方便复用
  • 做好文档
    • 业务梳理,记录下常维护的功能模块
    • 沉淀领域模型
    • 为组件制作 playground

结语

如果说应用是一条路,技术就是在铺路,那么体验良好的应用就是一条宽阔平坦、风景优美的路。或许它不是必要的,但是作为开发和用户,能在行路时欣赏风景,也不失为一种乐趣