深入理解three.js对svg的支持(二):SVGRenderer
2017-07-14 20:31
686 查看
前言:SVG作为一种优秀的矢量图形格式在Web得到广泛应用,three.js作为知名的WebGL库自然也对其提供了支持。然而,官方文档中对此的说明十分单薄,网上与此相关的资源也不多。经过多次试验之后,在此分享我的一点理解,包括SVGLoader,SVGObject,SVGRenderer,svg和THREE对象的互相转化等内容。
至于
注意到这里有一个_svg对象,它在一开始就被定义为DOM元素,所有的内容都在此对象下显示,其构建完成之后就是一个完整的svg图像。
其实
可见
先不管,看它是如何渲染的呢?render的最后有这么一段代码:
原来渲染流程的最后会通过遍历查找scene中的SVGObject对象,单独处理SVGObject!对,2.1小节部分的render代码你怎么改都和SVGObject的显示没关系……,读取其node——合着是把我们的svg图像放到了_svg里,再放到DOM里而已,纯粹是多套了一层啊——坑爹呢是!
怪不得不能用变换,因为数据都在node属性里,又没有提供任何操作node的方法,你变transform和这个扩展出来的node没有任何关系。想变的话。。。改源代码吧——但又回到svg蛋疼的变换上去了。(我想静静)
下篇中,将对svg于THREE对象的关系进行进一步的探索。
2 SVGRenderer
上文说到了SVGRenderer的机制,那么这一节就来看看源码。源码不长,只有500多行。
2.1 THREE对象转svg
SVGRenderer代码的核心在
this.render方法上。渲染的数据从投影得来:
_projector = new THREE.Projector(), ... _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements ); _elements = _renderData.elements; _lights = _renderData.lights;
至于
Projector.js就复杂多了,单单
projectScene方法代码的行数就和整个
SVGRenderer.js一样多,不再深究,有兴趣的自行研读。
_renderData包含了元素和光照信息。撇开光照不谈,数组
_elements是核心数据,对其进行遍历渲染。这里将元素分为了3种类型,是根据
Projector.js制定,但不完全对应。3种类型分别是
THREE.RenderableSprite、
THREE.RenderableLine、
THREE.RenderableFace,每个类型的判断中分别调用各自的render函数,如
renderLine等,各自的render函数大同小异,核心流程和函数定义的伪代码如下:
//遍历元素将数据放入_svg for e in elements: if e是3种的某一种: 处理数据 调用自己的render方法 flushPath()//将最后一条路径数据存入_svg,因为addPath机制的原因,最后一条路径不会调用flushPath,因此_currentPath中的数据不会保存到_svg中,得手动来一下 //函数定义 3种render: 将数据按照svg path格式编码到path、处理style; addPath(style,path); addPath: if style == _currentStyle: path放入_currentPath; else: flushPath(); 清空_currentPath和_currentStyle; flushPath(): _currentPath和_currentStyle数据放入_svg; 清空_currentPath和_currentStyle;
注意到这里有一个_svg对象,它在一开始就被定义为DOM元素,所有的内容都在此对象下显示,其构建完成之后就是一个完整的svg图像。
SVGRenderer的功能还是很强大的,可以将视口中的三维物体转为二维svg显示(统一使用
<path>编码)。如官方的例子就是将一组动态的
THREE.Line转为了svg的path在SVGRenderer中显示。
2.2 SVGObject
等等,前面的这些都是三维对象转svg的例子,那么SVGObject是怎样在
SVGRenderer中显示的呢?
其实
SVGRenderer.js的源码首先就给出了
SVGObject的定义:
THREE.SVGObject = function ( node ) { THREE.Object3D.call( this ); this.node = node; }; THREE.SVGObject.prototype = Object.create( THREE.Object3D.prototype ); THREE.SVGObject.prototype.constructor = THREE.SVGObject;
可见
SVGObject确实是继承自
Object3D,但是注意构造函数,有个传入参数
node,并且还动态扩展了一个属性
this.node,这个就是SVG文件的根节点啊,有种不好的预感……
先不管,看它是如何渲染的呢?render的最后有这么一段代码:
scene.traverseVisible( function ( object ) { if ( object instanceof THREE.SVGObject ) { _vector3.setFromMatrixPosition( object.matrixWorld ); _vector3.applyMatrix4( _viewProjectionMatrix ); var x = _vector3.x * _svgWidthHalf; var y = - _vector3.y * _svgHeightHalf; var node = object.node; node.setAttribute( 'transform', 'translate(' + x + ',' + y + ')' ); _svg.appendChild( node ); } } );
原来渲染流程的最后会通过遍历查找scene中的SVGObject对象,单独处理SVGObject!对,2.1小节部分的render代码你怎么改都和SVGObject的显示没关系……,读取其node——合着是把我们的svg图像放到了_svg里,再放到DOM里而已,纯粹是多套了一层啊——坑爹呢是!
怪不得不能用变换,因为数据都在node属性里,又没有提供任何操作node的方法,你变transform和这个扩展出来的node没有任何关系。想变的话。。。改源代码吧——但又回到svg蛋疼的变换上去了。(我想静静)
下篇中,将对svg于THREE对象的关系进行进一步的探索。
相关文章推荐
- 深入理解three.js对svg的支持(三):svg转three对象
- 深入理解three.js对svg的支持(一):SVGLoader
- 深入理解js中的闭包
- 深入理解js中的闭包
- javascript深入理解js闭包
- 深入理解 ASP.NET 与客户端缓存 (Part 2 - ASP.NET 支持)
- javascript:深入理解js闭包
- 图说js中的this——深入理解javascript中this指针
- js的事件深入理解
- 深入理解C#索引器(一种支持参数的属性)与属性的对比
- javascript深入理解js闭包
- 深入理解AngularJs-scope(一)
- 深入理解Spring Redis的使用 (二)、RedisTemplate事务支持、序列化
- 深入理解Lustre文件系统-第8篇 基础结构支持
- javascript深入理解js闭包
- javascript深入理解js闭包
- javascript深入理解js闭包
- javascript深入理解js闭包
- 深入理解js闭包
- javascript技巧-javascript深入理解js闭包