ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

PixiJS v8 遮罩(Masking)完全指南:AlphaMask、StencilMask、ScissorMask 与 ColorMask

PixiJS v8 遮罩(Masking)完全指南:AlphaMask、StencilMask、ScissorMask 与 ColorMask PixiJS v8 遮罩Masking完全指南AlphaMask、StencilMask、ScissorMask 与 ColorMask【免费下载链接】pixijsThe HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.项目地址: https://gitcode.com/gh_mirrors/pi/pixijs导读遮罩Masking是 PixiJS 中最常用的视觉裁剪手段之一它允许你用任意形状裁剪显示对象的渲染区域实现圆形头像、图片挖洞、渐隐过渡、UI 蒙版等效果。本指南以 PixiJS 场景容器scene/container体系中的遮罩能力为核心系统讲解 PixiJS v8 支持的四种遮罩类型——基于 Sprite 纹理的 AlphaMask、基于 Graphics/Container 的 StencilMask模板缓冲、轴对齐矩形的 ScissorMask以及按通道位掩码裁剪的 ColorMask——并通过源码级解析与仓库内的真实示例帮助你掌握遮罩类型自动选择机制、通道选择、反向遮罩、遮罩移除等全部核心用法与性能取舍。遮罩体系总览四种类型与自动选择在 PixiJS 中遮罩的本质是用一个显示对象或数值限制另一个容器及其子树的可见区域。PixiJS v8 支持四种遮罩类型遮罩对象实际使用的类型性能开销说明Graphics或ContainerStencilMask中等使用模板缓冲stencil bufferSpriteAlphaMask昂贵内部走滤镜filter管线Number例如0xFColorMask最便宜对 RGBA 四个通道做位掩码性能层级从低到高为ColorMask最便宜 StencilMask AlphaMask最昂贵。在视觉效果允许的前提下应优先选择最简单的遮罩类型。值得注意的一个细节是代码库中虽然存在ScissorMasksrc/rendering/mask/scissor/ScissorMask.ts但遮罩系统不会自动选中它——只有AlphaMask、StencilMask、ColorMask被注册为遮罩效果MaskEffect。从 MaskEffectManager.ts 的扩展注册机制可以确认这一点StencilMask、AlphaMask、ColorMask三个类都声明了public static extension: ExtensionMetadata ExtensionType.MaskEffect而ScissorMask没有extension静态属性因此不会被自动使用。快速上手三步完成基础遮罩最简单的遮罩使用方式是把一个显示对象赋给容器的mask属性const photoGroup new Container(); photoGroup.addChild(new Sprite(await Assets.load(photo.png))); const mask new Graphics().circle(100, 100, 80).fill(0xffffff); photoGroup.mask mask; photoGroup.addChild(mask); app.stage.addChild(photoGroup);这里有两条重要的使用约定遮罩必须位于被遮罩对象父级的场景图中典型做法是作为被遮罩Container的子节点这样它的变换transform才能跟随被遮罩的子树同步。这一点在 effectsMixin.ts 的类型注释中也有强调A mask of an object must be in the subtree of its parent. Otherwise,getLocalBoundsmay calculate incorrect bounds遮罩必须位于对象父级的子树中否则getLocalBounds可能计算出错误的边界进而导致容器宽高异常。Sprite、Text等叶子节点不能持有遮罩作为子节点这些类allowChildren false。如果需要给 Sprite 或 Text 加遮罩请像上面的示例一样把它们包进一个Container中。为容器设置container.mask后PixiJS 会根据所赋对象的类型自动选择遮罩类型赋Graphics/Container走 Stencil赋Sprite走 Alpha赋数字走 Color。核心模式Core PatternsStencil 遮罩基于 Graphics模板缓冲遮罩是处理不规则几何形状时的默认选择也是性价比最高的形状裁剪方案const container new Container(); const mask new Graphics().roundRect(0, 0, 200, 150, 20).fill(0xffffff); container.mask mask; container.addChild(mask);要点遮罩Graphics应该是被遮罩容器的子节点或与被遮罩对象共享同一坐标空间。填充颜色无关紧要——只有形状参与裁剪。从源码看StencilMask.ts 的init方法会把遮罩对象标记为includeInBuild false和measurable false即它参与模板裁剪但不会被重复渲染进画面、也不参与父级边界测量reset时恢复这两个标志。此外StencilMask.test的判断条件是mask instanceof Container所以任何 Container 子类Graphics、Sprite、甚至普通 Container作为mask赋值时理论上都会先命中 Stencil 分支——但实际类型判定顺序由注册顺序决定见下文类型自动选择的源码实现。Alpha 遮罩基于 Sprite当需要用纹理的灰度/透明度做渐变式裁剪例如羽化边缘、渐隐过渡时使用 Sprite 作为遮罩const maskTexture await Assets.load(gradient-mask.png); const maskSprite new Sprite(maskTexture); const photoGroup new Container(); photoGroup.addChild(new Sprite(await Assets.load(photo.png))); photoGroup.mask maskSprite; photoGroup.addChild(maskSprite);Alpha 遮罩**默认读取 Sprite 纹理的红色通道red channel**来控制可见性红色值高 完全可见红色为 0 隐藏。这是最昂贵的遮罩类型因为它在内部使用了滤镜管线filter pipeline——在 AlphaMask.ts 中可以看到它的pipe alphaMask而实际渲染由MaskFiltersrc/filters/mask/MaskFilter.ts驱动它是一个继承自Filter的着色器过滤器通过 uniformuChannel0 表示 red、1 表示 alpha和uInverse0/1控制采样通道与反向逻辑。从 AlphaMask.ts 的init还可以看到一个内部优化细节renderMaskToTexture !(mask instanceof Sprite)——如果遮罩对象不是 Sprite会先被渲染到一张纹理上再参与 alpha 遮罩计算。遮罩通道选择Mask Channel如果遮罩纹理本身使用的是透明度例如一张带 alpha 渐变的 PNG可以通过setMask切换到 alpha 通道const maskSprite new Sprite(await Assets.load(alpha-gradient.png)); const photoGroup new Container(); photoGroup.addChild(new Sprite(await Assets.load(photo.png))); photoGroup.setMask({ mask: maskSprite, channel: alpha }); photoGroup.addChild(maskSprite);可用通道red默认、alpha。当同一张遮罩纹理在不同通道中编码了不同形状时例如红色通道画了星形、alpha 通道画了圆形这一能力尤其有用。仓库中的 examples/container_alpha-channel-mask.ts 就是一个完整的实战演示它用Graphics绘制一张红色星形 半透明蓝色圆形的遮罩纹理然后分别以channel: red与channel: alpha应用到两张相同的照片上——前者只露出星形区域后者露出完整的圆形。该示例还印证了通道默认值与选项定义在 effectsMixin.ts 中_maskOptions的默认值即为{ inverse: false, channel: red }且MaskChannel类型定义red | alpha位于 MaskFilter.ts。反向遮罩Inverse Masking使用setMask并传入inverse: true可以显示遮罩形状之外的所有内容即挖洞效果const holeMask new Graphics().circle(100, 100, 80).fill(0xffffff); const container new Container(); container.setMask({ mask: holeMask, inverse: true }); container.addChild(holeMask); const maskSprite new Sprite(await Assets.load(mask.png)); const photoGroup new Container(); photoGroup.addChild(new Sprite(await Assets.load(photo.png))); photoGroup.setMask({ mask: maskSprite, inverse: true }); photoGroup.addChild(maskSprite);Alpha 遮罩与 Stencil 遮罩在WebGL 和 WebGPU 上都支持反向。Canvas2D 不支持反向 Stencil 遮罩——它会记录一条警告并忽略该标志。反向标志的底层实现同样可以在 MaskFilter.ts 中看到uInverseuniform 被写入片段着色器参与计算而在 AlphaMask.ts 的addBounds中反向遮罩时遮罩对象本身不参与边界计算if (!this.inverse) addMaskBounds(...)这保证了反向遮罩的边界语义正确。仓库中的 examples/container_inverse-mask.ts 提供了一个开箱即用的反向遮罩示例一个红色矩形配上五角星形状的反向遮罩形成星形区域被挖空的视觉效果完整展示了rect.setMask({ mask: masky, inverse: true })的用法。移除遮罩container.mask null; container.mask null; mask.destroy();清除遮罩时必须使用container.mask null。setMask({ mask: null })不起作用原因在于 effectsMixin.ts 中setMask的实现存在一次内部真值判断if (options.mask)才继续设置而mask为null时该分支不会执行。另外在销毁遮罩对象或被遮罩对象之前务必先移除遮罩引用置为null否则渲染管线可能访问已销毁的纹理——MaskFilter.ts 中专门有一处防御逻辑检测到遮罩纹理已销毁时会降级为Texture.EMPTY并在调试模式下输出警告The mask texture was destroyed while the mask is still in use. Remove the mask before destroying its texture.源码深挖遮罩类型自动选择的实现原理为什么赋什么对象就自动选什么遮罩类型答案在 MaskEffectManager.ts 与 effectsMixin.ts 的协同机制中注册AlphaMask、StencilMask、ColorMask各自声明extension ExtensionType.MaskEffect通过extensions.handleByList(ExtensionType.MaskEffect, MaskEffectManager._effectClasses)被收集到MaskEffectManager。测试每个遮罩类实现静态test(mask)方法——ColorMask.test判断typeof mask numberStencilMask.test判断mask instanceof ContainerAlphaMask.test判断mask instanceof Sprite。MaskEffectManager.getMaskEffect(item)按注册顺序遍历这些测试命中第一个匹配的类。转换与对象池命中后从BigPool取出对应的 Effect 实例StencilMask/AlphaMask实现PoolItem接口支持对象池复用交给容器。接入容器effectsMixin中的masksetter 在赋值时通过MaskEffectManager.getMaskEffect(value)把原始对象转换为 Effect加入容器的effects列表_markStructureAsChanged会通知渲染组结构发生变化触发重排。渲染每种遮罩类型有独立的 pipestencilMask、alphaMask、colorMask、scissorMask如 ColorMaskPipe.ts 维护一个颜色掩码栈初始为0xFpush 时与父级掩码做按位与pop 时恢复最终调用渲染器的colorMask.setMask写入 WebGL/WebGPU 的 color mask 状态。这也解释了文档中ScissorMask存在于代码库但不会被自动选择的原因它没有注册为MaskEffect扩展其构造函数需要显式传入Container见 ScissorMask.ts适合在需要轴对齐矩形裁剪且追求近零开销的场景中手动使用。常见误区Common Mistakes[高] 将 cacheAsTexture 与遮罩组合使用cacheAsTexture()与遮罩的组合是脆弱的。在 Firefox 中它可能需要在设置遮罩与启用缓存之间加入一个超时timeout才能正常工作在其他浏览器中则可能静默失败。能避免就尽量避免组合使用如果确实需要务必在目标浏览器中充分测试。[中] 使用过多的 Sprite 遮罩Sprite 遮罩AlphaMask在内部使用滤镜管线是最昂贵的遮罩类型。同时使用大量 Sprite 遮罩会显著降低渲染性能。当视觉效果允许时优先使用 Stencil 遮罩Graphics 形状或 Scissor 遮罩轴对齐矩形。性能开销对比Scissor接近零 Stencil一次额外绘制 Alpha完整滤镜通道API 参考以下 API 的完整定义与实现均可直接在仓库源码中查看AlphaMask基于 Sprite 纹理的 alpha 遮罩效果支持channelred/alpha与inverse非 Sprite 遮罩会被自动渲染到纹理。StencilMask基于模板缓冲的 Container/Graphics 遮罩效果includeInBuild/measurable会在挂载时被自动关闭。ScissorMask轴对齐矩形裁剪效果需手动构造未被注册为自动 MaskEffect。ColorMaskRGBA 通道位掩码效果test接受任意number。MaskEffectManager遮罩到 Effect 的转换管理器负责类型测试、实例化与对象池回收。配套实现ColorMaskPipe颜色掩码栈、MaskFilteralpha 遮罩着色器与通道/uniform 定义、effectsMixin.tsmask/setMask/MaskOptions的类型与默认值。小结PixiJS v8 的遮罩体系可以用一句话概括把遮罩对象赋给container.mask引擎自动帮你选择最合适的实现。理解四种遮罩类型的差异Stencil 的形状裁剪、Alpha 的纹理渐变、Color 的通道位掩码、Scissor 的矩形裁剪、掌握setMask的inverse与channel选项、牢记遮罩要放进父级子树、移除要用mask null这两条约定再配合 examples/container_inverse-mask.ts 与 examples/container_alpha-channel-mask.ts 两个可运行示例实践你就能在各种裁剪场景中做出正确且高效的技术选型。【免费下载链接】pixijsThe HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.项目地址: https://gitcode.com/gh_mirrors/pi/pixijs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表