查看原文
其他

假如给周杰伦演唱会设计选座功能,你会怎么设计?

阿里文娱技术 程序人生 2020-10-16
作者 | 阿里文娱高级前端工程师 弋辰
责编 | 胡巍巍
出品 | 程序人生(ID:coder_life) 
超大型场馆座位图的加载与渲染在行业内始终是个不小的挑战,很多团队在面对绘座选座 技术研发时,都难以支撑超大型场馆的座位图在浏览器端快速、稳定地渲染。如果你是奋斗在现场娱乐、剧院演出和电影院线相关行业内的一名开发者,那么文章将帮助你更多的了解大场馆座位图技术,同时可以帮助你扩展绘座选座核心功能开发的思路。

 
业务场景

麦座是一套完善的数字化运营系统,连接内容和场馆,提供票务生产、票务销售、现场管 理和演出运营等能力,绘座选座是麦座的核心能力之一,从建设场馆到规划票房再到门店销售。目前可支持的十万座位量级的场馆,包括剧院、演唱会、体育赛事等多个垂类。
本文将介绍麦座的绘座、票房规划、锁座和门店销售等场景是如何通过技术手段实现业务 需求的,以及超大型场馆的座位图是如何打破性能边界,给用户呈现出更流畅的交互体验。 
 
 

功能场景

麦座的座位图相关的业务可以分为“绘座”和“选座”两大功能场景。选座就是通过用户 事件绑定选中的座位进而完成接下来的业务逻辑,而绘座包括绘制座位、设置楼层、看台、舞 台、出口等信息,绘制座位同时又涉及到如何给块级座位进行变形处理。那么,绘制的座位是 如何填满看台区域的呢?又是如何将现场千变万化的座位排布展示出来的呢?下面我们带着疑 问来看看麦座的解决方案。

1. 绘座

Svg 导入、校验;
编辑场馆信息:可对舞台、楼层、看台、区域和场馆入口等进行设置;
添加座位:主要针对座位的物理属性进行设置,包含但不限于座位类型、所在区域、楼 层信息、排数、列数、排序规则;
块级座位变形:间距调整,可通过座位 x,y 轴的数值进行调整;
旋转:将所选座位集合设置成为一个临时块,将其作为矩形矩阵。向上取整,获取离矩 阵中心最近的座位,将其设做圆心,其他座位以圆心座位进行 rotate 旋转;
错位:根据角度进行奇偶排位移错位; 
倾斜:将所选座位集合设置成为一个临时块,将其作为矩形矩阵。第一排不改变位移, 从第二排开始,每一排根据上一排进行等比例位移;
弧形:
  • 应用贝塞尔曲线:贝塞尔曲线是用一系列点来控制曲线状态的,我将这些点简单分为 两类:数据点、控制点。通过调整控制点,贝塞尔曲线形状会发生变化;


中弧算法:二阶曲线: 
 
左/右弧算法:三阶曲线: 
2. 选座
票房规划:规划票档、保留票、套票和打印座位图;
锁票:根据业务场景可分为单场次锁票和跨场次锁票,跨场次锁票可支持在相同场馆的 不同场次内进行锁票;
门店销售:彩虹图、高级筛选、购物车和下单;
 

效率提升(按区域加载方案)

麦座的选座场景在两万以上座位量的大型体育赛事上,座位图页面加载缓慢、操作座位时出现卡顿等情况。
实现座位按区域加载,使用户在拖拽、缩放的同时惰性加载所需要展示区域内的座位,加 快首屏渲染时间,在用户无感知的情况下加载其余区域的座位。解决因数据量庞大引起的页面 加载缓慢、卡顿等体验问题。
技术实现(以规划票房场景为例):1)展示当前浏览器窗口内所有看台/区域的座位按区域加载。看台内座位的关键技术是获取到当前浏览器窗口内所展示出来的看台/区域。那么如何来做
呢?首先我们设定一个矩形区域,同步浏览器视窗的范围,然后可以通过 getBBox()获取矩形区
域内部的看台元素,最后遍历看台区域并与矩形区域进行对比,可以根据业务需要来设定重叠 多少面积触发加载内部座位的逻辑。
2)预加载浏览器窗口附近的看台/区域的座位,保证在用户移动底图时可以更快速地浏览 视窗以外的其他座位。
预加载的初衷是减少异步加载的耗时,提高用户体验。这里的预加载并非 Application Cache, 而是一种巧妙的提前加载方案:如之前说过的如何实现获取浏览器视窗内的所有看台区域,在 这个基础上我们可以在对比的过程中将实际的 SVG 面板缩小一定的比例,比如 80%,那么得到的看台区域和视窗矩形重叠的部分会增加,更会有实际视窗外的看台被视作与矩形有重叠,就 是这样我们可以提前拿到视窗外且遍布在视窗周边的看台区域,把这些区域提前加载出来从而 实现预加载。
3)以座位维度单点绘制座位。早期麦座座位图场景绘制座位的维度是看台,也就是从服务端获取的数据是看台集合,而看台到座位需要遍历看台、区域、块、排。在浏览器渲染座位之前,做了很多数据包装的工作,
而且操作的数据量是很庞大的,性能与绘制效率均受到了不同程度的影响。

架构设计

业界普遍采取的技术实现方案有三种:Dom 渲染、Svg 渲染和 Svg+Canvas 渲染。基本的 架构设计思路如下:
本文解决方案采用 Grid 思路:将座位坐标进行按照一定范围,比如 2000(经测算这个范围 2000*2000 比较合适)进行网化,也就是将元素坐标在 0 到 2000 的放到一个网格、2001 到 4000 的放到一个网格,以此类推。
 

性能提升

 

1. 座位图快照

目的:提高页面加载速度;
产物:利用 Canvas 快照能力,将非焦点区域的座位图以图片的形势展示出来,减少不必 要的 Canvas 渲染。

2.全场景数据打通

目的:加载与渲染速度提升;
产物:画座、票房规划、单场次/跨场次锁座、门店销售、打印座位图打通获取场次、票 档信息、座位数据的结构,座位由原来的看台维度的加载变化成座位单点加载,规避了 大量的深层 Map 结构解析与数据包装。

3.局部异步渲染

目的:降低引起重绘的 CPU 使用率;
产物:设置票档、保留票、套票、高亮等操作,将所选中的座位设置成临时方形矩阵, 重绘矩阵内部的座位。
4.Canvas 拆分
目的:减少页面加载渲染卡顿; 
产物:Canvas 宽高大于一定数值(经过测试这个数值在大多数浏览器下是 5000)时, 就会出现卡顿问题,Demo 之所以不会比较流畅,是因为模拟的十万座位数据比较密集,Canvas 没有设置到那么大,将多个小的 Canvas 拼接,然后再绘制座位,按照座位坐标 确定座位该绘制到具体的 Canvas 上。

5.组件化沉淀

目的:提高多处相似能力的可复用性,降低技术成本。低耦合,高维护性;
产物:鹰眼图组件、座位变形组件、票房规划相关组件、创建座位组件等等。

 

辅助工具

1)圈选:通过鼠标右键圈选自定义矩形块,选中矩形块内的座位集合;
2)套索:类似于 Photoshop 套索工具,可以通过打点完成不规则图形的圈选,选中多边形 区域内的座位集合;
3)增量选座:增量添加已选座位,可以通过不同的选座工具做增量添加;
4)Svg 校验:团队内部根据一套完善的 Svg 规范定义,对新绘制的 Svg 进行校验,目的是过滤掉一些不符合规范的 Svg 底图,避免到线上出现比例有误影响缩放效果和底图显示出现问 题的情况,同时避免出现因为 Svg 底图的问题导致已生产完毕的场次重新生产的情况;
5)标尺。辅助绘座对其排、列的标尺工具,可随意切换颜色。

 

新领域:“全景、3D”思路与初探

现有的一些技术资源介绍:
1)ThreeJs:被称作 3D 大哥的 ThreeJS 封装了 WebGL 很多核心方法,通过做三个核心“场景(Scene)”、“相机(Camera)”和“渲染器(Renderer)”完成 3D 效果,需要自己造轮子、自己搬 砖,看案例性能上需要做很多优化工作,坑也需要自己一点点去踩;
2)Aframe:入手相对容易,还可以支持 VR 模式观看,但比较鸡肋,不支持放大缩小,移 动端视角不支持移动;
3)jQuery-VRview:开源插件很多,但功能大多都未必不合适我们要的场景,需要探索一 下资源库碰碰运气;
4)Pannellum:国外的一个插件,图片宽度最大限制 4086,图片放大后有失真、像素感严 重的情况,尤其是移动端;
5)Krpano:但是据说很好用,市面上很多全景 VR 公司用的都是这个。缺点是本地生产, 如果需要上传,有 Linux 版本,可能需要 Java 帮助,是收费的。
3D 全景展示目标看台的视角/视野效果:图片资源要求比较严格,可能需要专业的设备和 “摄影师”,具体是受 WebGL 规范影响,图片的宽度有要求,所以涉及到图片的裁减与拼接,图 片质量直接影响分辨率和抗锯齿程度。
用户视角:鼠标悬浮展示当前看台的视觉效果,主要是图片展示给用户一个直观感受,类 似于国外网站 Seats Master 的效果。


热 文 推 荐

1分钟抗住10亿请求!某些App怎么做到的?| 原力计划

工程师如何从技术转型做管理?

2020,国产AI开源框架“亮剑”TensorFlow、PyTorch

罗永浩回应做主播赚钱还债;360 否认裁员;Kubernetes 1.18 版本发布

另一种声音:容器是不是未来?

探索比特币独特时间链、挖矿费用及场外交易的概念


你点的每个“在看”,我都认真当成了喜欢

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存