动态更改svg的颜色并在three.js中应用为纹理 [英] Change color of an svg dynamically and apply as texture in three.js
问题描述
我正在尝试使用three.js创建一个配置器,但即时通讯我需要更改dinamycally产品的颜色,我虽然我可以使用svg作为纹理,更改svg的填充属性并且很容易更新纹理,但我没有取得好成绩
i´m trying to create a configurator with three.js but im at the point that i need to change the color of the product dinamycally, i though that i can use an svg as texture, change the fill property of the svg and update the texture easily, but im not having good results
目前我所拥有的是
- 带有svg的3D模型作为纹理应用于TextureLoader,但是svg被放置在外部文件中(images / texture.svg)(也是three.js正在减小纹理的大小,但我认为它是一个映射问题)
-A 3D model with an svg applied as texture with a TextureLoader, but the svg is placed in a external file ("images/texture.svg")(also three.js is reducing the size of the texture, but i think its a mapping problem)
- svg在图层中分开,所以我可以手动更改颜色并应用它
-The svg is separated in layers, so i can manually change the color and apply it
但是我试图让它变得动态,你选择一种颜色并自动更新应用为纹理的svg
But im trying to make it dynamic, you choose a color and it automatically updates the svg applied as texture
任何想法?
谢谢!
推荐答案
我分道别人的小提琴来展示解决方案。我添加了一个单击功能,可以修改SVG并重新绘制模型上的材质。
I forked someone else's fiddle to show the solution. I added a click function which modifies the SVG and redraws the material on the model.
参见 http://jsfiddle.net/L4pepnj7/
单击示例中的任意位置以更改SVG中圆圈的颜色。
Click anywhere on the example to change the color of the circle in the SVG.
将SVG转换为encodedURI的操作是密集的,以便在一个常量循环中,但是你可以在渲染器处于点击事件时将颜色变化放入做它自己的事情。我在现有小提琴中添加了一个名为clickBody的函数,它改变了其中一个SVG元素的颜色。
The operation which converts the SVG to an encodedURI is to intensive to have in a constant loop, but you can put the color change in a click event while the renderer is doing it's own thing. I added a function called "clickBody" to the existing fiddle which changes the color of one of the SVG elements.
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();
这篇关于动态更改svg的颜色并在three.js中应用为纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!