如何在three.js中加载和显示SVG图形? [英] How do you load and display SVG graphics in three.js?
问题描述
考虑一下,我有一个SVG矢量图形文件(徽标),我想将其加载并显示在three.js(使用WebGL渲染器)中.
Consider, I have an SVG vector graphics file (logotype), which I want to load and display in three.js (with WebGL renderer).
推荐使用哪种方法?
似乎我需要加载图像并从中创建几何图形和网格.
It seems like I need to load the image and to create a geometry and a mesh from it.
我已经成功地使用THREE.SVGLoader
加载了SVG文档,但是我无法找到有关如何从其下边创建几何/网格的任何相关信息.
I've managed to load the SVG document using the THREE.SVGLoader
, but I can't find any relevant information on how to create a geometry/mesh from it further down the line.
function preload () {
const svgLoader = new THREE.SVGLoader();
svgLoader.load('images/logo.svg', svgDocument => {
// @todo: create a geometry/mesh from svgDocument?
// @todo: scene.add(logoMesh);
});
}
推荐答案
纹理
如果仅出于纹理目的需要svg:
Texture
If you need svg only for texture purposes:
- 将svg图像渲染到画布上
- 使用该画布作为纹理来源
- 在场景中使用纹理...
免责声明我不是该代码的作者,我只是修正了 jsfiddle 我找到了
Disclaimer I'm not the author of this code, I just fixed jsfiddle that I've found
window.onload = () => {
var mesh;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, 500 / 400, 0.1, 1000);
camera.position.z = 10;
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(500, 400);
document.body.appendChild(renderer.domElement);
var svg = document.getElementById("svgContainer").querySelector("svg");
var svgData = (new XMLSerializer()).serializeToString(svg);
var canvas = document.createElement("canvas");
var svgSize = svg.getBoundingClientRect();
canvas.width = svgSize.width;
canvas.height = svgSize.height;
var ctx = canvas.getContext("2d");
var img = document.createElement("img");
img.setAttribute("src", "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(svgData))) );
img.onload = function() {
ctx.drawImage(img, 0, 0);
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
var geometry = new THREE.SphereGeometry(3, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
var material = new THREE.MeshBasicMaterial({ map: texture });
material.map.minFilter = THREE.LinearFilter;
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
};
var render = function () {
requestAnimationFrame(render);
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
};
render();
}
<script src="https://threejs.org/build/three.min.js"></script>
<div id="svgContainer" style="width: 222px; height: 222px;">
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect width="200" height="200" fill="lime" stroke-width="4" stroke="pink" />
<circle cx="125" cy="125" r="75" fill="orange" />
<polyline points="50,150 50,200 200,200 200,100" stroke="red" stroke-width="4" fill="none" />
<line x1="50" y1="50" x2="200" y2="200" stroke="blue" stroke-width="4" />
</svg>
</div>
如果您想将svg渲染为几何图形,我会建议使用某些库,例如 svg-mesh-3d
If you would like to render svg as geometry I'll would suggest use of some libraries e.g. svg-mesh-3d
svg-mesh-3d文档的示例
Example from docs of svg-mesh-3d
var loadSvg = require('load-svg')
var parsePath = require('extract-svg-path').parse
var svgMesh3d = require('svg-mesh-3d')
loadSvg('svg/logo.svg', function (err, svg) {
if (err) throw err
var svgPath = parsePath(svg)
var mesh = svgMesh3d(svgPath, {
delaunay: false,
scale: 4
})
})
搅拌器
替代方法是使用Blender导入svg,(可选)调整几何形状,并使用 查看全文