写点什么

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

2020 年 3 月 20 日

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

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


一、业务场景

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



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


二、功能场景

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


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 年 3 月 20 日 10:001089

评论 1 条评论

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

架构师训练营 - 第五周 - 作业

韩挺

20道Redis面试题(含答案)面试官会问的我都找到了

你是人间四月天

redis Spring Cloud Java 面试 redis6.0.0 Redis项目

正确的做事比做正确的事更重要

魔曦

架构师 极客大学架构师训练营

Spring Boot 多数据源 Redis 配置

南南

redis Spring Boot Java 面试 Redis作者

最右JS2Flutter框架——开篇(一)

刘剑

flutter 前端 探索与实践

week5 学习总结

Geek_2e7dd7

架构师训练营 - 第 5 周命题作业

红了哟

记录一次拼多多Web前端面试【一面+二面+hr面】

阿文

Spring Cloud Spring Boot Web Java 面试

阿里内推面试,挂在了一道简单的问题上…

小新

Java 阿里巴巴 程序员 架构 面试

产业区块链发展迎来爆发期

CECBC区块链专委会

产业区块链 系统稳定性 应用安全性 信任的机器

这份架构PDF如何得到百度、洋码头、饿了么CTO等大咖联袂推荐?

小新

Java 架构 面试 队列

架构师训练营 - 第五周 - 学习总结

韩挺

【week05作业】

chengjing

架构师训练营 - 第 5 周学习总结

红了哟

码农必备SQL高性能优化指南!35+条优化建议立马get

码哥小胖

MySQL SQL语法 sql查询 sql

【week05】总结

chengjing

架构师训练营 - 第五周命题作业

牛牛

极客大学架构师训练营 命题作业 一致性Hash算法

第五周总结

武鹏

为你的 SpringBoot 服务生成或推送各平台的部署包

华宇法律科技

Docker k8s springboot

公司制的黄昏:区块链重构商业世界

CECBC区块链专委会

区块链思维 裂变 契约 激励

Week5 学习总结

wyzwlj

极客大学架构师训练营

程序员是这样解读《隐秘的角落》

陈东泽 EuryChen

学习 程序员 隐秘的角落

搞懂Spring事务失效的8大原因,轻轻松松面试过关

码哥小胖

Java spring Spring Boot

week5

Geek_2e7dd7

深入理解队列:LinkedBlockingQueue源码深度解析

itlemon

阻塞队列 LinkedBlockingQueue Queue

Uniapp使用GoEasy实现websocket实时通讯

GoEasy消息推送

uni-app websocket 即时通讯

啃碎并发(一):Java线程总述与概念

猿灯塔

一篇文章深入理解分布式锁

itlemon

redis 分布式锁

打造Redis分布式环境下的银弹?我觉得Redisson比Redlock更胜一筹

码农月半

Java redis redis高可用 Redis项目

老龄化时代的人机共生:京东数科以AI机器人推动产业增长

脑极体

最强总结——分布式事务处理方式

小闫

分布式 分布式锁 Java 面试 分布式存储 分布式缓存

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