10W 座位的大场馆究竟是怎么画出来的?

阅读数:2 2020 年 3 月 3 日 11:00

10W 座位的大场馆究竟是怎么画出来的?

一、背景

  1. 网络售票需要画座:购票所见即所得

大麦主要业务是票务,包括演唱会、体育赛事、音乐节等,品类繁多。卖票就要画场馆、画座位,大家都在网上买过电影票,这不难理解。虽然可以拿电影售票做类比,但底层难度差异很大。没有 10W 座的电影院,却有 10W 座的演唱会,而且演出 / 体育类场馆变化多,座位不固定,场景非常复杂,想随心所欲画出 10W 座的场馆,挑战相当大。

  1. 大麦绘座演进:从示意图到实际场景图

大麦以前的绘座系统,是安装版的程序,画座位只能一个看台一个看台的画,看台之间完全无关联,画出来几乎每个看台都长一个模样,座位只有相对位置的示意图,没有角度、距离,更谈不上精确定位。

10W 座位的大场馆究竟是怎么画出来的?

图 1:老版绘座页面(已淘汰)

大麦网从 2017 年,开始设计新版绘座系统。这里没有修补,没有重构,新版绘座完全重来,连技术栈也由.NET 换成了 Java,由 C/S 换成了 B/S。

新绘座以 SVG 矢量图为核心,通过 Canvas 进行绘制,在演进的过程中攻克了大量的性能卡点和技术难点,最终打造成型,堪以重任。

10W 座位的大场馆究竟是怎么画出来的?

图 2:新绘座页面

10W 座位的大场馆究竟是怎么画出来的?

图 3:座位效果图

二、新绘座:Flash 走了,Canvas 来了

  1. Flash 已死,来到路口,别无选择

新绘座已诞生 2 年多,现在回首,这条路似乎早已注定。

老版绘座和选座是基于 Flash 的,悲剧的是,Adobe 宣称 Flash 2020 年后,将不再维护,相关技术会在 2020 年底全部退役,大麦的绘座和选座系统,都被迫转型。

Flash 只是原因之一,看过竞争对手的产品,会发现 SVG 是条不错的道路,即使没有 Flash 这一出,大麦网也会朝这个方向迈进。

  1. 技术选型

1)任何过度使用 DOM 的应用,都不会快经过技术调研,发现国外一些场馆座位绘制,选用的是 SVG 方案,每个座位都是一个独立

的 SVG 元素。但如果直接把 SVG 搬到浏览器,无法支持几万座位的场馆,因为浏览器无法支持过多的 DOM 数量,并且,一旦 DOM 数量太多,操作一定是低效的,“任何过度使用 DOM 的应用,都不会太快”。

于是,技术同学想到了 Canvas,Canvas 是浏览器上的一个画布,无论上面绘制多少元素,对于浏览器而言,都只是一个 DOM 元素。

对于不了解 Canvas 的同学,我们可以简单做个说明,Canvas 在浏览器上,就是下面一个标签:

复制代码
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;">
</canvas>

在 Canvas 上绘图,就是使用 JS 获取 Canvas 对象,使用封装好的方法进行绘制。Canvas 画布上的图形变化,完全通过擦除 + 重绘的方式展现。

那么新绘座的目标就变得很明确了,我们就是要在 Canvas 上绘制出想要的场馆座位图,然后以 SVG 的格式把图形保存起来,用以选座、售票。

2)Canvas 也不是银弹:单个 Canvas 的大小是有限制的,超限之后也会卡顿

选型初期,技术同学使用 Canvas+SVG 做了个 Demo,模拟了 10W 座位的渲染,并实现了拖拽、缩放。但真正作为画座组件开发的时候,发现座位达到 2W 就出现了卡顿,因为 Canvas 的宽高达到一定的数值,就会出现卡顿。于是,沿着化整为零的思路,技术同学将整个画布,分成了多份 Canvas,形成了一个 Canvas 矩阵,通过对每个 Canvas 的操作,完美解决了单个 Canvas 过大引起卡顿的问题。

关于 Canvas 绘图组件,大家可以在网上搜到很多资料,这里不再赘述。

  1. 新版绘座上线初期:青苹果

刚上线的新版绘座,就像个青涩的苹果,虽然漂亮,却没那么好吃。

最突出的问题有 2 个:第 1 个是变形难用,由于算法比较初级,座位矩阵变形很难满足用户需求;第 2 个是接口速度慢,打开一个 1W 座的场馆,好几分钟,超过 5W,直接崩溃,根本无法支持。

为什么理想很丰满,结果却差强人意呢?根源在于第一版只重功能,忽略了算法效率。与服务端的接口调用,都是整个场馆级别的,几万座位数据,加上关联的看台、票、以及状态等,一个硕大的数据包在前后端丢来丢去,系统不堪重负,用户受尽折磨。

  1. 艰苦改进之旅

新绘座上线后,立刻启动了改进优化工程,主要攻克的难关有三点:页面响应时间;座位自由组合变形;打印顺序计算。

1)交互 + 接口优化,进入秒开时代

首先要解决接口慢的问题,解决效率低的一大法宝:化整为零。

从一次 load 一个场馆的数据,改成一次 load 几个看台的数据。服务端数据随着前端视口(页面可视范围)的变化,逐渐加载,类似地图常用的“拉框查询”。前端交互也从全加载,改为按视口取数据。仅此一项优化,几万座大场馆的系统响应速度,立刻由几分钟,降到了 1~2s,小场馆更是瞬时打开,系统好用了不少。

这里面最重要的一个技术点,就是视口计算,原理如下:

前端首先获取到屏幕视口在 Canvas 画布上的坐标,然后和看台的外接矩形进行碰撞检测,两个矩形一旦相交,就说明该看台已暴露在视口之内,于是就加载该看台的数据。

从接口优化开始,新绘座逐渐走向成熟。

10W 座位的大场馆究竟是怎么画出来的?

图 4:按视口加载原理图

2)合并座位矩阵,自由变形座位自由变形包括倾斜、错位、排距、座距、旋转、弧度等多种操作。除了弧度变形,其它基本上是一些数学上的坐标计算,我们不赘述,这里重点说一下弧度变形。

新弧度变形,运用贝塞尔二阶曲线原理,根据用户的数据输入,计算出相应的贝塞尔曲线,再把每排座位,均匀排列到曲线上。下面是贝塞尔二阶公式:

10W 座位的大场馆究竟是怎么画出来的?

图 5:贝塞尔曲线示意图

10W 座位的大场馆究竟是怎么画出来的?

注释:P0、P2 为一排座位的左右端点(一排的第一个座位和最后一个座位)

看似套公式就可以搞定,非常简单的样子。但是这里有一个难点:从图中可以看出,t 为比例值,处在线段 P0P2 不同的比例,所在的弧度位置也是不一样的。

如果所有的座位都在 P0P2 线段上,很好算,但是如果座位之前就是一条弧线呢?中间所有的座位都不在 P0P2 线段上,要怎么算出中间座位的每个比例?

我们通过弧线上的每个座位,做一条 P0P2 线段的垂线,垂线与线段 P0P2 的交点,就是这些座位所在这一排的原始位置,计算出这些原始位置的坐标,根据这些原始位置,就可以算出中间所有座位的比例了。

这样,弧度变形问题就通过贝塞尔二阶曲线完美解决。

10W 座位的大场馆究竟是怎么画出来的?

图 6:弧形座位矩阵贝塞尔曲线变形原理图

10W 座位的大场馆究竟是怎么画出来的?

图 7:弧度变形实际操作

10W 座位的大场馆究竟是怎么画出来的?

图 8:座位自由组合,随意变形

3)打印顺序计算

“打印顺序”是个什么鬼?

这得从大麦的业务特点说起,主办有时候会批量出票并将票配发给相关人群,有时整个看台一起打印。在配票的时候,需要按照座位的物理位置关系排序,避免座位没挨着、“2 个情侣”被“拆散”的情况发生。举个例子:下图中,主办期望打印票的顺序是“5-3-1-2-4-6”,而不是“1-2-3-4-5-6”,这样他们就可以按打印顺序配票,而不用担心两张票不挨着。那么,在绘座过程中,我们就要计算出座位的顺序,看似简单,实现起来有难度很大,原因只有一个,场馆形状各异,座位排列多样。

10W 座位的大场馆究竟是怎么画出来的?

图 9:北京奥体中心的某个看台

如果说,上图还能按照座位 Y 坐标对比进行排序,那么下面的几个情形,就不那么好处理了:

10W 座位的大场馆究竟是怎么画出来的?

图 10:各种特殊的座位排列场景

打印问题,我们通过场景汇总,对场馆进行分区,最终找到了排序的规律,得以解决。打印问题技术方案原理:

第 1 步:将场馆分成 8 个象限,象限内的座位,已标识出该如何排序(标识出了应该对比 X 坐标还是 Y 坐标来进行排序);

第 2 步:每一组座位矩阵,取出首排,求首尾座位连线的斜率,然后根据斜率将座位矩阵划分到对应象限;

第 3 步:按照对应象限的排序标识,对比座位的 X 坐标(或 Y 坐标),进行座位排序。

10W 座位的大场馆究竟是怎么画出来的?

图 11:座位排序原理图

4)小彩蛋之“沙发、角度”

效率、变形和打印 3 个主要问题根解之后,随之出现了大量的产品优化需求,开始着眼于细微之处,小沙发和座位角度就是 2 个典型的功能。这两个功能虽然难度不大,但却在体验上有了一大步的提升。

10W 座位的大场馆究竟是怎么画出来的?

图 12:圆点、沙发效果对比

5)小彩蛋之“撤回”

经过不断优化和添砖加瓦,大麦的绘座系统,越来越像一款专业的绘图工具。好的绘图工具一定需要“前进 & 撤回”功能。

新绘座系统的撤回功能实现原理:设计一个“历史数据”数组,数组里的每个元素,记录一个操作步骤对应的被编辑座位数据以及座位位置信息,回退时,找到对应操作步骤的数组元素,重绘座位位置,这样就回退了整个操作。因为无论座位相对位置如何变形,本质上,其实都是坐标数据的改变,通过记录和重绘历史坐标信息,就达到了撤回操作的目的。

三、在正确的路上继续前行

到目前为止,新绘座系统已能够承接国内外任何大型场馆的绘座工程,各种细节的优化也日臻完善,效率大幅提升。但产品和技术同学的努力,并没有终止,而是在正确的道路上,继续前行。

以下简单列举几个很实用的功能,供大家参考:

  1. 区域编辑

自由绘制矩形、圆形、多边形等各种形状,并自由变形;

  1. 一键自动变形

全选看台内的座位,点击“一键变形按钮”,座位瞬间适应看台形状,自动排列;

10W 座位的大场馆究竟是怎么画出来的?

图 13:一键变形效果图
  1. 座位复制、镜像

区用户可以自由复制选中座位,并且支持镜像、翻转等多种复制模式,排号、座位号根据设置自动处理;

  1. 一键朝向舞台

用户选中一个看台的数据,点击“一键朝向舞台”,系统会自动计算舞台方向和座位角度,瞬间将整个看台座位“摆正”。

作者简介

阿里文娱技术专家 莫那、阿里文娱高级工程师 土嚎

评论

发布