尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Two.js SVG 渲染器(Two.SVGRenderer)深度解析:从场景图到 `<svg />` 的渲染管线与实战指南

Two.js SVG 渲染器(Two.SVGRenderer)深度解析:从场景图到 `<svg />` 的渲染管线与实战指南 图形学前端【免费下载链接】two.jsA renderer agnostic two-dimensional drawing api for the web项目地址https://gitcode.com/gh_mirrors/tw/two.js点击查看免费下载Two.SVGRenderer是 Two.js 渲染器家族中面向矢量 DOM 的实现也是new Two(...)在不显式指定渲染类型时默认启用的渲染后端。它负责把 Two.js 的场景图scenegraph——由Group、Path、Text、渐变与纹理等对象组成的层级结构——翻译成浏览器原生的svg /元素树适用于图标、图表、可缩放插画以及任何需要高保真矢量输出的 Web 场景。读完本文你将掌握Two.SVGRenderer的构造参数、核心成员与渲染方法并深入理解 pathd属性生成、渐变/纹理defs管理、遮罩与裁剪等底层机制能够在此基础上自行阅读源码、调试渲染结果甚至定制渲染行为。Two.SVGRenderer 是什么Two.js 的默认渲染后端Two.js 是一个渲染器无关renderer agnostic的二维绘图库同一套场景图可以输出到 SVG、Canvas 与 WebGL 三种后端。Two.SVGRenderer就是其中之一官方文档对其定位的说明是This class is used by Two when constructing withtypeofTwo.Types.svg(the default type). It takes Two.js scenegraph and renders it to asvg /.类继承关系为Two.SVGRenderer extends Two.Events事件体系参见 wiki/docs/events/README.md因此它天然支持addEventListener/trigger等事件能力例如尺寸变化时会派发Two.Events.resize事件。渲染类型在 src/constants.js 中定义Types: { webgl: WebGLRenderer, svg: SVGRenderer, canvas: CanvasRenderer, },在 src/two.js 的构造逻辑中type默认值就是Two.Types.svg。这意味着下面的写法就足以得到一个由Two.SVGRenderer驱动的实例const two new Two({ width: 640, height: 480, }); // 未指定 type默认使用 SVG 渲染器构造参数Two.SVGRenderer的构造函数在 src/renderers/svg.js 实现其参数说明如下ArgumentDescriptionparameters该对象在构造新的 Two 实例时被继承。parameters.domElement要绘制的svg /元素。如果不提供渲染器会自动构造一个新的。从源码可以看到默认行为的细节构造函数先通过svg.createElement(svg)创建 SVG 根节点并自动带上 SVG 1.1 的version属性见 src/renderers/svg.js随后创建defs /子节点并把它挂到根 SVG 下同时把根节点样式设为overflow: hiddenthis.domElement params.domElement || svg.createElement(svg); this.scene new Group(); this.scene.parent this; this.defs svg.createElement(defs); this.defs._flagUpdate false; this.domElement.appendChild(this.defs); this.domElement.defs this.defs; this.domElement.style.overflow hidden;需要注意的是Two主类在构造时会根据传入的domElement标签名自动校正渲染器类型src/two.js如果传入的元素与当前type不匹配例如给了一个svg元素却声明type: Two.Types.canvasTwo.js 会把类型覆盖为Two.Types.svg因为该元素只支持SVGRenderer-svg组合。核心实例成员domElement、scene 与 defsTwo.SVGRenderer暴露了三个贯穿渲染全流程的实例属性理解它们就抓住了渲染器的骨架成员含义domElement与 Two.js 场景关联的svg /元素是整个渲染的输出目标。scene场景图的根Group所有添加到 Two 实例中的对象都挂在这棵树下。defs用于承载渐变、图案pattern与位图素材的defs /元素。scene的声明在 src/renderers/svg.js它是一个独立的Two.Group实例。实际上Two主类在构造完成之后会把this.scene this.renderer.scenesrc/two.js所以你在two实例上通过two.add(...)添加的任何对象最终都会成为渲染器scene的子节点。defs的职责可以从渲染器对渐变、纹理的处理中看出linearGradient、radialGradient、pattern等元素都会被追加到defs下见后文渐变与纹理一节而路径元素则通过fillurl(#two-xx)/strokeurl(#two-xx)这样的引用方式关联它们。Two.js 每个对象都会获得形如two-0、two-1的自增 id前缀two-定义于 src/constants.js这个 id 正是 SVG 中跨元素引用的纽带。核心方法setSize 与 rendersetSize(width, height)变更渲染器尺寸setSize用于改变渲染器的大小签名与行为如下src/renderers/svg.jsArgumentDescriptionwidth渲染器的新宽度。height渲染器的新高度。setSize(width, height) { this.width width; this.height height; svg.setAttributes(this.domElement, { width: width, height: height, }); return this.trigger(Events.Types.resize, width, height); }方法内部会把width/height直接写成根svg的 DOM 属性并触发Two.Events.resize事件文档中以 nota-bene 的形式特别标注了这一行为。Two主类在构造时src/two.js绑定resize事件来同步维护实例的width/height字段所以当你想在运行时改画布大小时除了调用two.renderer.setSize(w, h)也可以通过two.width w; two.height h; two.update()这类上层 API 间接生效。render()把当前场景绘制到svg /render()是渲染的入口其实现非常精炼src/renderers/svg.jsrender() { svg.group.render.call(this.scene, this.domElement); svg.defs.update(this.domElement); return this; }它把根scene作为一个组来渲染随后调用svg.defs.update清理defs中已无引用的渐变/图案通过选择器[fillurl(#id)],[strokeurl(#id)],[clip-pathurl(#id)]判断引用是否仍存在见 src/renderers/svg.js。渲染完成后返回this便于链式调用。在 Two.js 的正常工作流中你一般不会直接调用render而是使用two.update()或two.play()驱动刷新单元测试如 tests/suite/svg.js正是通过two.update()之后查询two.renderer.domElement.querySelector(# id)来断言渲染结果的。静态工具集 Two.SVGRenderer.UtilsTwo.SVGRenderer.Utils源码位置 src/renderers/svg.js是官方文档中重点介绍的一个大型工具对象——它集中了把 Two.js 对象渲染到svg /所需的全部工具函数与属性源码实现即 src/renderers/svg.js 中的svg对象。DOM 工具createElement / setAttributes / removeAttributescreateElement(name, attrs)通过document.createElementNS(svg.ns, name)创建命名空间下的 SVG 元素创建svg时自动补上version: 1.1。setAttributes(elem, attrs)批量写入属性其中键名匹配/href/的属性如xlink:href会走setAttributeNS(svg.xlink, ...)以兼容旧版 SVG 命名空间写法。removeAttributes(elem, attrs)批量移除属性。命名空间常量定义在 src/renderers/svg.jsns为http://www.w3.org/2000/svgxlink为http://www.w3.org/1999/xlink。另外这里还预置了两组映射表用于把 Two.js 的语义值翻译成 SVG 标准值alignments: { left: start, center: middle, right: end }, baselines: { top: hanging, middle: middle, bottom: ideographic, baseline: alphabetic },toString(points, closed)路径d属性生成器这是渲染管线中最关键的函数之一src/renderers/svg.js它的职责是把一组顶点Anchor转换为path的d属性字符串。源码注释特别强调字符串拼接必须尽可能快因为这个调用在一秒内会发生多次动画场景。实现逻辑按顶点的command字段分发命令常量定义于 src/utils/path-commands.jsCommands.moveM记录last move点输出M x yCommands.closeZ直接输出闭合命令Commands.arcA输出完整的 SVG 椭圆弧参数A rx ry x-axis-rotation large-arc-flag sweep-flag x yCommands.curveC读取前后顶点的贝塞尔控制点controls.left/controls.right并兼容relative相对坐标模式输出三次贝塞尔曲线段C ...若处于闭合曲线的收尾处还会补上回到最近move点的C段与Z。toFixed会把坐标规整到 6 位小数src/utils/math.js这也是测试断言中d属性数值精确到55.228474这类值的原因。pointsToString(points, size)点集合渲染Points形状散点在 SVG 中同样以path输出但每个点渲染成一个小圆。pointsToStringsrc/renderers/svg.js为每个点生成一段M x ya r r 0 1 0 0.001 0 Z的微小圆弧路径。测试中Two.makePoints的输出即为该格式见 tests/suite/svg.js。getRendererType / getClipgetRendererType(type)src/renderers/svg.js把对象标记的渲染类型映射到svg工具对象上的对应条目未知类型一律回退到path。getClip(shape, domElement)src/renderers/svg.js惰性创建并复用clipPath元素追加到defs用于实现clip裁剪。各类对象的渲染管线Utils中最核心的是按渲染类型组织的render函数group、path、points、text、linear-gradient、radial-gradient与texture。它们遵循同一套脏标记flag机制Two.js 对象在属性变化时置位对应的_flagXxx渲染函数只把置位了的属性写进changed字典从而做到最小化 DOM 写入。group场景树的容器group.rendersrc/renderers/svg.js是递归遍历的起点负责隐藏对象的短路优化!this._visible !this._flagVisible或opacity 0时直接返回且不重置标记这样对象再次可见时变更会被一次性应用矩阵变换以matrix(a b c d e f)字符串写入transform属性Matrix.toString()生成逐属性同步id、opacity、display由visible映射为inline/none、class增量增删_flagAdditions/_flagSubtractions时调用appendChild/removeChild梯度与裁剪对象会被跳过_flagOrder时按顺序重排遮罩当_mask存在时先渲染遮罩对象再给当前元素写clip-path: url(#maskId)否则移除该属性。path矢量路径path.rendersrc/renderers/svg.js把 Path 及其子类矩形、圆、椭圆、多边形、星形等落成path元素属性映射关系如下Two.js 属性SVG 属性说明_flagVerticesd经svg.toString生成路径数据_flagFillfill纯色直接写值渐变/纹理写url(#id)_flagStrokestroke同上_flagLinewidthstroke-width经getEffectiveStrokeWidth处理_flagOpacitystroke-opacity/fill-opacity透明度同时作用于描边与填充_flagCapstroke-linecap线帽样式_flagJoinstroke-linejoin线段连接样式_flagMiterstroke-miterlimit斜接限制dashesstroke-dasharray/stroke-dashoffset虚线样式_flagVisiblevisibilityvisible/hidden_flagMaskclip-path遮罩引用关于stroke-width这里调用的是getEffectiveStrokeWidthsrc/utils/math.js当strokeAttenuation默认开启为true时直接返回原始线宽让描边跟随变换缩放为false时则解算世界矩阵、取scaleX/scaleY中较大者做补偿使描边在屏幕上保持恒定宽度。另外path还支持裁剪clip当对象设置了_clip时元素会被移入对应的clipPath节点取消裁剪则恢复原状src/renderers/svg.js。源码中还保留了一段关于 Chromium 裁剪 bugissue 370951的注释掉的组级双向往返实现可供研究裁剪历史行为时参考。points散点points.rendersrc/renderers/svg.js输出pathd属性由svg.pointsToString生成。它额外支持sizeAttenuation当关闭尺寸衰减时会解算世界矩阵的缩放值来调整点的大小保证点在不同缩放层级下视觉尺寸稳定。text文本text.rendersrc/renderers/svg.js把Two.Text渲染为text并利用开头的alignments/baselines映射表做语义翻译Two.js 属性SVG 属性_flagFamilyfont-family_flagSizefont-size_flagLeadingline-height_flagAlignmenttext-anchorstart/middle/end_flagBaselinedominant-baselinehanging/middle/ideographic/alphabetic_flagStyle/_flagWeight/_flagDecorationfont-style/font-weight/text-decoration_flagDirectiondirection_flagValuetextContent文本内容直接写入元素文本同样支持填充、描边、透明度、虚线与遮罩。注意文本的透明度使用的是单个opacity属性而非 path 的双 opacity因为text作为一个整体元素透明度语义更合适。渐变linear-gradient 与 radial-gradientTwo.js 的渐变对象在 SVG 后端中被翻译成linearGradient与radialGradient元素统一挂到defs下src/renderers/svg.js。线性渐变x1 / y1 / x2 / y2由left/right两个端点向量输出spreadMethod来自spread属性gradientUnits来自units属性。径向渐变cx / cy来自centerfx / fy来自focal半径输出为r。渐变的色标stops被渲染为stop子元素offset由stop._offset * 100 %生成stop-color与stop-opacity分别来自颜色与透明度。在tests/suite/svg.js的Two.makeLinearGradient测试tests/suite/svg.js中可以看到默认输出为spreadMethodpad、gradientUnitsobjectBoundingBox色标形如stop offset0% stop-colorrgb(255, 100, 100) stop-opacity1。这些属性与 Two.js 渐变类的 API 一一对应相关用法可参见 wiki/docs/effects/gradient/README.md。texture纹理与图案texture.rendersrc/renderers/svg.js把Two.Texture渲染为pattern实现图案填充图案元素设置patternUnitsuserSpaceOnUseid 作为填充引用键内部image元素的href/xlink:href根据图片来源分支canvas走toDataURL(image/png)img/image直接引用src通过offset、scale、repeat计算图案的x/y位移、width/height并按是否no-repeat决定preserveAspectRatioxMidYMid保持居中否则拉伸为none。图案会被追加到defs下并以fillurl(#textureId)的形式被路径引用最终实现平铺或拉伸的纹理填充效果详见 wiki/docs/effects/texture/README.md。与 Two 主类协同构造、尺寸与 SVG 导入从使用者的角度Two.SVGRenderer几乎完全被 src/two.js 的主类封装你通常通过Two实例间接操作它。构造相关选项包括选项默认值说明typeTwo.Types.svg渲染器类型见 wiki/docs/two/README.mdwidth/height640/480舞台尺寸构造时经renderer.setSize生效domElement自动创建指定的svg且会覆盖type推断fullscreenfalse让舞台自适应windowfittedfalse让舞台自适应父元素autostartfalse是否立即进入requestAnimationFrame循环由于 SVG 是结构化文档Two.js 还提供了two.interpret(svg)/two.load(url, callback)等 SVG 导入能力解析入口见 src/utils/interpret-svg.js 与 src/two.js 中的Two.Utils.read。导入测试覆盖了 D.svg、K.svg、donut.svg 等样例见 tests/images/interpretation 与 tests/suite/svg-interpreter.js这些能力让 Two.js 可以把既有 SVG 资产直接纳入场景图再由Two.SVGRenderer原样输出。关于导入矩阵行为可通过Two.AutoCalculateImportedMatricessrc/constants.js控制是否重新推算导入 SVG 的变换矩阵。渲染正确性的测试验证Two.SVGRenderer的行为在 tests/suite/svg.js 中被系统地验证测试方式具有很强的参考价值构造new Two({ width: 400, height: 400 })→ 通过two.makeXxx(...)创建对象 →two.update()触发渲染 →querySelector(# id)取回 SVG 元素 → 断言 DOM 属性。例如Two.makeLine断言d为M 0 0 L 400 400 Two.makeRectangle断言d为M -50 -50 L 50 -50 L 50 50 L -50 50 Z Two.makeCircle/Two.makeEllipse断言贝塞尔近似的C段坐标Two.makePath同时断言d与transformmatrix(1 0 0 1 0 0)渐变测试断言linearGradient/radialGradient的坐标、spreadMethod、gradientUnits及内嵌stop的 HTML。这套测试既是对渲染器正确性的背书也是理解Two.js 对象 → SVG 属性映射关系的最佳入门教材。你还可以运行仓库中的 QUnit 测试套件tests/index.html在浏览器中直接观察每个用例的渲染产物。总结Two.SVGRenderer是 Two.js 默认且最贴近浏览器原生能力的渲染后端它以svg /为输出目标通过 src/renderers/svg.js 中的Utils工具集把场景图翻译为path、text、linearGradient、radialGradient、pattern与clipPath等标准 SVG 元素并依靠脏标记机制实现高效的增量更新。无论是把 Two.js 场景输出为可缩放、可检索、可被 CSS 与浏览器开发者工具直接操控的矢量 DOM还是复用既有 SVG 素材Two.SVGRenderer都是最适合的起点。掌握本文梳理的构造参数、核心成员domElement/scene/defs、两个关键方法setSize/render以及各类对象的属性映射表你就能熟练驾驭 Two.js 的 SVG 渲染路径并能在需要时深入到源码层面定制渲染行为。赞分享图形学前端【免费下载链接】two.jsA renderer agnostic two-dimensional drawing api for the web项目地址https://gitcode.com/gh_mirrors/tw/two.js点击查看免费下载相关推荐Two.js CanvasRenderer 详解场景图到 canvas / 的 2D 渲染管线Two.js CanvasRenderer 详解场景图到 canvas / 的 2D 渲染管线 导读 Two.CanvasRenderer 是 Two.js图形学前端three.js 中 SVGObject 的完整指南把 SVG 图形接入 3D 场景并与渲染管线深度交错three.js 中 SVGObject 的完整指南把 SVG 图形接入 3D 场景并与渲染管线深度交错 本文围绕 three.js 官方 API 文档 SV前端3D渲染图形学GameDevMind 图形与渲染技术图谱从场景基础到现代渲染管线的完整实战指南GameDevMind 图形与渲染技术图谱从场景基础到现代渲染管线的完整实战指南 本文基于 GameDevMind 知识图谱中的《2.1.1 图形与渲染》核心文档教程知识库游戏开发上一篇推荐文章探索窗口焦点的新境界 - JankyBorders下一篇D2DX 开源项目安装与使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表