如何用 PixiJS 渲染 SVG?

Posted

技术标签:

【中文标题】如何用 PixiJS 渲染 SVG?【英文标题】:How to render SVG with PixiJS? 【发布时间】:2015-10-21 02:33:02 【问题描述】:

我正在尝试使用 SVG 图像制作游戏,以实现可扩展性并通过程序从它们中制作物理对象(请参阅 matter.js 了解如何)。

我遇到的问题是,如果我加载 2 个不同的 SVG 纹理然后渲染它们,第二个在它下面有第一个分层。

光栅图像不会发生这种情况,画布选项不会发生这种情况,只有 WebGL 会发生这种情况。

有没有办法阻止这种情况,还是我做错了 SVG?

var renderer = PIXI.autoDetectRenderer(
    window.innerWidth, 
    window.innerHeight, 
    
        backgroundColor : 0xffffff,
        resolution:2
    
);

// add viewport and fix resolution doubling
document.body.appendChild(renderer.view);
renderer.view.style.width = "100%";
renderer.view.style.height = "100%";

var stage = new PIXI.Container();

//load gear svg
var texture = PIXI.Texture.fromImage('https://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Gear_icon_svg.svg/2000px-Gear_icon_svg.svg.png');
var gear = new PIXI.Sprite(texture);

//position and scale
gear.scale = x:0.1,y:0.1;
gear.position = x:window.innerWidth / 2,y:window.innerHeight / 2;
gear.anchor = x:0.5,y:0.5;

//load heart svg
var texture2 = PIXI.Texture.fromImage('https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/Love_Heart_SVG.svg/2000px-Love_Heart_SVG.svg.png');
var heart = new PIXI.Sprite(texture2);

//position and scale
heart.scale = x:0.1,y:0.1;
heart.position = x:window.innerWidth/4,y:window.innerHeight / 2;
heart.anchor = x:0.5,y:0.5;

//add to stage
stage.addChild(gear);
stage.addChild(heart);

// start animating
animate();
function animate() 
    gear.rotation += 0.05;

    // render the container
    renderer.render(stage);
    requestAnimationFrame(animate);

<script src="https://github.com/pixijs/pixi.js/releases/download/v4.8.2/pixi.min.js"></script>

【问题讨论】:

你找到解决办法了吗? 这听起来像是浏览器和/或 pixi.js 的错误。您是否仍然看到这种行为? 不清楚你的意思是“我遇到的问题是如果我加载 2 个不同的 SVG 纹理然后渲染它们,第二个在它下面有第一个分层。”你能看穿你的svg吗?它是透明的svg吗?你能添加一个突出显示问题的屏幕截图吗? 我不明白你为什么要使用 SVG 作为纹理。为什么不直接导入该 SVG 内部的 .png 呢?在 WebGL 中没有矢量图像的概念。 我相信问题提供的示例是使用 PNG,而不是 SVG。查看传递给 PIXI.Texture.fromImage() 的 URL。 URL 以2000px-Gear_icon_svg.svg.png2000px-Love_Heart_SVG.svg.png 结尾。这些是 PNG 文件,而不是 SVG 文件。所以......无论这里发生什么行为,我怀疑它与 SVG 与 PNG 无关。我也不明白为什么行为不正确。 【参考方案1】:

所以我认为你有点混淆了概念。

SVG 是一回事,WebGL 是另一回事。 SVG 由浏览器渲染,您可以放大或缩小它们,而不会损失质量/分辨率或任何您想要调用的内容。

然而,这个特性在 WebGL 中是不可能的,因为 WebGL 会光栅化图像。有点像截取屏幕截图并将其放在 Photoshop 上的图层中。您可以操作该图像,但如果不开始查看像素,您将无法对其进行缩放。

简短的回答是,您不能在 WebGL 中使用 SVG,希望让您的图形“缩放”。

关于你上面的例子,结果是预期的。

您正在加载 2 个 png 纹理并覆盖它们。

【讨论】:

您可以将 SVG 转换为纹理,但是当您提供给 WebGL 时,您仍然提供的是图像。 jpg,png不是svg。如果那是您的重点,是的,您可以将 svg 转换为 jpg 并将该 jpg 反馈回来。但是您不能在需要图像的地方提供 svg。也不是字符串或其他数据类型,并期望它能够工作 PIXI 可以做到这一点,但例如 three.js 不能。因此,他们在幕后将 SVG 转换为图像。但是 GPU 不接受 svgs,这是我唯一的观点。这是讨论添加功能的问题。 github.com/pixijs/pixi.js/issues/4128【参考方案2】:

嗯,这个例子似乎运行得很好!

var beeSvg = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/106114/bee.svg";
beeTexture = new PIXI.Texture.fromImage(beeSvg, undefined, undefined, 1.0);
var bee = new PIXI.Sprite(beeTexture)

查看更多信息:https://codepen.io/osublake/pen/ORJjGj

【讨论】:

在 translatez 旁边的第 86 行添加 scale(5) 看看它是否仍然是矢量图形 这显然会将您的 SVG 渲染为光栅。

以上是关于如何用 PixiJS 渲染 SVG?的主要内容,如果未能解决你的问题,请参考以下文章

PixiJS - HTML5 创作引擎

PIXIJS性能优化之图集加载

实践解析 | 如何用 OpenGL 实现跨平台应用高效渲染

ubuntu如何用Intel集成显卡渲染桌面,NV卡做计算

如何用OpenGL ES 2.0渲染一个透明surface

如何用模板渲染后台返回不确定的data