简体   繁体   English

动态更改 svg 的颜色并在three.js 中作为纹理应用

[英]Change color of an svg dynamically and apply as texture in three.js

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我正在尝试使用three.js创建一个配置器,但我需要改变产品的颜色,虽然我可以使用svg作为纹理,更改svg的填充属性并更新纹理很容易,但我没有很好的结果

at the moment what i have is目前我所拥有的是

-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 的 3D 模型,但 svg 放置在外部文件中(“images/texture.svg”)(也是 Three.js 正在减小纹理的大小,但我认为它是一个映射问题)

-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

Any ideas?有任何想法吗?

Thanks!谢谢!

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.我添加了一个点击功能,可以修改 SVG 并在模型上重新绘制材质。

See http://jsfiddle.net/L4pepnj7/http://jsfiddle.net/L4pepnj7/

Click anywhere on the example to change the color of the circle in the SVG.单击示例上的任意位置以更改 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.将 SVG 转换为 encodingURI 的操作在一个恒定循环中是密集的,但是您可以在渲染器做自己的事情时将颜色更改放在单击事件中。 I added a function called "clickBody" to the existing fiddle which changes the color of one of the SVG elements.我在现有的小提琴中添加了一个名为“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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM