写点什么

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

  • 2020-03-03
  • 本文字数:3595 字

    阅读完需:约 12 分钟

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

一、背景

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


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


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


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



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


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


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



图 2:新绘座页面



图 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 画布上的坐标,然后和看台的外接矩形进行碰撞检测,两个矩形一旦相交,就说明该看台已暴露在视口之内,于是就加载该看台的数据。


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



图 4:按视口加载原理图


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


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



图 5:贝塞尔曲线示意图



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


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


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


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


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



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



图 7:弧度变形实际操作



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


3)打印顺序计算


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


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



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


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



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


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


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


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


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



图 11:座位排序原理图


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


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



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


5)小彩蛋之“撤回”


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


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

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

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


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


  1. 区域编辑


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


  1. 一键自动变形


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



图 13:一键变形效果图


  1. 座位复制、镜像


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


  1. 一键朝向舞台


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


作者简介


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


2020-03-03 11:002548

评论

发布
暂无评论
发现更多内容

React-Hook最佳实践

xiaofeng

React

使用python时刻中监控文件夹,记录文件夹中文件异常信息

技能实验室

Python 10月月更

在Centos6.10安装python3后安装第三方包遇到的问题

技能实验室

Python 10月月更

python版局域网端口扫描

技能实验室

Python 10月月更

python中的一个实用的库imghdr,用于探测图片格式

技能实验室

Python 10月月更

testcontainers-java 新增对 TiDB 的支持

PingCAP

TiDB

python替换图片背景色,适用于制作证件照

技能实验室

python 3.5+ 10月月更

使用python处理视频的库moviepy

技能实验室

python 3.5+ 10月月更

使用python提供一个简单的restful接口

技能实验室

python 3.5+ 10月月更

Zebec 以 Layer2 的形式推出 Zebec Chain,流支付新时达来临了

鳄鱼视界

国产CPU执行SPL实现数据库运算的性能实用性测试

石臻臻的杂货铺

数据库 SPL 10月月更

React高级特性之Context

夏天的味道123

React

高级特性之Render Props

夏天的味道123

React

使用python校验密码强度

技能实验室

python 3.5+ 10月月更

深度解析云安全责任共担模型

HummerCloud

10月月更

一文读懂 DNS 解析的工作机制和优化挑战

融云 RongCloud

DNS

React-diff原理及应用

xiaofeng

React

使用python计算两个位置的距离是多远

技能实验室

Python 10月月更

SPL 工业智能:识别指定工况

石臻臻的杂货铺

SPL 10月月更

深度理解Redux原理并实现一个redux

夏天的味道123

React

STM32 非接触测温传感器 项目记录(ModbusRTU协议)

矜辰所致

stm32 ModbusRTU 10月月更 非接触测温

个推TechDay治数训练营第三期直播预告:分享数据指标体系搭建秘诀!

个推

数据中台 数据分析 指标体系 数据指标 指标中台; 数据分析

windows机器配置自签名ssl证书,部署文件服务器

技能实验室

windows SSL证书 10月月更

AI 应用的全流程存储加速方案技术解析和实践分享

Baidu AICLOUD

海量存储 高性能计算 高性能存储 AI加速

翻译API的python调用方式

技能实验室

Python 10月月更

python实现ftp服务端和客户端

技能实验室

Python 10月月更

python入门之发送邮件

技能实验室

Python 10月月更

React的5种高级模式

夏天的味道123

React

技术分享 | 使用 Zabbix + Grafana 搭建服务器监控系统

霍格沃兹测试开发学社

技术分享 | 一文搞定 Appium 环境配置

霍格沃兹测试开发学社

使用python给图片加个盲水印

技能实验室

Python 10月月更

10W 座位的大场馆究竟是怎么画出来的?_文化 & 方法_阿里巴巴文娱技术_InfoQ精选文章