从图形到像素:前端图形编程技术概览(30)

发布于2019-04-20 11:58:18

图形是人与人之间传递信息的媒介,直观性远胜于口头语言和书面语言。4000多年前,古巴比伦人在石块上绘制建筑物的平面图;2000多年前,古希腊人用图形表达建筑思想,而与其相关的数学直到文艺复兴时期才开始完善。

—— 摘自《交互式计算机图形学(第七版)》

将以上的理念带入到计算机领域,图形是计算机向用户传递信息的主要媒介。不论是26个英文字母构成的代码还是枯燥的二进制,在直观性上远不能比得上图形。这也是前端相对于其他领域最显著的特征。

我入行前端的过程颇有些曲折,读书期间主攻的方向是当时正热的Android开发,拿到的第一个offer是盛大游戏的测试实习生。可惜盛大要求每周五天全勤,而当时我正在写毕业论文,时间上没法保证,很遗憾地拒掉了。第二个offer是SAP上海研究院BI部门的前端实习生,有趣的是,面试的过程中没有被问及任何关于前端的东西,反而着重讨论了Android的UI适配问题。最终靠着Android开发的一点皮毛知识,因缘巧合地成为了一名前端开发者。

在SAP参与的项目是基于SVG的charts图表库,技术选型上使用的是开源的D3.js。Charts在完整的Web应用中仅仅是作为展示数据的工具,是相对小众的领域,尤其是在如今普及大前端概念的时代背景下更鲜有人讨论。我在实习的半年时间内,没有接触到AJAX/跨域/CSS兼容性这些前端“常识”,烂熟于心的是viewBox/transform/SMIL(用于实现SVG动画)等SVG图形编程的基本要素。然而尴尬的是参加校招时发现根本没有任何一家公司的前端笔试和面试会涉及这些,导致当时我郁闷地以为怕是入错了行。后来随着工作的深入,我逐渐体会到虽然charts与常规前端项目所涉及的知识点略有不同,但实际上两者的差异并非表面看上去那样巨大。

举个比较常见的例子,SVG与CSS存在同名属性transform,用法基本一致(SVG不支持3D变换),支持translate/scale等快捷写法,也支持matrix矩阵。CSStransform的默认变换原点为HTML节点自身的中心,即transform-origin:center center。

SVG中并不存在transform-origin属性,其变换的的原点始终为SVG节点自身的左上角。其实CSS的transform-origin默认为center center是考虑到日常开发中所接触的transform大多以中心点均为原点,如果将其赋值为0 0则与SVG等同。

transform-origin很大程度上简化了transform的复杂度,但本质上CSS的transform使用的是与SVG相同的坐标体系。事实上,CSS的transform规范本身便是在SVG 1.1规范的基础上延展而来。除此之外,常规前端技术领域还存在与SVG许多相似的理念,比如CSS animation/key-frame与SMIL、Shadow DOM与SVG<use>等等。

值得一提的是,D3.js的节点与数据绑定、数据驱动UI的模式与React颇为类似,却比React的诞生早了许多年。

从图形到像素

虽然相对于CSS,SVG略显晦涩,但它本身仍然是非常上层的图形编程技术。SVG是一种描述性语言,编程的主要方式是通过标签和属性的搭配,其语义性侧重功能而非逻辑。开发者需要做的是熟知各个标签和属性的功能,而无需关注底层实现。比如计算机图形学所描述的最小系统仅支持点、线段和三角形这三种基本图元,SVG一个简单的<circle>标签背后是计算机在基本图元基础上逐个像素的计算逻辑。也就是说,SVG编程的最小单元是图形而非像素。细节处理能力的不足,以及性能的瓶颈(大量的节点),令SVG难以应对复杂的图形应用程序,“面向像素”的图形编程技术-canvas便成了进一步的选择。

准确地说,canvas分为两部分:HTML中的<canvas>标签和渲染上下文(Rendering Context),其中渲染上下文又可分为2D渲染上下文和WebGL渲染上下文。canvas 2D在图形的绘制层面可以视为SVG的阉割版:去掉了图形,只保留路径(path)。

canvas 2D渲染的基本图元只有长方形rect,其他所有图形均是由path完成。在path的基础上封装了一些常用路径的便捷API,比如直线lineTo()、圆弧arc()、贝塞尔曲线bezierCurveTo()等等。对于简单图形的绘制canvas并不如SVG便捷,所以对于数据量较小、结构简单的charts(比如柱状图、饼图等)SVG是比canvas更好的技术选型。canvas的强大之处在于两点:

从CSS到SVG,前端UI脱离了方块(CSS盒子)的束缚;从SVG到canvas,前端UI的表现力深入到像素级。但截止到此也仅仅是在二维世界里打转,前端UI急切需要能将其带入到三维世界的“三向箔”。

从二维到三维

WebGL其实是个“老古董”了,早在2007年Mozilla和Opera浏览器就各自实现了初始版本。其标准的推进也非常迅速,WebGL 1.0标准规范于2011年发布。对比之下,2014年被正式确认的HTML5;2015年发布的ES6;以及虽然1999年就开始制定草案却直至今天仍有部分特性未被确定为标准的CSS3们简直就是小鲜肉了。

相对于canvas 2D,WebGL不仅仅是只增加了一个Z轴,而是更底层的图形编程技术。WebGL理论上更接近纯粹的计算机图形学,基本图元只包括点、线段和三角形,并且只支持1像素宽的线段。像素处理仅仅是canvas 2D的一种高级特性,但是对于WebGL来说,每一次绘制都是像素级操作。

与CSS/SVG/canvas 2D比起来,WebGL的开发过程是相对枯燥的,没有便捷的绘图和变换API,每个图形均是向量和矩阵综合运算的结果。但这也正是图形编程独特的魅力。将枯燥的数字和最简单的图元组合为复杂的UI,这是一种极致的创造乐趣。

WebGL shader的计算由GPU承担,有着比CPU更强悍的计算能力,所以WebGL最佳的应用场景是数据量庞大、计算密集型程序。目前市场对于WebGL应用最广泛的领域包括游戏、地图、WebVR、数据可视化等。

游戏

游戏是一种极致的强交互式应用,受限于浏览器可调用资源的局限性,HTML5游戏相对于客户端游戏更轻量,但是随着设备硬件性能的提升和浏览器的进化,目前市面上也不乏可媲美端游的大型HTML5游戏。在保证图形质量的前提下,游戏引擎最核心的是计算性能,能够调动GPU的WebGL自然成为了不二之选。

地图

目前较主流的地图厂商如Google、高德、百度等均推出了矢量的3D web地图(搜狗地图的矢量引擎即将推出,敬请期待),高清3D地图的数据体量和计算密集度并不亚于游戏。

WebVR

2016年被称为“VR元年”,虽然目前VR的热门度远不及当初,但并不代表这个领域没有市场,只是回到了一个相对理性和稳定的发展速度上。强调沉浸式体验的WebVR对图形的要求非常苛刻,在VR视角下1像素的锯齿都会影响整体的观感。此外,WebVR的视角变换灵敏度远甚于鼠标和键盘,用户头部一个微小角度的转动都会触发应用程序大量的计算。综合这些特征,开发WebVR应用的技术栈必须具有像素级处理能力以及高性能计算能力,在前端技术领域能够满足这两项要求的仅有WebGL。

数据可视化

在人工智能几乎遍布街头巷尾的今天,TensorFlow.js带给了前端开发者一个新的市场和方向。作为前端开发者,尤其是作为一个WebGL图形编程的从业者,我看到了人工智能与前端最紧密也是最理性的结合方式:数据可视化。如果试图依靠前端有限的计算能力做深度的机器学习可能有些痴人说梦,但是不论什么时代、何种业务形式,视觉展示都是“刚需”。数据体量和交互场景复杂度的提升也必然推进数据可视化领域的改革,WebGL必然会取代SVG成为复杂数据可视化应用的最佳选择。

与新技术的融合

性能是计算密集型图形编程的应用架构核心要素之一,任何可压榨浏览器性能的技术和模式均可尝试,即便新技术只具备部分可行性,比如web worker和WebAssembly。

web worker用于实现多线程,并且worker线程安全,是前端实现并行计算的最佳也是唯一技术选型。目前浏览器支持度比较理想,几乎成为了WebGL应用的基础技术栈。

WebAssembly正式规范虽然还未发布,但可以确定的是WebAssembly能够大幅提升前端的计算性能,计算密集型的图形编程是其最佳的应用场景之一。

工程化

相对于常规前端项目,图形编程应用在工程化实施上更具优势。图形编程是纯粹的客户端渲染并且无SEO需求,更利于前后端分离开发和动静资源的分离部署。数据驱动UI也更利于单元测试。

总结

传世名画无非是简单的颜料所成,背后是画师们独特的构图思想和创作技法;木结构的中国古建筑得以千年不倒,其精髓不在于木材而是工匠们的榫卯技艺,这些均是用简单原料创造出的艺术品。从CSS到SVG,从SVG到Canvas2D,从Canvas2D到WebGL,前端图形编程技术越来越接近底层,开发者所能使用的“原料”也越来越有限,用最简单的原料实现丰富视觉表现力的过程中必然充满了极致的创造乐趣。

作者简介

周俊鹏,搜狗地图Web前端主管,负责Web前端团队管理和工程化体系建设工作。主要研究方向为前端工程化、前端图形编程和 Web 应用层架构。

更多内容,请关注前端之巅。

会议推荐

2019年6月,GMTC全球大前端技术大会2019即将到来。小程序、Flutter、移动AI、工程化、性能优化…大前端的下一站在哪里?点击下图了解更多详情。