three.js 3d 空间中的 .svg 资产
Posted
技术标签:
【中文标题】three.js 3d 空间中的 .svg 资产【英文标题】:.svg asset in three.js 3d space 【发布时间】:2018-03-25 01:30:16 【问题描述】:我正在尝试将.svg
资产加载到我的three.js 场景中,作为平面矢量图层;我在另一篇文章中找到了这个带有SVGLoader
和SVGRenderer
的示例,但我无法让它工作。
加载的 svg 卡在 2d 空间中并且没有响应相机的移动,我无法访问它的位置。
我尝试切换到WebGLRenderer
,但没有加载 svg。
将其加载为精灵的选项会很好,但我希望精灵不要面对相机并保持在 3d 空间中。
var svgManager = new THREE.SVGLoader();
var url = 'https://upload.wikimedia.org/wikipedia/commons/f/f7/Europe_laea_location_map.svg';
function svg_loading_done_callback(doc)
init();
svg(new THREE.SVGObject(doc));
ico();
animate();
;
svgManager.load(url,
svg_loading_done_callback,
function()
console.log("Loading SVG...");
,
function()
console.log("Error loading SVG!");
);
var AMOUNT = 100;
var container, camera, scene, renderer;
function init()
scene = new THREE.Scene();
renderer = new THREE.SVGRenderer();
renderer.setClearColor(0x00ff00);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
var container = document.getElementById('container');
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1100;
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableZoom = true;
window.addEventListener('resize', onWindowResize, false);
function svg(svgObject)
svgObject.position.x = 510;
svgObject.position.y = -110;
svgObject.position.z = 0;
scene.add(svgObject);
function ico()
geometry = new THREE.IcosahedronGeometry(100, 1)
material = new THREE.MeshNormalMaterial();
ico = new THREE.Mesh(geometry, material);
ico.position.y = -300;
scene.add(ico);
ico2 = new THREE.Mesh(geometry, material);
ico2.position.y = 500;
ico2.position.x = -500;
ico2.position.z = -50;
scene.add(ico2);
function onWindowResize()
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
function animate()
requestAnimationFrame(animate);
controls.update;
render();
function render()
renderer.render(scene, camera);
body
margin: 0;
canvas
width: 100%;
height: 100%
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<div id="container"></div>
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/renderers/SVGRenderer.js"></script>
<script src="https://threejs.org/examples/js/renderers/Projector.js"></script>
<script src="https://threejs.org/examples/js/loaders/SVGLoader.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
【问题讨论】:
对此有何想法? 【参考方案1】:SVGLoader
和 SVGRenderer
是两个不同的东西。第一个加载一个 SVG 文件并将其转换为 three.js 形状(尽管有一些限制,即可以读取非常简单的 SVG,不渲染笔触而只渲染填充对象等),而后者使用 SVG 元素渲染三个.js 原语而不是 WebGL。从某种意义上说,它们是相互对立的。
因此,首先,您需要为您的案例使用WebGLRenderer
。
然后,您需要更改 SVG 加载回调。它接收一组路径,您可以使用这些路径来渲染 SVG。
查看svg_loading_done_callback
、init
和svg
函数的变化,并在JSFiddle中运行:
var svgManager = new THREE.SVGLoader();
var url = 'https://upload.wikimedia.org/wikipedia/commons/f/f7/Europe_laea_location_map.svg';
function svg_loading_done_callback(paths)
init();
svg(paths);
ico();
animate();
;
svgManager.load(url,
svg_loading_done_callback,
function()
console.log("Loading SVG...");
,
function()
console.log("Error loading SVG!");
);
var AMOUNT = 100;
var container, camera, scene, renderer;
function init()
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x00ff00);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
var container = document.getElementById('container');
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1100;
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableZoom = true;
window.addEventListener('resize', onWindowResize, false);
function svg(paths)
var group = new THREE.Group();
group.position.x = 510;
group.position.y = -110;
group.position.z = 0;
for ( var i = 0; i < paths.length; i ++ )
var path = paths[ i ];
var material = new THREE.MeshBasicMaterial(
color: path.color,
side: THREE.DoubleSide,
depthWrite: false
);
var shapes = path.toShapes( true );
for ( var j = 0; j < shapes.length; j ++ )
var shape = shapes[ j ];
var geometry = new THREE.ShapeBufferGeometry( shape );
var mesh = new THREE.Mesh( geometry, material );
group.add( mesh );
scene.add( group );
function ico()
geometry = new THREE.IcosahedronGeometry(100, 1)
material = new THREE.MeshNormalMaterial();
ico = new THREE.Mesh(geometry, material);
ico.position.y = -300;
scene.add(ico);
ico2 = new THREE.Mesh(geometry, material);
ico2.position.y = 500;
ico2.position.x = -500;
ico2.position.z = -50;
scene.add(ico2);
function onWindowResize()
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
function animate()
requestAnimationFrame(animate);
controls.update;
render();
function render()
renderer.render(scene, camera);
PS:检查SVG Loader 看看它能解析什么
【讨论】:
谢谢,我有一个不使用 svg 资产的解决方法。下次需要的时候我会回来的!以上是关于three.js 3d 空间中的 .svg 资产的主要内容,如果未能解决你的问题,请参考以下文章