2017-08-28 165 views
0

我试图用three.js创建一个配置器,但即时点我需要改变产品的颜色dinamycally,我虽然那我可以使用SVG作为纹理,改变SVG的填充性能,轻松地更新纹理,但我不是有很好的效果动态更改svg的颜色并将其作为纹理应用于three.js

此刻我有什么是

-A 3D模型与应用为SVG纹理与TextureLoader,但svg被放置在一个外部文件(“images/texture.svg”)(也three.js减少纹理的大小,但我认为它的映射问题)

-The SVG是在层分离,这样我就可以手动更改颜色,并将其应用于

但是我试图使它的动态,你选择一种颜色,它会自动更新应用纹理

任何SVG的想法?

谢谢!

回答

2

我指派别人的小提琴来展示解决方案。我添加了一个修改SVG并在模型上重绘材质的点击功能。

参见例子http://jsfiddle.net/L4pepnj7/

点击任意位置更改SVG圆的颜色。

将SVG转换为encodedURI的操作需要密集处理以保持常量循环,但您可以在渲染器自己做事情时将颜色更改置于点击事件中。我在现有的小提琴中添加了一个名为“clickBody”的函数,该函数改变了其中一个SVG元素的颜色。

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"); 
var material; 
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); 
    material = new THREE.MeshBasicMaterial({ 
     map: texture 
    }); 
    material.map.minFilter = THREE.LinearFilter; 
    mesh = new THREE.Mesh(geometry, material); 
    scene.add(mesh); 
}; 



var colors = ["red", "orange", "yellow", "green", "blue"]; 


var c = 0; 

function clickBody() { 
    document.getElementById("test").setAttribute("fill", colors[c]); 
    var svgData = (new XMLSerializer()).serializeToString(svg); 
    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); 
     material.map = texture; 
     material.map.needsUpdate = true; 
     renderer.render(scene, camera); 
    } 
    c = c + 1; 
    if (c == colors.length) { 
     c = 0; 
    } 
} 
document.body.addEventListener("click", clickBody) 

var render = function() { 
    requestAnimationFrame(render); 
    mesh.rotation.y += 0.01; 
    renderer.render(scene, camera); 
}; 


render(); 
+0

所以基本上这是什么代码正在做的是使更新后的纹理只在clickevent?请问SVG的大小会影响到UV贴图或比例?我的意思是,一个为800x800 SVG质地会在相同的UV纹理空间比300x300? –

+0

@robertgarcia是的。所以在你的情况下,你有一个产品配置器来改变3D模型的图形。在这种情况下,如果SVG通过单独的UI更新,例如通过[svg-edit](https://github.com/SVG-Edit/svgedit)启用,则可以触发代码将svg重新绘制为编码uri,并将其设置为材质的新纹理。 – Radio

+0

好吧,关键并不是要改变图形,只需加载一个3D模型,并且您可以选择不同的设计(SVG中的纹理),一旦您拥有了您想要的图形,就可以使用您的图形更改纹理的SVG属性例如,使用颜色选择器界面,所以你的技巧,谢谢! –