移动端的「基金地图」是怎么做的?

简介: 移动端的「基金地图」是怎么做的?

🙋🏻‍♀️ 编者按:本文作者是蚂蚁集团前端工程师芒僧,今年 8 月份开始到 9 月底,「支付宝 - 基金」里面的指数专区进行了一波大改版升级,这次借助 F2 4.0 强大的移动端手势交互能力,我们尝试了一种多维度探索式选基决策工具,本文具体介绍了它是如何实现的。

这次在 「支付宝 - 基金」里的【指数专区改版】需求,我们玩了一种很新的东西 🌝

8 月份开始到 9 月底,「支付宝 - 基金」里面的指数专区进行了一波大改版升级,这次借助 F2 4.0 强大的移动端手势交互能力,我们尝试了一种多维度探索式选基决策工具(如上动图所示)。

简单来说,用户可以在一个散点图上根据「收益」和「波动」这两个维度全览对比整个市场里的指数基金,并选出适合自己的指数基金进行投资,这个功能我们愿称其为「指数图谱」🐶 。

图谱是这个业务场景上的叫法,实际上图谱应该是关系图而非统计图.

功能已发布,页面访问路线如上

  先看看有哪些功能点

  1. 精细打磨的移动端手势交互,平移、缩放、横扫不在话下 :
  2. 依次为:缩放、平移、横扫

  1. 底部产品卡和图表的联动交互:

   

依次为:点击图表上的气泡、滑动底部卡片

  1. 无惧数据点太多看不到细节,我们有自适应的气泡抽样展示和自动聚焦:

依次为:抽样优化前、抽样优化后

  那么,怎么做的呢?

最开始看到这个需求的时候,当时觉得可行性比较低。因为需求里面针对图谱的方案以及细节都特别模糊;不敢承诺各种功能和排期,所以先做了一轮比较完整的系分,增加一些说话的底气 🫣

📱 第一步:同类产品调研

因为设计同学的灵感来自于 大众点评 APP 上面的「美食地图」,所以第一步就是做了一次「同类产品调研」,仔细去看了一下 「美食地图」上究竟有哪些花样,有哪些体验优化的小细节,不看不知道,一看发现细节原来这么多啊 🤕:

图表和卡片的交互联动 点抽样展示 列表视图和卡片视图可切换 交互时卡片自动折叠 散点懒加载 上滑直接唤起详情页

做完这一步之后,大概能够知道自己距离“成品”有多远的距离,方便自己评估工期;另外还可以在系分评审的时候把这些细节提出来,防止临近发布了突然发现某个交互逻辑有个致命的漏洞(别问我怎么知道的,要命的)。这波调研之后,最终我们在实现上致敬了「美食地图」50% 的体验细节优化 (狗头)。

⚙️ 第二步:功能点分析

第二步就是从需求本身的角度做功能点的分析,这样可以方便我们拆分组件,为后续做分层设计打下基础,明白哪些是需要支持可扩展的。这一步大家都熟悉,就不赘述了:

📦 第三步:通用化设计

有了功能点的分析之后,就可以进行通用化的设计了,这就来到了喜闻乐见的沉淀组件的设计环节 🌝

我们希望这个功能不仅仅是纯业务代码,期望下次能够复用大部分核心功能 (理想很丰满),所以在系分的时候是往通用化的方向去设计的,这里主要做了三件事情:分层设计概念标准化核心流程定义

  1. 分层设计

拆的逻辑是按最基础的 M(数据层) - C(控制层) - V(视图层) 拆分的。

有了分层设计和功能点分析之后,就可以知道哪些应该放到组件内,哪些接口应该被抽象成通用接口,哪些应该保留扩展性供使用者自己来定义,就可以画个表格了,一一决定哪些模块应该放到组件内:

  1. 概念标准化

下面来到造词环节,把一些常用的概念都定义成一个个名字,这样方便和后端、设计协同的时候效率更高,同时也方便自己定义清楚各个模型(类)。(这里其实取名越贴切越形象越好,有点考验语言能力了属实是)

  1. 核心流程定义

这一步是脑补环节,在脑子里跑一遍整体的流程,也是整个需求最核心的流程,比如这里会分成四种流程:初始化流程 、散点图交互流程、底部卡片交互流程、顶部tab交互流程

进而可以将四种流程里面的各节点做一些归类,比如都会有图表渲染、数据补全、卡片渲染这些共同的节点,而这些节点就可以实现成具体模型里的具体方法。

🌝 第四步:难点分析

根据上面拆分的各模块,列出哪些点是实现有困难的,耗时长的。这样就可以在评估工期的时候多 Battle 一下,还能砍砍需求,更可以让底层引擎/SDK来突破这些难点(比如找 F2 的核心开发者)

:

📃 最后一步:

按照上述的设计进行代码编写。

  难点实现

1. 移动端的图表手势交互体验优化

开发之初,F2 只支持单轴(x或者y)的平移缩放,也不支持全方向交互;在 swipe 上的体验也不太好(阻尼感很强),所以在项目开发过程中, F2 完成了很多体验优化,打磨出很多细致入微的良好体验:

  • X轴、Y轴可同时开启平移、缩放
  • swiper 体验效果优化
  • 移出可视区之后的蒙层遮挡能力(view-clip)
  • zIndex 元素层叠渲染
  • 平移缩放性能优化

2. 气泡抽样展示优化

因为散点图上的点在初始化的缩放比例下分布非常密集,所以如果每个点上面都绘制一个气泡的话,就会显得密密麻麻的,根本无从下手(如下图1所示)。针对这样的问题,做了「气泡抽样展示」的优化。


实现方式上就是渲染前遍历所有的点,如果在这个点周围某个半径距离之内有其他点,那么就认为这个点是脏点(dirty point),最后筛选出所有“干净”的点进行气泡展示。

如下图图1所示,灰色点(右上角)是干净点,而灰白色的点(偏中间的位置)因为其在圆圈半径范围之内有其他点存在,所以这个点是脏点。      

多提一句,这样的过滤方式会使得密集区域的点都不会展示气泡,后续会进行优化。

3. 获取到可视区内的所有点

由于做了气泡抽样展示,所以上图中的底部卡片只会展示用户可视区内散点图上有气泡的点(细心的盆友可以发现,散点图上有两种点,一种是带气泡的交互点,一种是不带气泡的缩略点)。那么就需要一个获取「可视区内所有的点」,实现思路如下:

- 监听 PanEnd(平移结束)、PinchEnd(缩放结束), SwipeEnd(横扫结束)的事件
 - 获取到平移/缩放/横扫之后最新的 scales
 - 根据最新的 scales 里面的 x、y 的 range 过滤一遍图表原数据
 - 将脏点从上一步的结果过滤出去
 - 底部卡片根据上一步的结果进行渲染展示
- 结束
// 根据当前的缩放比例,拿到「可视区」范围内的数据
function getRecordsByZoomScales(scales, data) {
  const { x: xScale, y: yScale } = scales;
  const { field: xField, min: xMin, max: xMax } = xScale;
  const { field: yField, min: yMin, max: yMax } = yScale;
  return data.filter((record) => {
    const isInView =
      record[xField] >= xMin &&
      record[xField] <= xMax &&
      record[yField] >= yMin &&
      record[yField] <= yMax;
    return isInView;
  });
}
// 使用时
export default props => {
  // 图表原数据
  const { data } = props;
  function handlePanEnd (scales, data) {
    // 手动高亮下面这一行
    getRecordsByZoomScales(scales, data);
  }
  return (
     <ReactCanvas>
       <Chart>
         {/* ... */}
         <ScrollBar onPanEnd={handlePanEnd}/>
       </Chart>
     </ReactCanvas>
  )
}

4. 数据懒加载

底部卡片的数量是由散点图上点的数量决定的,而每张卡上都有不少的数据量(基金产品信息、指数信息、标签信息),所以不能一次性就把所有点里关联的数据都查询出来(会导致接口返回数据过多)。

这里采取的是懒加载的方式 ,每次只在交互后查询相邻 N+2/N-2 张的卡片数据,并且增加了一份内存缓存来存储已经查询过的卡片数据:

基本的流程图如下:

- 触发散点图交互/滑动底部卡片
  - 读取缓存,过滤出没有缓存过的卡片
  - 发起数据调用,获取到卡片的数据
  - 写入缓存
  - 更新卡片数据,返回
- 更新卡片视图,渲染完成

  实际线上效果

项目上线之后,我们发现散点图区域的交互率(包含平移,缩放)非常高,可以看出用户对新类型的选基工具抱有新鲜感,也乐于去进行探索;也有部分用户能够通过工具完成决策或者进行产品之间的详细对比(即点击底部卡片上的详情按钮),起到了一个工具类产品的作用 🌝 。

  致谢

感谢 AntV 以及 F2 对移动端图表交互能力的支持。


相关文章
|
资源调度 前端开发 算法
前端依赖版本重写指南
感谢神奇的 Semver 动态规则,npm 社区经常会发生依赖包更新后引入破坏变更的情况(应用没有使用依赖锁的话),而应用开发者就要在自己的依赖声明里先临时绕过,避免安装到有问题的版本,如果是一级依赖,只需要改 package.json 的声明就可以了,但如果是子依赖,就需要进行版本重写(overrides/resolution)了。本文是一篇针对版本重写功能的指南性文章,当你遇到如下的问题时,就可以按照对应的依赖重写语法,解决这些依赖问题了。
8555 1
前端依赖版本重写指南
|
存储 SQL 数据库连接
MPPDB分布式结构化数据库
1.MPPDB简介 MPP,它是一款 Shared Nothing 架构的分布式并行数据库集群,具备高性能、高可用、高扩展特性,可以为超大规模数据管理提供高性价比的通用计算平台,并广泛地用于支撑各类数据仓库系统、BI 系统和决策支持系统。
7413 0
|
消息中间件 NoSQL Redis
Redis高可用之哨兵模式(第二部分)
Redis高可用之哨兵模式(第二部分)
|
6月前
|
人工智能 JSON 自然语言处理
构建AI智能体:三十一、AI医疗场景实践:医学知识精准问答+临床智能辅助决策CDSS
本文探讨了医疗AI从传统规则系统向大模型的演进,重点介绍了基于RAG技术的医学知识精准问答系统与临床智能辅助决策系统(CDSS)的构建原理与应用。二者协同工作,前者提供权威知识检索,后者结合患者数据生成个性化诊疗建议,共同提升医疗效率、安全与质量,助力医生实现更精准的临床决策。
822 2
|
5月前
|
数据采集 人工智能 搜索推荐
AI 问答占 52%!长沙别墅装修 GEO 突围:30 天引用率暴涨 40%
周有贵,巴黎学院人工智能博士,GGI商学院GEO首席技术专家,专注AI时代数字营销革新。2025年12月1日,长沙著名别墅设计师张主华专程拜访交流,共探GEO技术在装修设计行业中的AI引流逻辑与实操应用。面对生成式AI问答入口占比突破52%的新趋势,传统SEO正被GEO取代——从链接点击到答案呈现,企业需通过构建灯塔内容、E-E-A-T信任链与结构化数据,让品牌信息被AI优先引用。本次对话揭示:未来流量之争,本质是“被AI推荐”的能力之争。
|
安全 Linux 开发工具
【小白必看】GitKraken超详细图文安装教程(附官方下载链接)
GitKraken 是一款跨平台的 Git 客户端,提供直观界面简化版本控制。支持 Windows、Mac 和 Linux,适合个人与团队使用。本文详细介绍其下载、安装流程及配置方法,包括语言设置、Git 配置、多分支管理等功能,并解答常见问题,助你高效管理代码仓库。
WordPress小白傻瓜式一键搭建博客个人网站详细教程
用宝塔功能来一键搭建WordPress博客网站。 最详细教程! 整个过程简单、易用,即使是零基础用户也能轻松上手。
1155 1
|
Docker Python Windows
pycharm使用fastapi/uvicorn无法reload的问题
这篇文章讨论了在PyCharm中使用FastAPI和uvicorn时遇到的无法快速重载的问题,并提供了包括降级uvicorn版本和使用命令行运行等解决方法。
pycharm使用fastapi/uvicorn无法reload的问题
|
存储 机器学习/深度学习 算法
【博士每天一篇文献-算法】连续学习算法之RWalk:Riemannian Walk for Incremental Learning Understanding
RWalk算法是一种增量学习框架,通过结合EWC++和修改版的Path Integral算法,并采用不同的采样策略存储先前任务的代表性子集,以量化和平衡遗忘和固执,实现在学习新任务的同时保留旧任务的知识。
524 3
|
缓存 API Android开发
Kotlin 学习笔记(七)—— Flow 数据流学习实践指北(三)冷流转热流以及代码实例(下)
Kotlin 学习笔记(七)—— Flow 数据流学习实践指北(三)冷流转热流以及代码实例(下)
493 0