问题
I'm trying to use SVGRenderer
in three.js (http://threejs.org/examples/#svg_sandbox). The example shows you how to make an SVG element (a circle) on the fly. I want to import an SVG file that I already have in my computer. How would I do that?
The createElementNS command doesn't seem to support importing SVG files?
I essentially want my image.svg
to be displayed on a three.js scene.
回答1:
You can use the THREE.SVGLoader() Library to achieve it :
var svgManager = new THREE.LegacySVGLoader();
var url = 'https://upload.wikimedia.org/wikipedia/commons/b/b0/NewTux.svg';
function svg_loading_done_callback(doc) {
init(new THREE.SVGObject(doc));
animate();
};
svgManager.load(url,
svg_loading_done_callback,
function() {
console.log("Loading SVG...");
},
function() {
console.log("Error loading SVG!");
});
var camera, scene, renderer;
function init(svgObject) {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100000);
camera.position.z = 1500;
svgObject.position.x = Math.random() * innerWidth;
svgObject.position.y = 200;
svgObject.position.z = Math.random() * 10000 - 5000;
svgObject.scale.x = svgObject.scale.y = svgObject.scale.z = 0.01;
scene = new THREE.Scene();
scene.add(svgObject);
var ambient = new THREE.AmbientLight(0x80ffff);
scene.add(ambient);
var directional = new THREE.DirectionalLight(0xffff00);
directional.position.set(-1, 0.5, 0);
scene.add(directional);
renderer = new THREE.SVGRenderer();
renderer.setClearColor(0xf0f0f0);
renderer.setSize(window.innerWidth, window.innerHeight - 5);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
var time = Date.now() * 0.0002;
camera.position.x = Math.sin(time) * 200;
camera.position.z = Math.cos(time) * 200;
camera.lookAt(scene.position);
renderer.render(scene, camera);
}
* {
margin: 0
}
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/renderers/SVGRenderer.js"></script>
<script src="http://threejs.org/examples/js/renderers/Projector.js"></script>
<script src="http://threejs.org/examples/js/loaders/SVGLoader.js"></script>
<script>
/**
* @name LegacySVGLoader
* @author mrdoob / http://mrdoob.com/
* @author zz85 / http://joshuakoo.com/
* @see https://github.com/mrdoob/three.js/issues/14387
*/
THREE.LegacySVGLoader = function(manager) {
this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
};
THREE.LegacySVGLoader.prototype = {
constructor: THREE.LegacySVGLoader,
load: function(url, onLoad, onProgress, onError) {
var scope = this;
var parser = new DOMParser();
var loader = new THREE.FileLoader(scope.manager);
loader.load(url, function(svgString) {
var doc = parser.parseFromString(svgString, 'image/svg+xml'); // application/xml
onLoad(doc.documentElement);
}, onProgress, onError);
}
};
</script>
回答2:
This is current answer from latest three.js lib:
https://threejs.org/examples/?q=svg#webgl_loader_svg
but this code loads svg into geometry mesh, so it is not a DOM element, it zooms out just like any other 3d object. Its like a billboard in 3d scene. If someone needs this kind of behavior then its fine.
If you want to load SVG to be DOM element, to have it float over 3D scene, to be able to add mouse click and hover events... I asked for example and here it is:
https://github.com/mrdoob/three.js/issues/15528
来源:https://stackoverflow.com/questions/33140342/how-to-load-svg-file-into-svgrenderer-in-three-js