写点什么

超大型场馆的绘座选座解决方案

  • 2020-03-20
  • 本文字数:3420 字

    阅读完需:约 11 分钟

超大型场馆的绘座选座解决方案

超大型场馆座位图的加载与渲染在行业内始终是个不小的挑战,很多团队在面对绘座选座技术研发时,都难以支撑超大型场馆的座位图在浏览器端快速、稳定地渲染。如果你是奋斗在现场娱乐、剧院演出和电影院线相关行业内的一名开发者,那么文章将帮助你更多的了解大场馆座位图技术,同时可以帮助你扩展绘座选座核心功能开发的思路。

一、业务场景

麦座是一套完善的数字化运营系统,连接内容和场馆,提供票务生产、票务销售、现场管理和演出运营等能力,绘座选座是麦座的核心能力之一,从建设场馆到规划票房再到门店销售。目前可支持的十万座位量级的场馆,包括剧院、演唱会、体育赛事等多个垂类。



本文将介绍麦座的绘座、票房规划、锁座和门店销售等场景是如何通过技术手段实现业务需求的,以及超大型场馆的座位图是如何打破性能边界,给用户呈现出更流畅的交互体验。

二、功能场景

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


1. 绘座


  • Svg 导入、校验;

  • 编辑场馆信息:可对舞台、楼层、看台、区域和场馆入口等进行设置;

  • 添加座位:主要针对座位的物理属性进行设置,包含但不限于座位类型、所在区域、楼层信息、排数、列数、排序规则;

  • 块级座位变形:间距调整,可通过座位 x,y 轴的数值进行调整;

  • 旋转:将所选座位集合设置成为一个临时块,将其作为矩形矩阵。向上取整,获取离矩阵中心最近的座位,将其设做圆心,其他座位以圆心座位进行 rotate 旋转;


  • 错位:根据角度进行奇偶排位移错位;


  • 倾斜:将所选座位集合设置成为一个临时块,将其作为矩形矩阵。第一排不改变位移,从第二排开始,每一排根据上一排进行等比例位移;


  • 弧形:

  • 应用贝塞尔曲线:贝塞尔曲线是用一系列点来控制曲线状态的,我将这些点简单分为两类:数据点、控制点。通过调整控制点,贝塞尔曲线形状会发生变化;

  • 中弧算法:二阶曲线:



  • 左/右弧算法:三阶曲线:




2. 选座


  • 票房规划:规划票档、保留票、套票和打印座位图;


  • 锁票:根据业务场景可分为单场次锁票和跨场次锁票,跨场次锁票可支持在相同场馆的不同场次内进行锁票;

  • 门店销售:彩虹图、高级筛选、购物车和下单;


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

麦座的选座场景在两万以上座位量的大型体育赛事上,座位图页面加载缓慢、操作座位时出现卡顿等情况。


实现座位按区域加载,使用户在拖拽、缩放的同时惰性加载所需要展示区域内的座位,加快首屏渲染时间,在用户无感知的情况下加载其余区域的座位。解决因数据量庞大引起的页面加载缓慢、卡顿等体验问题。


技术实现(以规划票房场景为例):


1)展示当前浏览器窗口内所有看台/区域的座位按区域加载。


看台内座位的关键技术是获取到当前浏览器窗口内所展示出来的看台/区域。那么如何来做呢?首先我们设定一个矩形区域,同步浏览器视窗的范围,然后可以通过 getBBox()获取矩形区域内部的看台元素,最后遍历看台区域并与矩形区域进行对比,可以根据业务需要来设定重叠多少面积触发加载内部座位的逻辑。


2)预加载浏览器窗口附近的看台/区域的座位,保证在用户移动底图时可以更快速地浏览视窗以外的其他座位。


预加载的初衷是减少异步加载的耗时,提高用户体验。这里的预加载并非 applicationCache,而是一种巧妙的提前加载方案:如之前说过的如何实现获取浏览器视窗内的所有看台区域,在这个基础上我们可以在对比的过程中将实际的 SVG 面板缩小一定的比例,比如 80%,那么得到的看台区域和视窗矩形重叠的部分会增加,更会有实际视窗外的看台被视作与矩形有重叠,就是这样我们可以提前拿到视窗外且遍布在视窗周边的看台区域,把这些区域提前加载出来从而实现预加载。


3)以座位维度单点绘制座位。


早期麦座座位图场景绘制座位的维度是看台,也就是从服务端获取的数据是看台集合,而看台到座位需要遍历看台、区域、块、排。在浏览器渲染座位之前,做了很多数据包装的工作,而且操作的数据量是很庞大的,性能与绘制效率均受到了不同程度的影响。


升级前(全量加载)升级后(按区域加载)
可支持座位量小于 3 万可支持 10 万
首屏渲染时间10 秒以上2 秒以内
组件化技术组件封装,降低业务耦合度,降低开发、维护成本
数据结构各场景不一致统一座位、商品模型,统一各场景数据结构
CPU 性能峰值 145.9峰值 69.1
接口响应时长10 秒以上2 秒以内
6 万座位渲染总时长几十秒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 规范影响,图片的宽度有要求,所以涉及到图片的裁减与拼接,图片质量直接影响分辨率和抗锯齿程度。


用户视角:鼠标悬浮展示当前看台的视觉效果,主要是图片展示给用户一个直观感受,类似于国外网站 seatsMaster 的效果。


作者介绍


阿里文娱高级前端工程师 弋辰


相关阅读


电影垂直行业的云智开放平台如何炼成?


阿里工程师带你了解 B 端垂类营销中心如何设计?


云智前端技术如何赋能场馆院线?


60 秒售出 5 万张票!电影节抢票技术揭秘


电影行业提升 DCP 传输效率,还能这样做!


2020-03-20 10:002419

评论 1 条评论

发布
用户头像
弋辰牛逼
2020-03-27 14:15
回复
没有更多了
发现更多内容

Webpack 简介

编程三昧

JavaScript 大前端 Node webpack 构建工具

沿着“云云协同”的桥梁,奔赴全面云化的产业之海

脑极体

5分钟速读之Rust权威指南(二十一)闭包

wzx

rust

网络攻防学习笔记 Day41

穿过生命散发芬芳

网络攻防 6月日更

周小川:一些加密货币已经不太可能再回到支付领域

CECBC

又一个重量级的分布式链路分析的轮子

代码先生

elasticsearch ELK 分布式链路 OpenTelemetry Data Prepper

C++内存访问错误检测

正向成长

内存泄露 内存溢出 Asan

本来无一物,何处惹尘埃|靠谱点评

无量靠谱

MySQL基础之九:子查询

打工人!

myslq 6月日更

明晚Django组队学习就要开始了

IT蜗壳-Tango

6月日更

JavaScript学习(一)——简介

空城机

JavaScript 大前端 6月日更

区块链赋能新能源汽车新业态——车电分离

CECBC

被勒索一月后比特币赎金被追回,现在价值几何?

CECBC

【LeetCode】完全平方数Java题解

Albert

算法 LeetCode 6月日更

Windows PowerShell ISE 是什么和 PowerShell 有什么区别

HoneyMoose

Linux系统日常定位常用指令

正向成长

linux命令

书山有路,学海无涯|靠谱点评

无量靠谱

员工提出离职就消极怠工怎么办?

石云升

员工离职 职场经验 管理经验 6月日更

【译】是时候了解 CSS 逻辑属性了

KooFE

6月日更

【Vue2.x 源码学习】第十一篇 - Vue的数据渲染流程

Brave

源码 vue2 6月日更

面试系列-4 hash应用场景分析实践

李阿柯

php 面试 Redis 核心技术与实战

记一次差点跑路的 RabbitMQ 运维经历

看山

运维 RabbitMQ 删库 6月日更

MySQL 中的反斜杠 \\,真是太坑了!!

xcbeyond

MySQL 6月日更

Java 并发编程——volatile 关键字解析

Antway

6月日更

字节跳动Java岗6月9号一面经验分享

北游学Java

Java 字节跳动 面试

公安合成作战指挥系统解决方案,警务实战指挥系统

《原则》(十一)

Changing Lin

6月日更

Kubernetes手记(8)- Service 配置清单

雪雷

k8s 6月日更

【21-3】Zabbix 重置 Admin 密码

耳东@Erdong

zabbix 6月日更

Go http 包详解

Rayjun

Go 语言

动态规划电路布线问题(Java代码实现)

若尘

数据结构 6月日更

超大型场馆的绘座选座解决方案_文化 & 方法_阿里巴巴文娱技术_InfoQ精选文章