如何使用PixiJS渲染SVG?

22

我正在尝试使用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的bug。您还能看到这种行为吗? - nnyby
“我不清楚你所说的“我的问题是,如果我加载了两个不同的SVG纹理然后渲染它们,第二个会在第一个下面。”这是什么意思?是指您可以透过SVG看到其他内容吗?这是一种透明的SVG吗?您能否添加一个突出显示问题的屏幕截图?” - lucascaro
我不明白为什么你想要将SVG用作纹理。为什么不直接导入SVG内部的.png文件呢?在WebGL中,不存在矢量图像的概念。 - andrevenancio
我认为问题提供的示例使用的是PNG而不是SVG。请查看传递给PIXI.Texture.fromImage()的URL。这些URL以2000px-Gear_icon_svg.svg.png2000px-Love_Heart_SVG.svg.png结尾。这些是PNG文件,而不是SVG文件。因此...无论这里发生了什么行为,我怀疑它与SVG与PNG无关。我也不明白为什么这种行为是错误的。 - mpb
2个回答

17

好的,这个例子看起来运行得非常不错!

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


2
在第86行旁边添加 scale(5) 到 translatez ,看看它是否仍然是矢量图形。 - Tom Siwik
5
这显然会将你的SVG转换成栅格图像。 - sparkyspider

10

我认为你在混淆一些概念。

SVG是一种,WebGL是另一种。 浏览器渲染SVG,您可以按比例缩放它们而不会失去质量/分辨率或任何您想称之为的东西。

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

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

关于您上面的示例,结果是预期的。

您正在加载2个PNG纹理并将它们叠加在一起。


你可以将SVG转换为纹理,但是当你提供给WebGL时,你仍然需要提供一张图片。jpg、png而不是svg。如果这是你的意图,你可以将svg转换为jpg并将该jpg反馈回去。但是,你不能在期望一个图片的地方提供一个svg,也不能提供字符串或其他数据类型并期望它能工作。 - andrevenancio
1
PIXI可以做到这一点,但例如three.js就不行。因此,在幕后,它们将SVG转换为图像。但是GPU不接受SVG,这是我的唯一观点。这是讨论添加该功能的问题。https://github.com/pixijs/pixi.js/issues/4128 - andrevenancio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接